@@ -145,15 +145,15 @@ private static Pattern[] compilePatterns(String... rawPatterns) {
145145 * 1. Authenticated and unauthenticated responses are DIFFERENT (confirms auth is required)
146146 * 2. Authenticated response with appended segment is SIMILAR to original (confirms backend ignores trailing segments)
147147 */
148- protected static String initialTest (IHttpRequestResponse message ) {
148+ protected static InitialTestResult initialTest (IHttpRequestResponse message ) {
149149 byte [] orgRequest = buildHttpRequest (message , null , null , true );
150150 Map <String , Object > orgDetails = retrieveResponseDetails (message .getHttpService (), orgRequest );
151151 if (orgDetails == null ) {
152- return null ;
152+ return InitialTestResult . failure ( "Unable to fetch the original authenticated response" ) ;
153153 }
154154 int orgStatusCode = (int ) orgDetails .get ("statusCode" );
155155 if (orgStatusCode < 200 || orgStatusCode >= 300 ) {
156- return null ; // Original request must succeed
156+ return InitialTestResult . failure ( " Original request returned status " + orgStatusCode );
157157 }
158158 byte [] originalAuthBody = (byte []) orgDetails .get ("body" );
159159
@@ -162,7 +162,7 @@ protected static String initialTest(IHttpRequestResponse message) {
162162 byte [] unAuthedRequest = buildHttpRequest (message , null , null , false );
163163 Map <String , Object > unauthDetails = retrieveResponseDetails (message .getHttpService (), unAuthedRequest );
164164 if (unauthDetails == null ) {
165- return null ;
165+ return InitialTestResult . failure ( "Unable to fetch unauthenticated response" ) ;
166166 }
167167 int unauthStatusCode = (int ) unauthDetails .get ("statusCode" );
168168 byte [] unauthBody = (byte []) unauthDetails .get ("body" );
@@ -175,7 +175,7 @@ protected static String initialTest(IHttpRequestResponse message) {
175175 // If unauthenticated response is similar, this endpoint doesn't require auth - skip it
176176 if (unauthedIsSimilar ) {
177177 BurpExtender .logDebug ("Initial test failed: Unauthenticated response similar to authenticated" );
178- return null ;
178+ return InitialTestResult . failure ( "Endpoint looks public (auth vs unauth are similar)" ) ;
179179 }
180180
181181 // Step 2: Verify that appending a random segment returns SIMILAR content
@@ -184,11 +184,11 @@ protected static String initialTest(IHttpRequestResponse message) {
184184 byte [] testRequest = buildHttpRequestWithSegment (message , randomSegment , null , true , "/" );
185185 Map <String , Object > appendedDetails = retrieveResponseDetails (message .getHttpService (), testRequest );
186186 if (appendedDetails == null ) {
187- return null ;
187+ return InitialTestResult . failure ( "Unable to fetch appended path response" ) ;
188188 }
189189 int appendedStatusCode = (int ) appendedDetails .get ("statusCode" );
190190 if (appendedStatusCode < 200 || appendedStatusCode >= 300 ) {
191- return null ; // Appended request must also succeed
191+ return InitialTestResult . failure ( "Appended path returned status " + appendedStatusCode );
192192 }
193193 byte [] appendedBody = (byte []) appendedDetails .get ("body" );
194194
@@ -199,11 +199,11 @@ protected static String initialTest(IHttpRequestResponse message) {
199199
200200 if (!appendIsSimilar ) {
201201 BurpExtender .logDebug ("Initial test failed: Appended segment response not similar to original" );
202- return null ;
202+ return InitialTestResult . failure ( "Backend rejects extra path segments" ) ;
203203 }
204204
205205 // Both conditions met: auth required AND backend ignores trailing segments
206- return randomSegment ;
206+ return InitialTestResult . success ( randomSegment ) ;
207207 }
208208
209209 /**
@@ -1482,4 +1482,36 @@ private byte[] toByteArray(boolean includeCookies) {
14821482 return BurpExtender .getHelpers ().buildHttpMessage (finalHeaders , body );
14831483 }
14841484 }
1485+
1486+ protected static final class InitialTestResult {
1487+ private final boolean success ;
1488+ private final String randomSegment ;
1489+ private final String failureReason ;
1490+
1491+ private InitialTestResult (boolean success , String randomSegment , String failureReason ) {
1492+ this .success = success ;
1493+ this .randomSegment = randomSegment ;
1494+ this .failureReason = failureReason ;
1495+ }
1496+
1497+ protected static InitialTestResult success (String randomSegment ) {
1498+ return new InitialTestResult (true , randomSegment , null );
1499+ }
1500+
1501+ protected static InitialTestResult failure (String reason ) {
1502+ return new InitialTestResult (false , null , reason );
1503+ }
1504+
1505+ protected boolean isSuccess () {
1506+ return success ;
1507+ }
1508+
1509+ protected String getRandomSegment () {
1510+ return randomSegment ;
1511+ }
1512+
1513+ protected String getFailureReason () {
1514+ return failureReason ;
1515+ }
1516+ }
14851517}
0 commit comments