@@ -83,7 +83,8 @@ public class PathTraversalScanRule extends AbstractAppParamPlugin
8383 * Windows local file targets and detection pattern
8484 */
8585 private static final ContentsMatcher WIN_PATTERN =
86- new PatternContentsMatcher (Pattern .compile ("\\ [drivers\\ ]" ));
86+ new PatternContentsMatcher (Pattern .compile ("\\ [drivers\\ ]" ), Tech .Windows );
87+ private static final String WIN_DIR_EVIDENCE = "Windows" ;
8788 private static final String [] WIN_LOCAL_FILE_TARGETS = {
8889 // Absolute Windows file retrieval (we suppose C:\\)
8990 "c:/Windows/system.ini" ,
@@ -132,7 +133,8 @@ public class PathTraversalScanRule extends AbstractAppParamPlugin
132133 */
133134 // Dot used to match 'x' or '!' (used in AIX)
134135 private static final ContentsMatcher NIX_PATTERN =
135- new PatternContentsMatcher (Pattern .compile ("root:.:0:0" ));
136+ new PatternContentsMatcher (Pattern .compile ("root:.:0:0" ), Tech .Linux );
137+ private static final String NIX_DIR_EVIDENCE = "etc" ;
136138 private static final String [] NIX_LOCAL_FILE_TARGETS = {
137139 // Absolute file retrieval
138140 "/etc/passwd" ,
@@ -158,10 +160,9 @@ public class PathTraversalScanRule extends AbstractAppParamPlugin
158160 // ..%252F..%252F..%252F..%252F..%252F..%252F..%252F..%252F..%252F..%252Fetc%252Fpasswd%2500.jpg
159161 };
160162
161- /*
162- * Windows/Unix/Linux/etc. local directory targets and detection pattern
163- */
164- private static final ContentsMatcher DIR_PATTERN = new DirNamesContentsMatcher ();
163+ private static final ContentsMatcher NIX_DIR_MATCHER = new DirNamesContentsMatcher (Tech .Linux );
164+ private static final ContentsMatcher WIN_DIR_MATCHER =
165+ new DirNamesContentsMatcher (Tech .Windows );
165166 private static final String [] WIN_LOCAL_DIR_TARGETS = {
166167 "c:/" ,
167168 "c:\\ " ,
@@ -183,17 +184,19 @@ public class PathTraversalScanRule extends AbstractAppParamPlugin
183184 "/" ,
184185 "../../../../../../../../../../../../../../../../" ,
185186 "/../../../../../../../../../../../../../../../../" ,
186- "file:///" ,
187+ "file:///"
187188 };
188189
189190 private static final ContentsMatcher WAR_PATTERN =
190- new PatternContentsMatcher (Pattern .compile ("</web-app>" ));
191+ new PatternContentsMatcher (Pattern .compile ("</web-app>" ), Tech . Tomcat );
191192
192193 /*
193194 * Standard local file prefixes
194195 */
195196 private static final String [] LOCAL_FILE_RELATIVE_PREFIXES = {"" , "/" , "\\ " };
196197
198+ private static final List <String > DIR_EVIDENCE_LIST =
199+ List .of (NIX_DIR_EVIDENCE , WIN_DIR_EVIDENCE );
197200 /*
198201 * details of the vulnerability which we are attempting to find
199202 */
@@ -389,7 +392,7 @@ public void scan(HttpMessage msg, String param, String value) {
389392
390393 // Check if a there was a finding or the scan has been stopped
391394 // if yes dispose resources and exit
392- if (sendAndCheckPayload (param , NIX_LOCAL_DIR_TARGETS [h ], DIR_PATTERN , 3 )
395+ if (sendAndCheckPayload (param , NIX_LOCAL_DIR_TARGETS [h ], NIX_DIR_MATCHER , 3 )
393396 || isStop ()) {
394397 // Dispose all resources
395398 // Exit the scan rule
@@ -399,7 +402,7 @@ public void scan(HttpMessage msg, String param, String value) {
399402 }
400403 if (inScope (Tech .Windows )) {
401404 for (int h = 0 ; h < winDirCount ; h ++) {
402- if (sendAndCheckPayload (param , WIN_LOCAL_DIR_TARGETS [h ], DIR_PATTERN , 3 )
405+ if (sendAndCheckPayload (param , WIN_LOCAL_DIR_TARGETS [h ], WIN_DIR_MATCHER , 3 )
403406 || isStop ()) {
404407 // Dispose all resources
405408 // Exit the scan rule
@@ -661,12 +664,23 @@ private AlertBuilder createUnmatchedAlert(String param, String attack) {
661664
662665 private AlertBuilder createMatchedAlert (
663666 String param , String attack , String evidence , int check ) {
664- return newAlert ()
665- .setConfidence (Alert .CONFIDENCE_MEDIUM )
666- .setParam (param )
667- .setAttack (attack )
668- .setEvidence (evidence )
669- .setAlertRef (getId () + "-" + check );
667+ AlertBuilder builder =
668+ newAlert ()
669+ .setConfidence (Alert .CONFIDENCE_MEDIUM )
670+ .setParam (param )
671+ .setAttack (attack )
672+ .setEvidence (evidence )
673+ .setAlertRef (getId () + "-" + check );
674+ if (DIR_EVIDENCE_LIST .contains (evidence )) {
675+ builder .setOtherInfo (
676+ Constant .messages .getString (
677+ MESSAGE_PREFIX + "info" ,
678+ evidence ,
679+ evidence .equals (WIN_DIR_EVIDENCE )
680+ ? DirNamesContentsMatcher .WIN_MATCHES
681+ : DirNamesContentsMatcher .NIX_MATCHES ));
682+ }
683+ return builder ;
670684 }
671685
672686 @ Override
@@ -692,7 +706,7 @@ private static class PatternContentsMatcher implements ContentsMatcher {
692706
693707 private final Pattern pattern ;
694708
695- public PatternContentsMatcher (Pattern pattern ) {
709+ public PatternContentsMatcher (Pattern pattern , Tech tech ) {
696710 this .pattern = pattern ;
697711 }
698712
@@ -708,46 +722,61 @@ public String match(String contents) {
708722
709723 private static class DirNamesContentsMatcher implements ContentsMatcher {
710724
725+ private static final String NIX_MATCHES =
726+ String .join (", " , List .of ("proc" , NIX_DIR_EVIDENCE , "boot" , "tmp" , "home" ));
727+ private static final String WIN_MATCHES =
728+ String .join (", " , List .of (WIN_DIR_EVIDENCE , "Program Files" ));
729+ private static final Pattern PROC_PATT =
730+ Pattern .compile (
731+ "(?:^|\\ W)proc(?:\\ W|$)" , Pattern .CASE_INSENSITIVE | Pattern .MULTILINE );
732+ private static final Pattern ETC_PATT =
733+ Pattern .compile (
734+ "(?:^|\\ W)etc(?:\\ W|$)" , Pattern .CASE_INSENSITIVE | Pattern .MULTILINE );
735+ private static final Pattern BOOT_PATT =
736+ Pattern .compile (
737+ "(?:^|\\ W)boot(?:\\ W|$)" , Pattern .CASE_INSENSITIVE | Pattern .MULTILINE );
738+ private static final Pattern TMP_PATT =
739+ Pattern .compile (
740+ "(?:^|\\ W)tmp(?:\\ W|$)" , Pattern .CASE_INSENSITIVE | Pattern .MULTILINE );
741+ private static final Pattern HOME_PATT =
742+ Pattern .compile (
743+ "(?:^|\\ W)home(?:\\ W|$)" , Pattern .CASE_INSENSITIVE | Pattern .MULTILINE );
744+
745+ private Tech tech ;
746+
747+ public DirNamesContentsMatcher (Tech tech ) {
748+ this .tech = tech ;
749+ }
750+
711751 @ Override
712752 public String match (String contents ) {
713- String result = matchNixDirectories (contents );
714- if (result != null ) {
715- return result ;
753+ if (this .tech == Tech .Linux ) {
754+ return matchNixDirectories (contents );
716755 }
717- return matchWinDirectories (contents );
756+ if (this .tech == Tech .Windows ) {
757+ return matchWinDirectories (contents );
758+ }
759+ return null ;
718760 }
719761
720762 private static String matchNixDirectories (String contents ) {
721- Pattern procPattern =
722- Pattern .compile ("(?:^|\\ W)proc(?:\\ W|$)" , Pattern .CASE_INSENSITIVE );
723- Pattern etcPattern = Pattern .compile ("(?:^|\\ W)etc(?:\\ W|$)" , Pattern .CASE_INSENSITIVE );
724- Pattern bootPattern =
725- Pattern .compile ("(?:^|\\ W)boot(?:\\ W|$)" , Pattern .CASE_INSENSITIVE );
726- Pattern tmpPattern = Pattern .compile ("(?:^|\\ W)tmp(?:\\ W|$)" , Pattern .CASE_INSENSITIVE );
727- Pattern homePattern =
728- Pattern .compile ("(?:^|\\ W)home(?:\\ W|$)" , Pattern .CASE_INSENSITIVE );
729-
730- Matcher procMatcher = procPattern .matcher (contents );
731- Matcher etcMatcher = etcPattern .matcher (contents );
732- Matcher bootMatcher = bootPattern .matcher (contents );
733- Matcher tmpMatcher = tmpPattern .matcher (contents );
734- Matcher homeMatcher = homePattern .matcher (contents );
735-
736- if (procMatcher .find ()
737- && etcMatcher .find ()
738- && bootMatcher .find ()
739- && tmpMatcher .find ()
740- && homeMatcher .find ()) {
741- return "etc" ;
763+ if (PROC_PATT .matcher (contents ).find ()
764+ && ETC_PATT .matcher (contents ).find ()
765+ && BOOT_PATT .matcher (contents ).find ()
766+ && TMP_PATT .matcher (contents ).find ()
767+ && HOME_PATT .matcher (contents ).find ()) {
768+ return NIX_DIR_EVIDENCE ;
742769 }
743770
744771 return null ;
745772 }
746773
747774 private static String matchWinDirectories (String contents ) {
748- if (contents .contains ("Windows" )
749- && Pattern .compile ("Program\\ sFiles" ).matcher (contents ).find ()) {
750- return "Windows" ;
775+ if (contents .contains (WIN_DIR_EVIDENCE )
776+ && Pattern .compile ("Program\\ sFiles" , Pattern .CASE_INSENSITIVE )
777+ .matcher (contents )
778+ .find ()) {
779+ return WIN_DIR_EVIDENCE ;
751780 }
752781
753782 return null ;
0 commit comments