File tree Expand file tree Collapse file tree 4 files changed +60
-0
lines changed
test/query-tests/Security/CWE-640 Expand file tree Collapse file tree 4 files changed +60
-0
lines changed Original file line number Diff line number Diff line change 1+ /**
2+ * @name Host header poisoning in email generation
3+ * @description Using the HTTP Host header to construct a link in an email can facilitate phishing attacks and leak password reset tokens.
4+ * @kind problem
5+ * @problem.severity error
6+ * @precision high
7+ * @id js/host-header-forgery-in-email-generation
8+ * @tags security
9+ * external/cwe/cwe-640
10+ */
11+ import javascript
12+
13+ class TaintedHostHeader extends TaintTracking:: Configuration {
14+ TaintedHostHeader ( ) { this = "TaintedHostHeader" }
15+
16+ override predicate isSource ( DataFlow:: Node node ) {
17+ exists ( HTTP:: RequestInputAccess input | node = input |
18+ input .getKind ( ) = "header" and
19+ input .getAHeaderName ( ) = "host" )
20+ }
21+
22+ override predicate isSink ( DataFlow:: Node node ) {
23+ exists ( EmailSender email | node = email .getABody ( ) )
24+ }
25+ }
26+
27+ from TaintedHostHeader taint , DataFlow:: Node src , DataFlow:: Node sink
28+ where taint .hasFlow ( src , sink )
29+ select sink , "Links in this email can be hijacked by poisoning the HTTP host header $@." , src , "here"
Original file line number Diff line number Diff line change 1+ | 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 |
2+ | 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 |
Original file line number Diff line number Diff line change 1+ Security/CWE-640/HostHeaderPoisoningInEmailGeneration.ql
Original file line number Diff line number Diff line change 1+ let nodemailer = require ( 'nodemailer' ) ;
2+ let express = require ( 'express' ) ;
3+ let app = express ( ) ;
4+ let backend = require ( './backend' ) ;
5+
6+ app . post ( '/resetpass' , ( req , res ) => {
7+ let email = req . query . email ;
8+
9+ let transport = nodemailer . createTransport ( { } ) ;
10+
11+ let token = backend . getUserSecretResetToken ( email ) ;
12+
13+ transport . sendMail ( {
14+ from : 'webmaster@example.com' ,
15+ to : email ,
16+ subject : 'Forgot password' ,
17+ text : `Hi, looks like you forgot your password. Click here to reset: https://${ req . host } /resettoken/${ token } ` , // NOT OK
18+ html : `Hi, looks like you forgot your password. Click <a href="https://${ req . host } /resettoken/${ token } ">here</a> to reset.` // NOT OK
19+ } ) ;
20+
21+ transport . sendMail ( {
22+ from : 'webmaster@example.com' ,
23+ to : email ,
24+ subject : 'Forgot password' ,
25+ text : `Hi, looks like you forgot your password. Click here to reset: https://example.com/resettoken/${ token } ` , // OK
26+ html : `Hi, looks like you forgot your password. Click <a href="https://example.com/resettoken/${ token } ">here</a> to reset.` // OK
27+ } ) ;
28+ } ) ;
You can’t perform that action at this time.
0 commit comments