-
Notifications
You must be signed in to change notification settings - Fork 192
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Apache Axis2 weak credential tester #578
base: master
Are you sure you want to change the base?
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hello @GiuseppePorcu, thanks for your contribution! The overall quality of the detector is good, I just left some comments and suggestions to improve style and readability.
boolean isWebService = NetworkServiceUtils.isWebService(networkService); | ||
|
||
if (!isWebService) { | ||
return false; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This function can be simplified maintaining the same logic and a good readability
boolean isWebService = NetworkServiceUtils.isWebService(networkService); | |
if (!isWebService) { | |
return false; | |
} | |
if (!NetworkServiceUtils.isWebService(networkService)) { | |
return false; | |
} |
boolean canAcceptByCustomFingerprint = false; | ||
|
||
String url = NetworkServiceUtils.buildWebApplicationRootUrl(networkService) + "axis2/"; | ||
|
||
try { | ||
logger.atInfo().log("probing Axis2 Home Page - custom fingerprint phase"); | ||
HttpResponse response = httpClient.send(get(url).withEmptyHeaders().build()); | ||
|
||
canAcceptByCustomFingerprint = | ||
response.status().isSuccess() | ||
&& response | ||
.bodyString() | ||
.map(Axis2CredentialTester::bodyContainsAxis2Elements) | ||
.orElse(false); | ||
} catch (Exception e) { | ||
logger.atWarning().withCause(e).log("Unable to query '%s'.", url); | ||
return false; | ||
} | ||
return canAcceptByCustomFingerprint; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
boolean canAcceptByCustomFingerprint = false; | |
String url = NetworkServiceUtils.buildWebApplicationRootUrl(networkService) + "axis2/"; | |
try { | |
logger.atInfo().log("probing Axis2 Home Page - custom fingerprint phase"); | |
HttpResponse response = httpClient.send(get(url).withEmptyHeaders().build()); | |
canAcceptByCustomFingerprint = | |
response.status().isSuccess() | |
&& response | |
.bodyString() | |
.map(Axis2CredentialTester::bodyContainsAxis2Elements) | |
.orElse(false); | |
} catch (Exception e) { | |
logger.atWarning().withCause(e).log("Unable to query '%s'.", url); | |
return false; | |
} | |
return canAcceptByCustomFingerprint; | |
String url = NetworkServiceUtils.buildWebApplicationRootUrl(networkService) + "axis2/"; | |
try { | |
logger.atInfo().log("probing Axis2 Home Page - custom fingerprint phase"); | |
HttpResponse response = httpClient.send(get(url).withEmptyHeaders().build()); | |
return response.status().isSuccess() | |
&& response | |
.bodyString() | |
.map(Axis2CredentialTester::bodyContainsAxis2Elements) | |
.orElse(false); | |
} catch (Exception e) { | |
logger.atWarning().withCause(e).log("Unable to query '%s'.", url); | |
return false; | |
} |
if (Ascii.toLowerCase(title).contains(AXIS_PAGE_TITLE)) { | ||
logger.atInfo().log("Found Axis2 Home Page (AXIS_PAGE_TITLE string present in the page)"); | ||
return true; | ||
} else { | ||
return false; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The else
clause can be removed, and a single return
statement is sufficient if the result of the check is stored in a variable.
if (Ascii.toLowerCase(title).contains(AXIS_PAGE_TITLE)) { | |
logger.atInfo().log("Found Axis2 Home Page (AXIS_PAGE_TITLE string present in the page)"); | |
return true; | |
} else { | |
return false; | |
} | |
boolean containsAxis2Elements = Ascii.toLowerCase(title).contains(AXIS_PAGE_TITLE); | |
if (containsAxis2Elements) { | |
logger.atInfo().log("Found Axis2 Home Page (AXIS_PAGE_TITLE string present in the page)"); | |
} | |
return containsAxis2Elements; |
* https://axis.apache.org/axis2/java/core/docs/webadminguide.html#login | ||
*/ | ||
TestCredential defaultUser = TestCredential.create(AXIS_USERNAME, Optional.of(AXIS_PASSWORD)); | ||
if (isAxis2Accessible(networkService, defaultUser)) return ImmutableList.of(defaultUser); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As per Google Java Style Guide - 4.1.1:
Braces are used with
if
[...] statements, even when the body is empty or contains only a single statement.
if (isAxis2Accessible(networkService, defaultUser)) return ImmutableList.of(defaultUser); | |
if (isAxis2Accessible(networkService, defaultUser)) { | |
return ImmutableList.of(defaultUser); | |
} |
/** | ||
* No need for detect_weakCredentialsExist_returnsAllWeakCredentials since Axis2 only supports a | ||
* single administrator user | ||
*/ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This comment can be confusing for the reader, please restructure the sentence in a more clearer way.
/** | |
* No need for detect_weakCredentialsExist_returnsAllWeakCredentials since Axis2 only supports a | |
* single administrator user | |
*/ | |
/** | |
* A separate test for detecting multiple weak credentials is unnecessary because | |
* Axis2 only supports a single administrator user. Therefore, this test | |
* (`detect_weakCredentialsExists_returnsWeakCredentials`) effectively covers the | |
* intended behavior. | |
*/ |
private static final String AXIS_USERNAME = "admin"; | ||
private static final String AXIS_PASSWORD = "axis2"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I just realized I didn't include this in the review while transposing my notes. Is there a specific reason why the default credentials aren’t in the appropriate proto file? If possible, please move them to:
google/detectors/credentials/generic_weak_credential_detector/src/main/resources/detectors/credentials/genericweakcredentialdetector/data/service_default_credentials.textproto
.
Thanks!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi @giacomo-doyensec thanks for your feedback, I'll resolve them as suggested!
Default credentials of Axis2 have been inserted within the class since nmap identifies the service as "http", so in order to not test such credentials against each http service we decided to add the credentials inside the detector.
Following I've inserted a screenshot of nmap discovery in order to show the issue:
Do you prefer to add the credential in the proto file or we can leave it here and add a comment in order to explain why the default credentials are inserted inside the detector instead of the proto file?
Hi there,
This PR contains the implementation of the weak credential tester for Apache Axis2 Administration Panel.
As described within the Issue, authenticated access to the Administration Panel allows to upload new services thus leading to RCE.
Below it is possible to find the necessary information for review:
Issue: #569
PR Testbed: google/security-testbeds#112
Thank you.