@@ -57,88 +57,82 @@ public class RetrievedFromCacheScanRule extends PluginPassiveScanner
57
57
@ Override
58
58
public void scanHttpResponseReceive (HttpMessage msg , int id , Source source ) {
59
59
60
- try {
61
- LOGGER .debug (
62
- "Checking URL {} to see if was served from a shared cache" ,
63
- msg .getRequestHeader ().getURI ());
64
-
65
- // X-Cache: HIT
66
- // X-Cache: HIT from cache.kolich.local <-- was the data actually served from the
67
- // cache (subject to no-cache, expiry, etc.)?
68
- // (if X-Cache: HIT, it implies X-Cache-Lookup: HIT)
69
- // (and if X-Cache-Lookup: MISS, it implies X-Cache: MISS)
70
- // X-Cache-Lookup: HIT from cache.kolich.local:80 <-- was the data *available* in the
71
- // cache? (not whether it was actually served)
72
-
73
- // X-Cache: MISS
74
- // X-Cache: MISS from cache.kolich.local
75
- // X-Cache-Lookup: MISS from cache.kolich.local:80
76
-
77
- // X-Cache HIT from proxy.domain.tld, MISS from proxy.local
78
- // X-Cache-Lookup HIT from proxy.domain.tld:3128, MISS from proxy.local:3128
79
-
80
- List <String > xcacheHeaders = msg .getResponseHeader ().getHeaderValues ("X-Cache" );
81
- if (!xcacheHeaders .isEmpty ()) {
82
- for (String xcacheHeader : xcacheHeaders ) {
83
- for (String proxyServerDetails : xcacheHeader .split ("," )) {
84
- // strip off any leading space for the second and subsequent proxies
85
- if (proxyServerDetails .startsWith (" " ))
86
- proxyServerDetails = proxyServerDetails .substring (1 );
87
- LOGGER .trace ("Proxy HIT/MISS details [{}]" , proxyServerDetails );
88
- String [] proxyServerDetailsArray = proxyServerDetails .split (" " , 3 );
89
- if (proxyServerDetailsArray .length >= 1 ) {
90
- String hitormiss =
91
- proxyServerDetailsArray [0 ].toUpperCase (); // HIT or MISS
92
- if (hitormiss .equals ("HIT" )) {
93
- // the response was served from cache, so raise it..
94
- String evidence = proxyServerDetails ;
95
- LOGGER .debug (
96
- "{} was served from a cache, due to presence of a 'HIT' in the 'X-Cache' response header" ,
97
- msg .getRequestHeader ().getURI ());
98
- // could be from HTTP/1.0 or HTTP/1.1. We don't know which.
99
- buildAlert (evidence , false ).raise ();
100
- return ;
101
- }
60
+ LOGGER .debug (
61
+ "Checking URL {} to see if was served from a shared cache" ,
62
+ msg .getRequestHeader ().getURI ());
63
+
64
+ // X-Cache: HIT
65
+ // X-Cache: HIT from cache.kolich.local <-- was the data actually served from the
66
+ // cache (subject to no-cache, expiry, etc.)?
67
+ // (if X-Cache: HIT, it implies X-Cache-Lookup: HIT)
68
+ // (and if X-Cache-Lookup: MISS, it implies X-Cache: MISS)
69
+ // X-Cache-Lookup: HIT from cache.kolich.local:80 <-- was the data *available* in the
70
+ // cache? (not whether it was actually served)
71
+
72
+ // X-Cache: MISS
73
+ // X-Cache: MISS from cache.kolich.local
74
+ // X-Cache-Lookup: MISS from cache.kolich.local:80
75
+
76
+ // X-Cache HIT from proxy.domain.tld, MISS from proxy.local
77
+ // X-Cache-Lookup HIT from proxy.domain.tld:3128, MISS from proxy.local:3128
78
+
79
+ List <String > xcacheHeaders = msg .getResponseHeader ().getHeaderValues ("X-Cache" );
80
+ if (!xcacheHeaders .isEmpty ()) {
81
+ for (String xcacheHeader : xcacheHeaders ) {
82
+ for (String proxyServerDetails : xcacheHeader .split ("," )) {
83
+ // strip off any leading space for the second and subsequent proxies
84
+ if (proxyServerDetails .startsWith (" " ))
85
+ proxyServerDetails = proxyServerDetails .substring (1 );
86
+ LOGGER .trace ("Proxy HIT/MISS details [{}]" , proxyServerDetails );
87
+ String [] proxyServerDetailsArray = proxyServerDetails .split (" " , 3 );
88
+ if (proxyServerDetailsArray .length >= 1 ) {
89
+ String hitormiss = proxyServerDetailsArray [0 ].toUpperCase (); // HIT or MISS
90
+ if (hitormiss .equals ("HIT" )) {
91
+ // the response was served from cache, so raise it..
92
+ String evidence = proxyServerDetails ;
93
+ LOGGER .debug (
94
+ "{} was served from a cache, due to presence of a 'HIT' in the 'X-Cache' response header" ,
95
+ msg .getRequestHeader ().getURI ());
96
+ // could be from HTTP/1.0 or HTTP/1.1. We don't know which.
97
+ buildAlert (evidence , false ).raise ();
98
+ return ;
102
99
}
103
100
}
104
101
}
105
102
}
103
+ }
106
104
107
- // The "Age" header (defined in RFC 7234) conveys the sender's estimate of the amount of
108
- // time since the response (or its revalidation) was generated at the origin server.
109
- // An HTTP/1.1 server that includes a cache MUST include an Age header field in every
110
- // response generated from its own cache.
111
- // i.e.: a valid "Age" header implies that the response was served from a cache
112
- // lets validate that it is actually a non-negative decimal integer, as mandated by RFC
113
- // 7234, however.
114
- // if there are multiple "Age" headers, just look for one valid value in the multiple
115
- // "Age" headers.. Not sure if this case is strictly valid with the spec, however.
116
- // Note: HTTP/1.0 caches do not implement "Age", so the absence of an "Age" header does
117
- // *not* imply that the response was served from the origin server, rather than a
118
- // cache..
119
- List <String > ageHeaders = msg .getResponseHeader ().getHeaderValues ("Age" );
120
- if (!ageHeaders .isEmpty ()) {
121
- for (String ageHeader : ageHeaders ) {
122
- LOGGER .trace ("Validating Age header value [{}]" , ageHeader );
123
- Long ageAsLong = null ;
124
- try {
125
- ageAsLong = Long .parseLong (ageHeader );
126
- } catch (NumberFormatException nfe ) {
127
- // Ignore
128
- }
129
- if (ageAsLong != null && ageAsLong >= 0 ) {
130
- String evidence = "Age: " + ageHeader ;
131
- LOGGER .debug (
132
- "{} was served from a HTTP/1.1 cache, due to presence of a valid (non-negative decimal integer) 'Age' response header value" ,
133
- msg .getRequestHeader ().getURI ());
134
- buildAlert (evidence , true ).raise ();
135
- return ;
136
- }
105
+ // The "Age" header (defined in RFC 7234) conveys the sender's estimate of the amount of
106
+ // time since the response (or its revalidation) was generated at the origin server.
107
+ // An HTTP/1.1 server that includes a cache MUST include an Age header field in every
108
+ // response generated from its own cache.
109
+ // i.e.: a valid "Age" header implies that the response was served from a cache
110
+ // lets validate that it is actually a non-negative decimal integer, as mandated by RFC
111
+ // 7234, however.
112
+ // if there are multiple "Age" headers, just look for one valid value in the multiple
113
+ // "Age" headers.. Not sure if this case is strictly valid with the spec, however.
114
+ // Note: HTTP/1.0 caches do not implement "Age", so the absence of an "Age" header does
115
+ // *not* imply that the response was served from the origin server, rather than a
116
+ // cache..
117
+ List <String > ageHeaders = msg .getResponseHeader ().getHeaderValues ("Age" );
118
+ if (!ageHeaders .isEmpty ()) {
119
+ for (String ageHeader : ageHeaders ) {
120
+ LOGGER .trace ("Validating Age header value [{}]" , ageHeader );
121
+ Long ageAsLong = null ;
122
+ try {
123
+ ageAsLong = Long .parseLong (ageHeader );
124
+ } catch (NumberFormatException nfe ) {
125
+ // Ignore
126
+ }
127
+ if (ageAsLong != null && ageAsLong >= 0 ) {
128
+ String evidence = "Age: " + ageHeader ;
129
+ LOGGER .debug (
130
+ "{} was served from a HTTP/1.1 cache, due to presence of a valid (non-negative decimal integer) 'Age' response header value" ,
131
+ msg .getRequestHeader ().getURI ());
132
+ buildAlert (evidence , true ).raise ();
133
+ return ;
137
134
}
138
135
}
139
-
140
- } catch (Exception e ) {
141
- LOGGER .error ("An error occurred while checking if a URL was served from a cache" , e );
142
136
}
143
137
}
144
138
0 commit comments