@@ -80,7 +80,8 @@ public class PathTraversalScanRule extends AbstractAppParamPlugin
80
80
* Windows local file targets and detection pattern
81
81
*/
82
82
private static final ContentsMatcher WIN_PATTERN =
83
- new PatternContentsMatcher (Pattern .compile ("\\ [drivers\\ ]" ));
83
+ new PatternContentsMatcher (Pattern .compile ("\\ [drivers\\ ]" ), Tech .Windows );
84
+ private static final String WIN_DIR_EVIDENCE = "Windows" ;
84
85
private static final String [] WIN_LOCAL_FILE_TARGETS = {
85
86
// Absolute Windows file retrieval (we suppose C:\\)
86
87
"c:/Windows/system.ini" ,
@@ -129,7 +130,8 @@ public class PathTraversalScanRule extends AbstractAppParamPlugin
129
130
*/
130
131
// Dot used to match 'x' or '!' (used in AIX)
131
132
private static final ContentsMatcher NIX_PATTERN =
132
- new PatternContentsMatcher (Pattern .compile ("root:.:0:0" ));
133
+ new PatternContentsMatcher (Pattern .compile ("root:.:0:0" ), Tech .Linux );
134
+ private static final String NIX_DIR_EVIDENCE = "etc" ;
133
135
private static final String [] NIX_LOCAL_FILE_TARGETS = {
134
136
// Absolute file retrieval
135
137
"/etc/passwd" ,
@@ -155,10 +157,9 @@ public class PathTraversalScanRule extends AbstractAppParamPlugin
155
157
// ..%252F..%252F..%252F..%252F..%252F..%252F..%252F..%252F..%252F..%252Fetc%252Fpasswd%2500.jpg
156
158
};
157
159
158
- /*
159
- * Windows/Unix/Linux/etc. local directory targets and detection pattern
160
- */
161
- private static final ContentsMatcher DIR_PATTERN = new DirNamesContentsMatcher ();
160
+ private static final ContentsMatcher NIX_DIR_MATCHER = new DirNamesContentsMatcher (Tech .Linux );
161
+ private static final ContentsMatcher WIN_DIR_MATCHER =
162
+ new DirNamesContentsMatcher (Tech .Windows );
162
163
private static final String [] WIN_LOCAL_DIR_TARGETS = {
163
164
"c:/" ,
164
165
"c:\\ " ,
@@ -180,17 +181,19 @@ public class PathTraversalScanRule extends AbstractAppParamPlugin
180
181
"/" ,
181
182
"../../../../../../../../../../../../../../../../" ,
182
183
"/../../../../../../../../../../../../../../../../" ,
183
- "file:///" ,
184
+ "file:///"
184
185
};
185
186
186
187
private static final ContentsMatcher WAR_PATTERN =
187
- new PatternContentsMatcher (Pattern .compile ("</web-app>" ));
188
+ new PatternContentsMatcher (Pattern .compile ("</web-app>" ), Tech . Tomcat );
188
189
189
190
/*
190
191
* Standard local file prefixes
191
192
*/
192
193
private static final String [] LOCAL_FILE_RELATIVE_PREFIXES = {"" , "/" , "\\ " };
193
194
195
+ private static final List <String > DIR_EVIDENCE_LIST =
196
+ List .of (NIX_DIR_EVIDENCE , WIN_DIR_EVIDENCE );
194
197
/*
195
198
* details of the vulnerability which we are attempting to find
196
199
*/
@@ -341,7 +344,6 @@ public void scan(HttpMessage msg, String param, String value) {
341
344
342
345
// Check 2: Start detection for *NIX patterns
343
346
if (inScope (Tech .Linux ) || inScope (Tech .MacOS )) {
344
-
345
347
for (int h = 0 ; h < nixCount ; h ++) {
346
348
347
349
// Check if a there was a finding or the scan has been stopped
@@ -383,10 +385,9 @@ public void scan(HttpMessage msg, String param, String value) {
383
385
// Check 3: Detect if this page is a directory browsing component
384
386
if (inScope (Tech .Linux ) || inScope (Tech .MacOS )) {
385
387
for (int h = 0 ; h < nixDirCount ; h ++) {
386
-
387
388
// Check if a there was a finding or the scan has been stopped
388
389
// if yes dispose resources and exit
389
- if (sendAndCheckPayload (param , NIX_LOCAL_DIR_TARGETS [h ], DIR_PATTERN , 3 )
390
+ if (sendAndCheckPayload (param , NIX_LOCAL_DIR_TARGETS [h ], NIX_DIR_MATCHER , 3 )
390
391
|| isStop ()) {
391
392
// Dispose all resources
392
393
// Exit the scan rule
@@ -396,7 +397,7 @@ public void scan(HttpMessage msg, String param, String value) {
396
397
}
397
398
if (inScope (Tech .Windows )) {
398
399
for (int h = 0 ; h < winDirCount ; h ++) {
399
- if (sendAndCheckPayload (param , WIN_LOCAL_DIR_TARGETS [h ], DIR_PATTERN , 3 )
400
+ if (sendAndCheckPayload (param , WIN_LOCAL_DIR_TARGETS [h ], WIN_DIR_MATCHER , 3 )
400
401
|| isStop ()) {
401
402
// Dispose all resources
402
403
// Exit the scan rule
@@ -658,12 +659,23 @@ private AlertBuilder createUnmatchedAlert(String param, String attack) {
658
659
659
660
private AlertBuilder createMatchedAlert (
660
661
String param , String attack , String evidence , int check ) {
661
- return newAlert ()
662
- .setConfidence (Alert .CONFIDENCE_MEDIUM )
663
- .setParam (param )
664
- .setAttack (attack )
665
- .setEvidence (evidence )
666
- .setAlertRef (getId () + "-" + check );
662
+ AlertBuilder builder =
663
+ newAlert ()
664
+ .setConfidence (Alert .CONFIDENCE_MEDIUM )
665
+ .setParam (param )
666
+ .setAttack (attack )
667
+ .setEvidence (evidence )
668
+ .setAlertRef (getId () + "-" + check );
669
+ if (DIR_EVIDENCE_LIST .contains (evidence )) {
670
+ builder .setOtherInfo (
671
+ Constant .messages .getString (
672
+ MESSAGE_PREFIX + "info" ,
673
+ evidence ,
674
+ evidence .equals (WIN_DIR_EVIDENCE )
675
+ ? DirNamesContentsMatcher .WIN_MATCHES
676
+ : DirNamesContentsMatcher .NIX_MATCHES ));
677
+ }
678
+ return builder ;
667
679
}
668
680
669
681
@ Override
@@ -689,7 +701,7 @@ private static class PatternContentsMatcher implements ContentsMatcher {
689
701
690
702
private final Pattern pattern ;
691
703
692
- public PatternContentsMatcher (Pattern pattern ) {
704
+ public PatternContentsMatcher (Pattern pattern , Tech tech ) {
693
705
this .pattern = pattern ;
694
706
}
695
707
@@ -705,46 +717,61 @@ public String match(String contents) {
705
717
706
718
private static class DirNamesContentsMatcher implements ContentsMatcher {
707
719
720
+ private static final String NIX_MATCHES =
721
+ String .join (", " , List .of ("proc" , NIX_DIR_EVIDENCE , "boot" , "tmp" , "home" ));
722
+ private static final String WIN_MATCHES =
723
+ String .join (", " , List .of (WIN_DIR_EVIDENCE , "Program Files" ));
724
+ private static final Pattern PROC_PATT =
725
+ Pattern .compile (
726
+ "(?:^|\\ W)proc(?:\\ W|$)" , Pattern .CASE_INSENSITIVE | Pattern .MULTILINE );
727
+ private static final Pattern ETC_PATT =
728
+ Pattern .compile (
729
+ "(?:^|\\ W)etc(?:\\ W|$)" , Pattern .CASE_INSENSITIVE | Pattern .MULTILINE );
730
+ private static final Pattern BOOT_PATT =
731
+ Pattern .compile (
732
+ "(?:^|\\ W)boot(?:\\ W|$)" , Pattern .CASE_INSENSITIVE | Pattern .MULTILINE );
733
+ private static final Pattern TMP_PATT =
734
+ Pattern .compile (
735
+ "(?:^|\\ W)tmp(?:\\ W|$)" , Pattern .CASE_INSENSITIVE | Pattern .MULTILINE );
736
+ private static final Pattern HOME_PATT =
737
+ Pattern .compile (
738
+ "(?:^|\\ W)home(?:\\ W|$)" , Pattern .CASE_INSENSITIVE | Pattern .MULTILINE );
739
+
740
+ private Tech tech ;
741
+
742
+ public DirNamesContentsMatcher (Tech tech ) {
743
+ this .tech = tech ;
744
+ }
745
+
708
746
@ Override
709
747
public String match (String contents ) {
710
- String result = matchNixDirectories (contents );
711
- if (result != null ) {
712
- return result ;
748
+ if (this .tech == Tech .Linux ) {
749
+ return matchNixDirectories (contents );
750
+ }
751
+ if (this .tech == Tech .Windows ) {
752
+ return matchWinDirectories (contents );
713
753
}
714
- return matchWinDirectories ( contents ) ;
754
+ return null ;
715
755
}
716
756
717
757
private static String matchNixDirectories (String contents ) {
718
- Pattern procPattern =
719
- Pattern .compile ("(?:^|\\ W)proc(?:\\ W|$)" , Pattern .CASE_INSENSITIVE );
720
- Pattern etcPattern = Pattern .compile ("(?:^|\\ W)etc(?:\\ W|$)" , Pattern .CASE_INSENSITIVE );
721
- Pattern bootPattern =
722
- Pattern .compile ("(?:^|\\ W)boot(?:\\ W|$)" , Pattern .CASE_INSENSITIVE );
723
- Pattern tmpPattern = Pattern .compile ("(?:^|\\ W)tmp(?:\\ W|$)" , Pattern .CASE_INSENSITIVE );
724
- Pattern homePattern =
725
- Pattern .compile ("(?:^|\\ W)home(?:\\ W|$)" , Pattern .CASE_INSENSITIVE );
726
-
727
- Matcher procMatcher = procPattern .matcher (contents );
728
- Matcher etcMatcher = etcPattern .matcher (contents );
729
- Matcher bootMatcher = bootPattern .matcher (contents );
730
- Matcher tmpMatcher = tmpPattern .matcher (contents );
731
- Matcher homeMatcher = homePattern .matcher (contents );
732
-
733
- if (procMatcher .find ()
734
- && etcMatcher .find ()
735
- && bootMatcher .find ()
736
- && tmpMatcher .find ()
737
- && homeMatcher .find ()) {
738
- return "etc" ;
758
+ if (PROC_PATT .matcher (contents ).find ()
759
+ && ETC_PATT .matcher (contents ).find ()
760
+ && BOOT_PATT .matcher (contents ).find ()
761
+ && TMP_PATT .matcher (contents ).find ()
762
+ && HOME_PATT .matcher (contents ).find ()) {
763
+ return NIX_DIR_EVIDENCE ;
739
764
}
740
765
741
766
return null ;
742
767
}
743
768
744
769
private static String matchWinDirectories (String contents ) {
745
- if (contents .contains ("Windows" )
746
- && Pattern .compile ("Program\\ sFiles" ).matcher (contents ).find ()) {
747
- return "Windows" ;
770
+ if (contents .contains (WIN_DIR_EVIDENCE )
771
+ && Pattern .compile ("Program\\ sFiles" , Pattern .CASE_INSENSITIVE )
772
+ .matcher (contents )
773
+ .find ()) {
774
+ return WIN_DIR_EVIDENCE ;
748
775
}
749
776
750
777
return null ;
0 commit comments