@@ -81,7 +81,8 @@ public class PathTraversalScanRule extends AbstractAppParamPlugin
8181 * Windows local file targets and detection pattern
8282 */
8383 private static final ContentsMatcher WIN_PATTERN =
84- new PatternContentsMatcher (Pattern .compile ("\\ [drivers\\ ]" ));
84+ new PatternContentsMatcher (Pattern .compile ("\\ [drivers\\ ]" ), Tech .Windows );
85+ private static final String WIN_DIR_EVIDENCE = "Windows" ;
8586 private static final String [] WIN_LOCAL_FILE_TARGETS = {
8687 // Absolute Windows file retrieval (we suppose C:\\)
8788 "c:/Windows/system.ini" ,
@@ -130,7 +131,8 @@ public class PathTraversalScanRule extends AbstractAppParamPlugin
130131 */
131132 // Dot used to match 'x' or '!' (used in AIX)
132133 private static final ContentsMatcher NIX_PATTERN =
133- new PatternContentsMatcher (Pattern .compile ("root:.:0:0" ));
134+ new PatternContentsMatcher (Pattern .compile ("root:.:0:0" ), Tech .Linux );
135+ private static final String NIX_DIR_EVIDENCE = "etc" ;
134136 private static final String [] NIX_LOCAL_FILE_TARGETS = {
135137 // Absolute file retrieval
136138 "/etc/passwd" ,
@@ -156,10 +158,9 @@ public class PathTraversalScanRule extends AbstractAppParamPlugin
156158 // ..%252F..%252F..%252F..%252F..%252F..%252F..%252F..%252F..%252F..%252Fetc%252Fpasswd%2500.jpg
157159 };
158160
159- /*
160- * Windows/Unix/Linux/etc. local directory targets and detection pattern
161- */
162- private static final ContentsMatcher DIR_PATTERN = new DirNamesContentsMatcher ();
161+ private static final ContentsMatcher NIX_DIR_MATCHER = new DirNamesContentsMatcher (Tech .Linux );
162+ private static final ContentsMatcher WIN_DIR_MATCHER =
163+ new DirNamesContentsMatcher (Tech .Windows );
163164 private static final String [] WIN_LOCAL_DIR_TARGETS = {
164165 "c:/" ,
165166 "c:\\ " ,
@@ -181,17 +182,19 @@ public class PathTraversalScanRule extends AbstractAppParamPlugin
181182 "/" ,
182183 "../../../../../../../../../../../../../../../../" ,
183184 "/../../../../../../../../../../../../../../../../" ,
184- "file:///" ,
185+ "file:///"
185186 };
186187
187188 private static final ContentsMatcher WAR_PATTERN =
188- new PatternContentsMatcher (Pattern .compile ("</web-app>" ));
189+ new PatternContentsMatcher (Pattern .compile ("</web-app>" ), Tech . Tomcat );
189190
190191 /*
191192 * Standard local file prefixes
192193 */
193194 private static final String [] LOCAL_FILE_RELATIVE_PREFIXES = {"" , "/" , "\\ " };
194195
196+ private static final List <String > DIR_EVIDENCE_LIST =
197+ List .of (NIX_DIR_EVIDENCE , WIN_DIR_EVIDENCE );
195198 /*
196199 * details of the vulnerability which we are attempting to find
197200 */
@@ -342,7 +345,6 @@ public void scan(HttpMessage msg, String param, String value) {
342345
343346 // Check 2: Start detection for *NIX patterns
344347 if (inScope (Tech .Linux ) || inScope (Tech .MacOS )) {
345-
346348 for (int h = 0 ; h < nixCount ; h ++) {
347349
348350 // Check if a there was a finding or the scan has been stopped
@@ -384,10 +386,9 @@ public void scan(HttpMessage msg, String param, String value) {
384386 // Check 3: Detect if this page is a directory browsing component
385387 if (inScope (Tech .Linux ) || inScope (Tech .MacOS )) {
386388 for (int h = 0 ; h < nixDirCount ; h ++) {
387-
388389 // Check if a there was a finding or the scan has been stopped
389390 // if yes dispose resources and exit
390- if (sendAndCheckPayload (param , NIX_LOCAL_DIR_TARGETS [h ], DIR_PATTERN , 3 )
391+ if (sendAndCheckPayload (param , NIX_LOCAL_DIR_TARGETS [h ], NIX_DIR_MATCHER , 3 )
391392 || isStop ()) {
392393 // Dispose all resources
393394 // Exit the scan rule
@@ -397,7 +398,7 @@ public void scan(HttpMessage msg, String param, String value) {
397398 }
398399 if (inScope (Tech .Windows )) {
399400 for (int h = 0 ; h < winDirCount ; h ++) {
400- if (sendAndCheckPayload (param , WIN_LOCAL_DIR_TARGETS [h ], DIR_PATTERN , 3 )
401+ if (sendAndCheckPayload (param , WIN_LOCAL_DIR_TARGETS [h ], WIN_DIR_MATCHER , 3 )
401402 || isStop ()) {
402403 // Dispose all resources
403404 // Exit the scan rule
@@ -659,12 +660,23 @@ private AlertBuilder createUnmatchedAlert(String param, String attack) {
659660
660661 private AlertBuilder createMatchedAlert (
661662 String param , String attack , String evidence , int check ) {
662- return newAlert ()
663- .setConfidence (Alert .CONFIDENCE_MEDIUM )
664- .setParam (param )
665- .setAttack (attack )
666- .setEvidence (evidence )
667- .setAlertRef (getId () + "-" + check );
663+ AlertBuilder builder =
664+ newAlert ()
665+ .setConfidence (Alert .CONFIDENCE_MEDIUM )
666+ .setParam (param )
667+ .setAttack (attack )
668+ .setEvidence (evidence )
669+ .setAlertRef (getId () + "-" + check );
670+ if (DIR_EVIDENCE_LIST .contains (evidence )) {
671+ builder .setOtherInfo (
672+ Constant .messages .getString (
673+ MESSAGE_PREFIX + "info" ,
674+ evidence ,
675+ evidence .equals (WIN_DIR_EVIDENCE )
676+ ? DirNamesContentsMatcher .WIN_MATCHES
677+ : DirNamesContentsMatcher .NIX_MATCHES ));
678+ }
679+ return builder ;
668680 }
669681
670682 @ Override
@@ -690,7 +702,7 @@ private static class PatternContentsMatcher implements ContentsMatcher {
690702
691703 private final Pattern pattern ;
692704
693- public PatternContentsMatcher (Pattern pattern ) {
705+ public PatternContentsMatcher (Pattern pattern , Tech tech ) {
694706 this .pattern = pattern ;
695707 }
696708
@@ -706,46 +718,61 @@ public String match(String contents) {
706718
707719 private static class DirNamesContentsMatcher implements ContentsMatcher {
708720
721+ private static final String NIX_MATCHES =
722+ String .join (", " , List .of ("proc" , NIX_DIR_EVIDENCE , "boot" , "tmp" , "home" ));
723+ private static final String WIN_MATCHES =
724+ String .join (", " , List .of (WIN_DIR_EVIDENCE , "Program Files" ));
725+ private static final Pattern PROC_PATT =
726+ Pattern .compile (
727+ "(?:^|\\ W)proc(?:\\ W|$)" , Pattern .CASE_INSENSITIVE | Pattern .MULTILINE );
728+ private static final Pattern ETC_PATT =
729+ Pattern .compile (
730+ "(?:^|\\ W)etc(?:\\ W|$)" , Pattern .CASE_INSENSITIVE | Pattern .MULTILINE );
731+ private static final Pattern BOOT_PATT =
732+ Pattern .compile (
733+ "(?:^|\\ W)boot(?:\\ W|$)" , Pattern .CASE_INSENSITIVE | Pattern .MULTILINE );
734+ private static final Pattern TMP_PATT =
735+ Pattern .compile (
736+ "(?:^|\\ W)tmp(?:\\ W|$)" , Pattern .CASE_INSENSITIVE | Pattern .MULTILINE );
737+ private static final Pattern HOME_PATT =
738+ Pattern .compile (
739+ "(?:^|\\ W)home(?:\\ W|$)" , Pattern .CASE_INSENSITIVE | Pattern .MULTILINE );
740+
741+ private Tech tech ;
742+
743+ public DirNamesContentsMatcher (Tech tech ) {
744+ this .tech = tech ;
745+ }
746+
709747 @ Override
710748 public String match (String contents ) {
711- String result = matchNixDirectories (contents );
712- if (result != null ) {
713- return result ;
749+ if (this .tech == Tech .Linux ) {
750+ return matchNixDirectories (contents );
751+ }
752+ if (this .tech == Tech .Windows ) {
753+ return matchWinDirectories (contents );
714754 }
715- return matchWinDirectories ( contents ) ;
755+ return null ;
716756 }
717757
718758 private static String matchNixDirectories (String contents ) {
719- Pattern procPattern =
720- Pattern .compile ("(?:^|\\ W)proc(?:\\ W|$)" , Pattern .CASE_INSENSITIVE );
721- Pattern etcPattern = Pattern .compile ("(?:^|\\ W)etc(?:\\ W|$)" , Pattern .CASE_INSENSITIVE );
722- Pattern bootPattern =
723- Pattern .compile ("(?:^|\\ W)boot(?:\\ W|$)" , Pattern .CASE_INSENSITIVE );
724- Pattern tmpPattern = Pattern .compile ("(?:^|\\ W)tmp(?:\\ W|$)" , Pattern .CASE_INSENSITIVE );
725- Pattern homePattern =
726- Pattern .compile ("(?:^|\\ W)home(?:\\ W|$)" , Pattern .CASE_INSENSITIVE );
727-
728- Matcher procMatcher = procPattern .matcher (contents );
729- Matcher etcMatcher = etcPattern .matcher (contents );
730- Matcher bootMatcher = bootPattern .matcher (contents );
731- Matcher tmpMatcher = tmpPattern .matcher (contents );
732- Matcher homeMatcher = homePattern .matcher (contents );
733-
734- if (procMatcher .find ()
735- && etcMatcher .find ()
736- && bootMatcher .find ()
737- && tmpMatcher .find ()
738- && homeMatcher .find ()) {
739- return "etc" ;
759+ if (PROC_PATT .matcher (contents ).find ()
760+ && ETC_PATT .matcher (contents ).find ()
761+ && BOOT_PATT .matcher (contents ).find ()
762+ && TMP_PATT .matcher (contents ).find ()
763+ && HOME_PATT .matcher (contents ).find ()) {
764+ return NIX_DIR_EVIDENCE ;
740765 }
741766
742767 return null ;
743768 }
744769
745770 private static String matchWinDirectories (String contents ) {
746- if (contents .contains ("Windows" )
747- && Pattern .compile ("Program\\ sFiles" ).matcher (contents ).find ()) {
748- return "Windows" ;
771+ if (contents .contains (WIN_DIR_EVIDENCE )
772+ && Pattern .compile ("Program\\ sFiles" , Pattern .CASE_INSENSITIVE )
773+ .matcher (contents )
774+ .find ()) {
775+ return WIN_DIR_EVIDENCE ;
749776 }
750777
751778 return null ;
0 commit comments