JS: Write help for ClientSideRequestForgery

This commit is contained in:
Asger Feldthaus
2022-02-16 10:58:27 +01:00
parent 91c64152d2
commit 8ac0ec8dfc
3 changed files with 93 additions and 0 deletions

View File

@@ -0,0 +1,81 @@
<!DOCTYPE qhelp PUBLIC
"-//Semmle//qhelp//EN"
"qhelp.dtd">
<qhelp>
<overview>
<p>
Directly incorporating user input in the URL of an outgoing HTTP request
can enable a request forgery attack, in which the request is altered to
target an unintended API endpoint or resource.
A client-side forged request may perform an unwanted action affecting the victim's account,
or may lead to cross-site scripting if the request response is handled in an unsafe way.
This is different from CSRF (cross-site request forgery), and will usually bypass CSRF protections.
This is usually less severe than SSRF (server-side request forgery), as it does not expose internal services.
</p>
</overview>
<recommendation>
<p>
Restrict user inputs in the URL of an outgoing request, in particular:
<ul>
<li>
Avoid user input in the hostname of the URL.
Pick the hostname from an allow-list instead of constructing it directly from user input.
</li>
<li>
Take care when user input is part of the pathname of the URL.
Restrict the input so that path traversal ("<code>../<code>")
cannot be used to redirect the request to an unintended endpoint.
</li>
</ul>
</p>
</recommendation>
<example>
<p>
The following example shows an HTTP request used to fetch the pre-rendered
HTML body of a message. It is using the endpoint <code>/api/messages/ID</code>, which
is believed to respond with a safe HTML string, to be embedded in the page:
</p>
<sample src="examples/ClientSideRequestForgeryBad.js"/>
<p>
However, the format of the message ID is not checked, and an attacker can abuse this to
alter the endpoint targeted by the request. If they can redirect it to an endpoint that returns
an untrusted value, this leads to cross-site scripting.
</p>
<p>
For example, given the query string <code>message_id=../pastebin/123</code>, the request will
end up targeting the <code>/api/pastebin</code> endpoint. Or if there is an open redirect on the login page,
a query string like <code>message_id=../../login?redirect_url=https://evil.com</code> could give
the attacker full control over the response as well.
</p>
<p>
In example below, the input has been restricted to a number so the endpoint cannot be altered:
</p>
<sample src="examples/ClientSideRequestForgeryGood.js"/>
</example>
<references>
<li>OWASP: <a href="https://cwe.mitre.org/data/definitions/918.html">Server-side request forgery</a></li>
<li>OWASP: <a href="https://cwe.mitre.org/data/definitions/352.html">Cross-site request forgery</a></li>
</references>
</qhelp>

View File

@@ -0,0 +1,6 @@
async function loadMessage() {
const query = new URLSearchParams(location.search);
const url = '/api/messages/' + query.get('message_id');
const data = await (await fetch(url)).json();
document.getElementById('message').innerHTML = data.html;
}

View File

@@ -0,0 +1,6 @@
async function loadMessage() {
const query = new URLSearchParams(location.search);
const url = '/api/messages/' + Number(query.get('message_id'));
const data = await (await fetch(url)).json();
document.getElementById('message').innerHTML = data.html;
}