Skip to content
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

ascanrulesBeta: Add more example alerts #5291

Merged
merged 1 commit into from
Feb 13, 2024
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
12 changes: 10 additions & 2 deletions addOns/ascanrulesBeta/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,16 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).

## Unreleased
### Changed
- The Backup File Disclosure scan rule now includes example alert functionality for documentation generation purposes (Issue 6119).
- Updated reference for scan rule: Session Fixation (Issue 8262)
- The following scan rules now include example alert functionality for documentation generation purposes (Issue 6119):
- Backup File Disclosure
- Httpoxy - Proxy Header Misuse
- Anti-CSRF Tokens Check
- HTTP Parameter Pollution
- Cross-Domain Misconfiguration
- Alerts from the HTTP Parameter Pollution scan rule are now raised with Low confidence.
- Updated reference for scan rules (Issue 8262):
- Session Fixation
- Cross-Domain Misconfiguration
- Add website alert links to the help page (Issue 8189).

## [50] - 2024-01-26
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
Expand Down Expand Up @@ -192,21 +193,7 @@ private void scanAdobeCrossdomainPolicyFile(URI originalURI)
String domain = exprAllowAccessFromDomainNodes.item(i).getNodeValue();
if (domain.equals("*")) {
// oh dear me.
newAlert()
.setConfidence(Alert.CONFIDENCE_MEDIUM)
.setName(
Constant.messages.getString(MESSAGE_PREFIX_ADOBE_READ + "name"))
.setDescription(
Constant.messages.getString(MESSAGE_PREFIX_ADOBE + "desc"))
.setOtherInfo(
Constant.messages.getString(
MESSAGE_PREFIX_ADOBE_READ + "extrainfo",
"/" + ADOBE_CROSS_DOMAIN_POLICY_FILE))
.setSolution(
Constant.messages.getString(MESSAGE_PREFIX_ADOBE_READ + "soln"))
.setEvidence("<allow-access-from domain=\"*\"")
.setMessage(crossdomainmessage)
.raise();
buildAdobeReadAlert().setMessage(crossdomainmessage).raise();
}
}
// check for cross domain send (upload) access
Expand All @@ -223,21 +210,7 @@ private void scanAdobeCrossdomainPolicyFile(URI originalURI)
String domain = exprRequestHeadersFromDomainNodes.item(i).getNodeValue();
if (domain.equals("*")) {
// oh dear, dear me.
newAlert()
.setConfidence(Alert.CONFIDENCE_MEDIUM)
.setName(
Constant.messages.getString(MESSAGE_PREFIX_ADOBE_SEND + "name"))
.setDescription(
Constant.messages.getString(MESSAGE_PREFIX_ADOBE + "desc"))
.setOtherInfo(
Constant.messages.getString(
MESSAGE_PREFIX_ADOBE_SEND + "extrainfo",
"/" + ADOBE_CROSS_DOMAIN_POLICY_FILE))
.setSolution(
Constant.messages.getString(MESSAGE_PREFIX_ADOBE_SEND + "soln"))
.setEvidence("<allow-http-request-headers-from domain=\"*\"")
.setMessage(crossdomainmessage)
.raise();
buildAdobeSendAlert().setMessage(crossdomainmessage).raise();
}
}
} catch (SAXException | IOException e) {
Expand All @@ -249,6 +222,35 @@ private void scanAdobeCrossdomainPolicyFile(URI originalURI)
}
}

private AlertBuilder buildAdobeAlert(String ref) {
return newAlert()
.setConfidence(Alert.CONFIDENCE_MEDIUM)
.setDescription(Constant.messages.getString(MESSAGE_PREFIX_ADOBE + "desc"))
.setAlertRef(getId() + ref);
}

private AlertBuilder buildAdobeReadAlert() {
return buildAdobeAlert("-1")
.setName(Constant.messages.getString(MESSAGE_PREFIX_ADOBE_READ + "name"))
.setOtherInfo(
Constant.messages.getString(
MESSAGE_PREFIX_ADOBE_READ + "extrainfo",
"/" + ADOBE_CROSS_DOMAIN_POLICY_FILE))
.setSolution(Constant.messages.getString(MESSAGE_PREFIX_ADOBE_READ + "soln"))
.setEvidence("<allow-access-from domain=\"*\"");
}

private AlertBuilder buildAdobeSendAlert() {
return buildAdobeAlert("-2")
.setName(Constant.messages.getString(MESSAGE_PREFIX_ADOBE_SEND + "name"))
.setOtherInfo(
Constant.messages.getString(
MESSAGE_PREFIX_ADOBE_SEND + "extrainfo",
"/" + ADOBE_CROSS_DOMAIN_POLICY_FILE))
.setSolution(Constant.messages.getString(MESSAGE_PREFIX_ADOBE_SEND + "soln"))
.setEvidence("<allow-http-request-headers-from domain=\"*\"");
}

private void scanSilverlightCrossdomainPolicyFile(URI originalURI)
throws IOException, XPathExpressionException {
// retrieve the Silverlight client access policy file, and assess it.
Expand Down Expand Up @@ -292,23 +294,7 @@ private void scanSilverlightCrossdomainPolicyFile(URI originalURI)
LOGGER.debug(
"Bingo! {}, at /access-policy/cross-domain-access/policy/allow-from/domain/@uri",
SILVERLIGHT_CROSS_DOMAIN_POLICY_FILE);
newAlert()
.setConfidence(Alert.CONFIDENCE_MEDIUM)
.setName(
Constant.messages.getString(
MESSAGE_PREFIX_SILVERLIGHT + "name"))
.setDescription(
Constant.messages.getString(
MESSAGE_PREFIX_SILVERLIGHT + "desc"))
.setOtherInfo(
Constant.messages.getString(
MESSAGE_PREFIX_SILVERLIGHT + "extrainfo"))
.setSolution(
Constant.messages.getString(
MESSAGE_PREFIX_SILVERLIGHT + "soln"))
.setEvidence("<domain uri=\"*\"")
.setMessage(clientaccesspolicymessage)
.raise();
buildSilverlightAlert().setMessage(clientaccesspolicymessage).raise();
}
}

Expand All @@ -321,6 +307,17 @@ private void scanSilverlightCrossdomainPolicyFile(URI originalURI)
}
}

private AlertBuilder buildSilverlightAlert() {
return newAlert()
.setConfidence(Alert.CONFIDENCE_MEDIUM)
.setName(Constant.messages.getString(MESSAGE_PREFIX_SILVERLIGHT + "name"))
.setDescription(Constant.messages.getString(MESSAGE_PREFIX_SILVERLIGHT + "desc"))
.setOtherInfo(Constant.messages.getString(MESSAGE_PREFIX_SILVERLIGHT + "extrainfo"))
.setSolution(Constant.messages.getString(MESSAGE_PREFIX_SILVERLIGHT + "soln"))
.setEvidence("<domain uri=\"*\"")
.setAlertRef(getId() + "-3");
}

@Override
public int getRisk() {
return Alert.RISK_HIGH;
Expand All @@ -341,4 +338,12 @@ public int getWascId() {
public Map<String, String> getAlertTags() {
return ALERT_TAGS;
}

@Override
public List<Alert> getExampleAlerts() {
return List.of(
buildAdobeReadAlert().build(),
buildAdobeSendAlert().build(),
buildSilverlightAlert().build());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -220,13 +220,7 @@ public void scan() {
Constant.messages.getString(
MESSAGE_PREFIX + "extrainfo.annotation");
}
newAlert()
.setRisk(risk)
.setConfidence(Alert.CONFIDENCE_MEDIUM)
.setOtherInfo(otherInfo)
.setEvidence(evidence)
.setMessage(getBaseMsg())
.raise();
buildAlert(risk, otherInfo, evidence).setMessage(getBaseMsg()).raise();
}
}

Expand All @@ -237,6 +231,14 @@ public void scan() {
}
}

private AlertBuilder buildAlert(int risk, String otherInfo, String evidence) {
return newAlert()
.setRisk(risk)
.setConfidence(Alert.CONFIDENCE_MEDIUM)
.setOtherInfo(otherInfo)
.setEvidence(evidence);
}

private boolean formOnIgnoreList(Element formElement) {
String id = formElement.getAttributeValue("id");
String name = formElement.getAttributeValue("name");
Expand Down Expand Up @@ -301,4 +303,14 @@ public int getWascId() {
public Map<String, String> getAlertTags() {
return ALERT_TAGS;
}

@Override
public List<Alert> getExampleAlerts() {
return List.of(
buildAlert(
Alert.RISK_MEDIUM,
"",
"<input type=\"hidden\" name=\"firstName\" value=\"\">")
.build());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.util.Enumeration;
import java.util.List;
import java.util.Map;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
Expand Down Expand Up @@ -142,13 +143,10 @@ public void scan() {

if (listener.isMsgReceived()) {
// the server is vulnerable
newAlert()
.setConfidence(Alert.CONFIDENCE_HIGH)
.setUri(getBaseMsg().getRequestHeader().getURI().toString())
.setAttack(HttpFieldsNames.PROXY + ": " + hostPort)
.setOtherInfo(
Constant.messages.getString(
MESSAGE_PREFIX + "otherinfo", listener.getMsgUrl()))
buildAlert(
hostPort,
getBaseMsg().getRequestHeader().getURI().toString(),
listener.getMsgUrl())
.setMessage(newRequest)
.raise();

Expand All @@ -162,6 +160,21 @@ public void scan() {
}
}

private AlertBuilder buildAlert(String hostPort, String baseUrl, String url) {
return newAlert()
.setConfidence(Alert.CONFIDENCE_HIGH)
.setUri(baseUrl)
.setAttack(HttpFieldsNames.PROXY + ": " + hostPort)
.setOtherInfo(Constant.messages.getString(MESSAGE_PREFIX + "otherinfo", url));
}

@Override
public List<Alert> getExampleAlerts() {
return List.of(
buildAlert("192.168.0.11:1080", "http://example.com/", "http://192.168.0.11:1080/")
.build());
}

private class HttpoxyListener implements HttpMessageHandler {

private boolean msgReceived;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -278,20 +278,16 @@ public void generateReport(List<String> vulnLinks) {
vulnParams = vulnParams + ", " + s;
}
LOGGER.debug("Page vulnerable to HPP attacks");
String attack = Constant.messages.getString("ascanbeta.HTTPParamPoll.alert.attack");
newAlert()
.setConfidence(Alert.CONFIDENCE_MEDIUM)
.setName(attack)
.setParam(vulnParams)
.setAttack(attack)
.setMessage(getBaseMsg())
.raise();
buildAlert(vulnParams).setMessage(getBaseMsg()).raise();
}

private AlertBuilder buildAlert(String vulnParams) {
return newAlert().setConfidence(Alert.CONFIDENCE_LOW).setParam(vulnParams);
}

@Override
public int getRisk() {
// TODO Auto-generated method stub
return 0;
return Alert.RISK_INFO;
}

@Override
Expand All @@ -308,4 +304,9 @@ public int getWascId() {
public Map<String, String> getAlertTags() {
return ALERT_TAGS;
}

@Override
public List<Alert> getExampleAlerts() {
return List.of(buildAlert("Id").build());
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
ascanbeta.HTTPParamPoll.alert.attack = HTTP Parameter Pollution
ascanbeta.HTTPParamPoll.desc = HTTP Parameter Pollution (HPP) attacks consist of injecting encoded query string delimiters into other existing parameters. If a web application does not properly sanitize the user input, a malicious user can compromise the logic of the application to perform either client-side or server-side attacks. One consequence of HPP attacks is that the attacker can potentially override existing hard-coded HTTP parameters to modify the behavior of an application, bypass input validation checkpoints, and access and possibly exploit variables that may be out of direct reach.
ascanbeta.HTTPParamPoll.extrainfo = https://owasp.org/www-project-web-security-testing-guide/v42/4-Web_Application_Security_Testing/07-Input_Validation_Testing/04-Testing_for_HTTP_Parameter_Pollution
ascanbeta.HTTPParamPoll.name = HTTP Parameter Pollution
Expand Down Expand Up @@ -35,8 +34,7 @@ ascanbeta.crossdomain.adobe.send.extrainfo = The web server permits malicious cr
ascanbeta.crossdomain.adobe.send.name = Cross-Domain Misconfiguration - Adobe - Send
ascanbeta.crossdomain.adobe.send.soln = Configure the crossdomain.xml file to restrict the list of domains that are allowed to make cross-domain send (but not necessarily read) requests to this web server, using <allow-http-request-headers-from domain="example.com" headers="Authorization,X-Blahh">. You should only grant access to "*" (all domains) if you are certain that this service is not vulnerable to Cross Site Request Forgery (CSRF) attacks.
ascanbeta.crossdomain.name = Cross-Domain Misconfiguration
#the refs cannot be customised for each sub-category (Adobe, Silverlight, etc.)
ascanbeta.crossdomain.refs = http://www.adobe.com/devnet/articles/crossdomain_policy_file_spec.html\nhttp://www.adobe.com/devnet-docs/acrobatetk/tools/AppSec/CrossDomain_PolicyFile_Specification.pdf\nhttp://msdn.microsoft.com/en-US/library/cc197955%28v=vs.95%29.aspx\nhttp://msdn.microsoft.com/en-us/library/cc838250%28v=vs.95%29.aspx
ascanbeta.crossdomain.refs = https://www.adobe.com/devnet-docs/acrobatetk/tools/AppSec/CrossDomain_PolicyFile_Specification.pdf\nhttps://learn.microsoft.com/en-us/previous-versions/windows/silverlight/dotnet-windows-silverlight/cc197955(v=vs.95)\nhttps://learn.microsoft.com/en-us/previous-versions/windows/silverlight/dotnet-windows-silverlight/cc838250(v=vs.95)
Comment on lines -38 to -39
Copy link
Member Author

@kingthorin kingthorin Feb 12, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I dropped the comment about sub-cats, they could be. It's 2024 and we should not be encountering flash anymore. (I think Silverlight is EOL too??? I'd have to dig) That's not 100% sure but it's close. I don't think there's much point splitting the refs up, as this rule should probably be retired <air_quotes>soon</air_quotes>

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The file is not just about Flash though.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know it's flash and silver light but I believe SL is rolling or headed roll as well.

Either way the comment is no longer necessary.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I mean the Adobe file is not just for Flash, it's for other Adobe programs too (not arguing against just saying).

Agreed.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh okay, I didn't realize they had other techs using it.

ascanbeta.crossdomain.silverlight.desc = Silverlight based cross-site request forgery may be possible, due to a misconfiguration on the web server.
ascanbeta.crossdomain.silverlight.extrainfo = The web server permits malicious cross-domain requests originating from Silverlight components served from any third party domain, to this domain. If the victim user is logged into this service, the malicious requests are processed using the privileges of the victim, and can result in data from this service being compromised by an unauthorised third party web site, via the victim's web browsers. It can also result in Cross Site Request Forgery (CSRF) type attacks. This is particularly likely to be an issue if a Cookie based session implementation is in use.
ascanbeta.crossdomain.silverlight.name = Cross-Domain Misconfiguration - Silverlight
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,10 @@
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.is;

import java.util.List;
import java.util.Map;
import org.junit.jupiter.api.Test;
import org.parosproxy.paros.core.scanner.Alert;
import org.zaproxy.addon.commonlib.CommonAlertTag;

class CrossDomainScanRuleUnitTest extends ActiveScannerTest<CrossDomainScanRule> {
Expand Down Expand Up @@ -63,4 +65,24 @@ void shouldReturnExpectedMappings() {
tags.get(CommonAlertTag.WSTG_V42_CONF_08_RIA_CROSS_DOMAIN.getTag()),
is(equalTo(CommonAlertTag.WSTG_V42_CONF_08_RIA_CROSS_DOMAIN.getValue())));
}

@Test
void shouldHaveExpectedExampleAlert() {
// Given / When
List<Alert> alerts = rule.getExampleAlerts();
// Then
assertThat(alerts.size(), is(equalTo(3)));
Alert adobeRead = alerts.get(0);
assertThat(adobeRead.getAlertRef(), is(equalTo("20016-1")));
Alert adobeSend = alerts.get(1);
assertThat(adobeSend.getAlertRef(), is(equalTo("20016-2")));
Alert silverlight = alerts.get(2);
assertThat(silverlight.getAlertRef(), is(equalTo("20016-3")));
}

@Test
@Override
public void shouldHaveValidReferences() {
super.shouldHaveValidReferences();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
import java.util.TreeSet;
import org.apache.commons.httpclient.URIException;
import org.junit.jupiter.api.Test;
import org.parosproxy.paros.core.scanner.Alert;
import org.parosproxy.paros.core.scanner.Plugin.AlertThreshold;
import org.parosproxy.paros.model.Model;
import org.parosproxy.paros.model.OptionsParam;
Expand Down Expand Up @@ -316,6 +317,20 @@ void shouldReturnExpectedMappings() {
is(equalTo(CommonAlertTag.WSTG_V42_SESS_05_CSRF.getValue())));
}

@Test
void shouldHaveExpectedExampleAlert() {
// Given / When
List<Alert> alerts = rule.getExampleAlerts();
// Then
assertThat(alerts.size(), is(equalTo(1)));
}

@Test
@Override
public void shouldHaveValidReferences() {
super.shouldHaveValidReferences();
}

private HttpMessage createMessage(boolean isInScope)
throws URIException, HttpMalformedHeaderException {
HttpMessage msg =
Expand Down
Loading
Loading