mirror of
https://github.com/github/codeql.git
synced 2026-05-03 04:39:29 +02:00
JS: Add HostHeaderPoisoningInEmailGeneration query
This commit is contained in:
@@ -0,0 +1,29 @@
|
||||
/**
|
||||
* @name Host header poisoning in email generation
|
||||
* @description Using the HTTP Host header to construct a link in an email can facilitate phishing attacks and leak password reset tokens.
|
||||
* @kind problem
|
||||
* @problem.severity error
|
||||
* @precision high
|
||||
* @id js/host-header-forgery-in-email-generation
|
||||
* @tags security
|
||||
* external/cwe/cwe-640
|
||||
*/
|
||||
import javascript
|
||||
|
||||
class TaintedHostHeader extends TaintTracking::Configuration {
|
||||
TaintedHostHeader() { this = "TaintedHostHeader" }
|
||||
|
||||
override predicate isSource(DataFlow::Node node) {
|
||||
exists (HTTP::RequestInputAccess input | node = input |
|
||||
input.getKind() = "header" and
|
||||
input.getAHeaderName() = "host")
|
||||
}
|
||||
|
||||
override predicate isSink(DataFlow::Node node) {
|
||||
exists (EmailSender email | node = email.getABody())
|
||||
}
|
||||
}
|
||||
|
||||
from TaintedHostHeader taint, DataFlow::Node src, DataFlow::Node sink
|
||||
where taint.hasFlow(src, sink)
|
||||
select sink, "Links in this email can be hijacked by poisoning the HTTP host header $@.", src, "here"
|
||||
@@ -0,0 +1,2 @@
|
||||
| tst.js:17:11:17:113 | `Hi, lo ... token}` | Links in this email can be hijacked by poisoning the HTTP host header $@. | tst.js:17:84:17:91 | req.host | here |
|
||||
| tst.js:18:11:18:127 | `Hi, lo ... reset.` | Links in this email can be hijacked by poisoning the HTTP host header $@. | tst.js:18:78:18:85 | req.host | here |
|
||||
@@ -0,0 +1 @@
|
||||
Security/CWE-640/HostHeaderPoisoningInEmailGeneration.ql
|
||||
28
javascript/ql/test/query-tests/Security/CWE-640/tst.js
Normal file
28
javascript/ql/test/query-tests/Security/CWE-640/tst.js
Normal file
@@ -0,0 +1,28 @@
|
||||
let nodemailer = require('nodemailer');
|
||||
let express = require('express');
|
||||
let app = express();
|
||||
let backend = require('./backend');
|
||||
|
||||
app.post('/resetpass', (req, res) => {
|
||||
let email = req.query.email;
|
||||
|
||||
let transport = nodemailer.createTransport({});
|
||||
|
||||
let token = backend.getUserSecretResetToken(email);
|
||||
|
||||
transport.sendMail({
|
||||
from: 'webmaster@example.com',
|
||||
to: email,
|
||||
subject: 'Forgot password',
|
||||
text: `Hi, looks like you forgot your password. Click here to reset: https://${req.host}/resettoken/${token}`, // NOT OK
|
||||
html: `Hi, looks like you forgot your password. Click <a href="https://${req.host}/resettoken/${token}">here</a> to reset.` // NOT OK
|
||||
});
|
||||
|
||||
transport.sendMail({
|
||||
from: 'webmaster@example.com',
|
||||
to: email,
|
||||
subject: 'Forgot password',
|
||||
text: `Hi, looks like you forgot your password. Click here to reset: https://example.com/resettoken/${token}`, // OK
|
||||
html: `Hi, looks like you forgot your password. Click <a href="https://example.com/resettoken/${token}">here</a> to reset.` // OK
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user