Skip to content

Commit 57fbd53

Browse files
committed
Add Email Injection tests for reverse flow models
1 parent fd699f5 commit 57fbd53

File tree

4 files changed

+137
-72
lines changed

4 files changed

+137
-72
lines changed

go/ql/test/query-tests/Security/CWE-640/EmailBad.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@ import (
66
)
77

88
func mail(w http.ResponseWriter, r *http.Request) {
9-
host := r.Header.Get("Host")
9+
host := r.Header.Get("Host") // $ Source
1010
token := backend.getUserSecretResetToken(email)
1111
body := "Click to reset password: " + host + "/" + token
12-
smtp.SendMail("test.test", nil, "from@from.com", nil, []byte(body))
12+
smtp.SendMail("test.test", nil, "from@from.com", nil, []byte(body)) // $ Alert
1313
}
Lines changed: 82 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -1,66 +1,94 @@
11
#select
22
| EmailBad.go:12:56:12:67 | type conversion | EmailBad.go:9:10:9:17 | selection of Header | EmailBad.go:12:56:12:67 | type conversion | Email content may contain $@. | EmailBad.go:9:10:9:17 | selection of Header | untrusted input |
3-
| main.go:31:57:31:78 | type conversion | main.go:29:21:29:31 | call to Referer | main.go:31:57:31:78 | type conversion | Email content may contain $@. | main.go:29:21:29:31 | call to Referer | untrusted input |
4-
| main.go:40:3:40:7 | definition of write | main.go:37:21:37:31 | call to Referer | main.go:40:3:40:7 | definition of write | Email content may contain $@. | main.go:37:21:37:31 | call to Referer | untrusted input |
5-
| main.go:52:46:52:59 | untrustedInput | main.go:46:21:46:31 | call to Referer | main.go:52:46:52:59 | untrustedInput | Email content may contain $@. | main.go:46:21:46:31 | call to Referer | untrusted input |
6-
| main.go:53:52:53:65 | untrustedInput | main.go:46:21:46:31 | call to Referer | main.go:53:52:53:65 | untrustedInput | Email content may contain $@. | main.go:46:21:46:31 | call to Referer | untrusted input |
7-
| main.go:63:16:63:22 | content | main.go:58:21:58:31 | call to Referer | main.go:63:16:63:22 | content | Email content may contain $@. | main.go:58:21:58:31 | call to Referer | untrusted input |
8-
| main.go:76:50:76:56 | content | main.go:68:21:68:31 | call to Referer | main.go:76:50:76:56 | content | Email content may contain $@. | main.go:68:21:68:31 | call to Referer | untrusted input |
9-
| main.go:76:59:76:65 | content | main.go:68:21:68:31 | call to Referer | main.go:76:59:76:65 | content | Email content may contain $@. | main.go:68:21:68:31 | call to Referer | untrusted input |
10-
| main.go:77:16:77:22 | content | main.go:68:21:68:31 | call to Referer | main.go:77:16:77:22 | content | Email content may contain $@. | main.go:68:21:68:31 | call to Referer | untrusted input |
11-
| main.go:89:37:89:50 | untrustedInput | main.go:82:21:82:31 | call to Referer | main.go:89:37:89:50 | untrustedInput | Email content may contain $@. | main.go:82:21:82:31 | call to Referer | untrusted input |
12-
| main.go:93:16:93:23 | content2 | main.go:82:21:82:31 | call to Referer | main.go:93:16:93:23 | content2 | Email content may contain $@. | main.go:82:21:82:31 | call to Referer | untrusted input |
3+
| main.go:33:57:33:78 | type conversion | main.go:31:21:31:31 | call to Referer | main.go:33:57:33:78 | type conversion | Email content may contain $@. | main.go:31:21:31:31 | call to Referer | untrusted input |
4+
| main.go:42:3:42:7 | definition of write | main.go:39:21:39:31 | call to Referer | main.go:42:3:42:7 | definition of write | Email content may contain $@. | main.go:39:21:39:31 | call to Referer | untrusted input |
5+
| main.go:54:46:54:59 | untrustedInput | main.go:48:21:48:31 | call to Referer | main.go:54:46:54:59 | untrustedInput | Email content may contain $@. | main.go:48:21:48:31 | call to Referer | untrusted input |
6+
| main.go:55:52:55:65 | untrustedInput | main.go:48:21:48:31 | call to Referer | main.go:55:52:55:65 | untrustedInput | Email content may contain $@. | main.go:48:21:48:31 | call to Referer | untrusted input |
7+
| main.go:65:16:65:22 | content | main.go:60:21:60:31 | call to Referer | main.go:65:16:65:22 | content | Email content may contain $@. | main.go:60:21:60:31 | call to Referer | untrusted input |
8+
| main.go:78:50:78:56 | content | main.go:70:21:70:31 | call to Referer | main.go:78:50:78:56 | content | Email content may contain $@. | main.go:70:21:70:31 | call to Referer | untrusted input |
9+
| main.go:78:59:78:65 | content | main.go:70:21:70:31 | call to Referer | main.go:78:59:78:65 | content | Email content may contain $@. | main.go:70:21:70:31 | call to Referer | untrusted input |
10+
| main.go:79:16:79:22 | content | main.go:70:21:70:31 | call to Referer | main.go:79:16:79:22 | content | Email content may contain $@. | main.go:70:21:70:31 | call to Referer | untrusted input |
11+
| main.go:91:37:91:50 | untrustedInput | main.go:84:21:84:31 | call to Referer | main.go:91:37:91:50 | untrustedInput | Email content may contain $@. | main.go:84:21:84:31 | call to Referer | untrusted input |
12+
| main.go:95:16:95:23 | content2 | main.go:84:21:84:31 | call to Referer | main.go:95:16:95:23 | content2 | Email content may contain $@. | main.go:84:21:84:31 | call to Referer | untrusted input |
13+
| main.go:124:57:124:65 | call to Bytes | main.go:113:21:113:31 | call to Referer | main.go:124:57:124:65 | call to Bytes | Email content may contain $@. | main.go:113:21:113:31 | call to Referer | untrusted input |
14+
| main.go:141:57:141:65 | call to Bytes | main.go:129:21:129:31 | call to Referer | main.go:141:57:141:65 | call to Bytes | Email content may contain $@. | main.go:129:21:129:31 | call to Referer | untrusted input |
1315
edges
14-
| EmailBad.go:9:10:9:17 | selection of Header | EmailBad.go:9:10:9:29 | call to Get | provenance | Src:MaD:1 MaD:5 |
16+
| EmailBad.go:9:10:9:17 | selection of Header | EmailBad.go:9:10:9:29 | call to Get | provenance | Src:MaD:1 MaD:7 |
1517
| EmailBad.go:9:10:9:29 | call to Get | EmailBad.go:12:56:12:67 | type conversion | provenance | |
16-
| main.go:29:21:29:31 | call to Referer | main.go:31:57:31:78 | type conversion | provenance | Src:MaD:2 |
17-
| main.go:37:21:37:31 | call to Referer | main.go:41:25:41:38 | untrustedInput | provenance | Src:MaD:2 |
18-
| main.go:41:25:41:38 | untrustedInput | main.go:40:3:40:7 | definition of write | provenance | MaD:4 |
19-
| main.go:46:21:46:31 | call to Referer | main.go:52:46:52:59 | untrustedInput | provenance | Src:MaD:2 |
20-
| main.go:46:21:46:31 | call to Referer | main.go:53:52:53:65 | untrustedInput | provenance | Src:MaD:2 |
21-
| main.go:58:21:58:31 | call to Referer | main.go:60:47:60:60 | untrustedInput | provenance | Src:MaD:2 |
22-
| main.go:60:14:60:61 | call to NewContent | main.go:63:16:63:22 | content | provenance | |
23-
| main.go:60:47:60:60 | untrustedInput | main.go:60:14:60:61 | call to NewContent | provenance | MaD:3 |
24-
| main.go:68:21:68:31 | call to Referer | main.go:74:47:74:60 | untrustedInput | provenance | Src:MaD:2 |
25-
| main.go:74:14:74:61 | call to NewContent | main.go:76:50:76:56 | content | provenance | |
26-
| main.go:74:14:74:61 | call to NewContent | main.go:76:59:76:65 | content | provenance | |
27-
| main.go:74:14:74:61 | call to NewContent | main.go:77:16:77:22 | content | provenance | |
28-
| main.go:74:47:74:60 | untrustedInput | main.go:74:14:74:61 | call to NewContent | provenance | MaD:3 |
29-
| main.go:82:21:82:31 | call to Referer | main.go:89:37:89:50 | untrustedInput | provenance | Src:MaD:2 |
30-
| main.go:82:21:82:31 | call to Referer | main.go:91:48:91:61 | untrustedInput | provenance | Src:MaD:2 |
31-
| main.go:91:15:91:62 | call to NewContent | main.go:93:16:93:23 | content2 | provenance | |
32-
| main.go:91:48:91:61 | untrustedInput | main.go:91:15:91:62 | call to NewContent | provenance | MaD:3 |
18+
| main.go:31:21:31:31 | call to Referer | main.go:33:57:33:78 | type conversion | provenance | Src:MaD:2 |
19+
| main.go:39:21:39:31 | call to Referer | main.go:43:25:43:38 | untrustedInput | provenance | Src:MaD:2 |
20+
| main.go:43:25:43:38 | untrustedInput | main.go:42:3:42:7 | definition of write | provenance | MaD:5 |
21+
| main.go:48:21:48:31 | call to Referer | main.go:54:46:54:59 | untrustedInput | provenance | Src:MaD:2 |
22+
| main.go:48:21:48:31 | call to Referer | main.go:55:52:55:65 | untrustedInput | provenance | Src:MaD:2 |
23+
| main.go:60:21:60:31 | call to Referer | main.go:62:47:62:60 | untrustedInput | provenance | Src:MaD:2 |
24+
| main.go:62:14:62:61 | call to NewContent | main.go:65:16:65:22 | content | provenance | |
25+
| main.go:62:47:62:60 | untrustedInput | main.go:62:14:62:61 | call to NewContent | provenance | MaD:4 |
26+
| main.go:70:21:70:31 | call to Referer | main.go:76:47:76:60 | untrustedInput | provenance | Src:MaD:2 |
27+
| main.go:76:14:76:61 | call to NewContent | main.go:78:50:78:56 | content | provenance | |
28+
| main.go:76:14:76:61 | call to NewContent | main.go:78:59:78:65 | content | provenance | |
29+
| main.go:76:14:76:61 | call to NewContent | main.go:79:16:79:22 | content | provenance | |
30+
| main.go:76:47:76:60 | untrustedInput | main.go:76:14:76:61 | call to NewContent | provenance | MaD:4 |
31+
| main.go:84:21:84:31 | call to Referer | main.go:91:37:91:50 | untrustedInput | provenance | Src:MaD:2 |
32+
| main.go:84:21:84:31 | call to Referer | main.go:93:48:93:61 | untrustedInput | provenance | Src:MaD:2 |
33+
| main.go:93:15:93:62 | call to NewContent | main.go:95:16:95:23 | content2 | provenance | |
34+
| main.go:93:48:93:61 | untrustedInput | main.go:93:15:93:62 | call to NewContent | provenance | MaD:4 |
35+
| main.go:113:21:113:31 | call to Referer | main.go:119:28:119:41 | untrustedInput | provenance | Src:MaD:2 |
36+
| main.go:116:3:116:4 | definition of mw | main.go:116:29:116:30 | &... | provenance | FunctionModel |
37+
| main.go:116:29:116:30 | &... | main.go:124:57:124:57 | b | provenance | |
38+
| main.go:119:28:119:41 | untrustedInput | main.go:116:3:116:4 | definition of mw | provenance | MaD:6 |
39+
| main.go:124:57:124:57 | b | main.go:124:57:124:65 | call to Bytes | provenance | MaD:3 |
40+
| main.go:129:21:129:31 | call to Referer | main.go:136:30:136:43 | untrustedInput | provenance | Src:MaD:2 |
41+
| main.go:132:3:132:4 | definition of mw | main.go:132:29:132:30 | &... | provenance | FunctionModel |
42+
| main.go:132:29:132:30 | &... | main.go:141:57:141:57 | b | provenance | |
43+
| main.go:135:3:135:12 | definition of formWriter | main.go:132:3:132:4 | definition of mw | provenance | FunctionModel |
44+
| main.go:136:30:136:43 | untrustedInput | main.go:135:3:135:12 | definition of formWriter | provenance | MaD:5 |
45+
| main.go:141:57:141:57 | b | main.go:141:57:141:65 | call to Bytes | provenance | MaD:3 |
3346
models
3447
| 1 | Source: net/http; Request; true; Header; ; ; ; remote; manual |
3548
| 2 | Source: net/http; Request; true; Referer; ; ; ReturnValue; remote; manual |
36-
| 3 | Summary: github.com/sendgrid/sendgrid-go/helpers/mail; ; false; NewContent; ; ; Argument[1]; ReturnValue; taint; manual |
37-
| 4 | Summary: io; ; false; WriteString; ; ; Argument[1]; Argument[0]; taint; manual |
38-
| 5 | Summary: net/http; Header; true; Get; ; ; Argument[receiver]; ReturnValue; taint; manual |
49+
| 3 | Summary: bytes; Buffer; true; Bytes; ; ; Argument[receiver]; ReturnValue; taint; manual |
50+
| 4 | Summary: github.com/sendgrid/sendgrid-go/helpers/mail; ; false; NewContent; ; ; Argument[1]; ReturnValue; taint; manual |
51+
| 5 | Summary: io; ; false; WriteString; ; ; Argument[1]; Argument[0]; taint; manual |
52+
| 6 | Summary: mime/multipart; Writer; true; WriteField; ; ; Argument[0..1]; Argument[receiver]; taint; manual |
53+
| 7 | Summary: net/http; Header; true; Get; ; ; Argument[receiver]; ReturnValue; taint; manual |
3954
nodes
4055
| EmailBad.go:9:10:9:17 | selection of Header | semmle.label | selection of Header |
4156
| EmailBad.go:9:10:9:29 | call to Get | semmle.label | call to Get |
4257
| EmailBad.go:12:56:12:67 | type conversion | semmle.label | type conversion |
43-
| main.go:29:21:29:31 | call to Referer | semmle.label | call to Referer |
44-
| main.go:31:57:31:78 | type conversion | semmle.label | type conversion |
45-
| main.go:37:21:37:31 | call to Referer | semmle.label | call to Referer |
46-
| main.go:40:3:40:7 | definition of write | semmle.label | definition of write |
47-
| main.go:41:25:41:38 | untrustedInput | semmle.label | untrustedInput |
48-
| main.go:46:21:46:31 | call to Referer | semmle.label | call to Referer |
49-
| main.go:52:46:52:59 | untrustedInput | semmle.label | untrustedInput |
50-
| main.go:53:52:53:65 | untrustedInput | semmle.label | untrustedInput |
51-
| main.go:58:21:58:31 | call to Referer | semmle.label | call to Referer |
52-
| main.go:60:14:60:61 | call to NewContent | semmle.label | call to NewContent |
53-
| main.go:60:47:60:60 | untrustedInput | semmle.label | untrustedInput |
54-
| main.go:63:16:63:22 | content | semmle.label | content |
55-
| main.go:68:21:68:31 | call to Referer | semmle.label | call to Referer |
56-
| main.go:74:14:74:61 | call to NewContent | semmle.label | call to NewContent |
57-
| main.go:74:47:74:60 | untrustedInput | semmle.label | untrustedInput |
58-
| main.go:76:50:76:56 | content | semmle.label | content |
59-
| main.go:76:59:76:65 | content | semmle.label | content |
60-
| main.go:77:16:77:22 | content | semmle.label | content |
61-
| main.go:82:21:82:31 | call to Referer | semmle.label | call to Referer |
62-
| main.go:89:37:89:50 | untrustedInput | semmle.label | untrustedInput |
63-
| main.go:91:15:91:62 | call to NewContent | semmle.label | call to NewContent |
64-
| main.go:91:48:91:61 | untrustedInput | semmle.label | untrustedInput |
65-
| main.go:93:16:93:23 | content2 | semmle.label | content2 |
58+
| main.go:31:21:31:31 | call to Referer | semmle.label | call to Referer |
59+
| main.go:33:57:33:78 | type conversion | semmle.label | type conversion |
60+
| main.go:39:21:39:31 | call to Referer | semmle.label | call to Referer |
61+
| main.go:42:3:42:7 | definition of write | semmle.label | definition of write |
62+
| main.go:43:25:43:38 | untrustedInput | semmle.label | untrustedInput |
63+
| main.go:48:21:48:31 | call to Referer | semmle.label | call to Referer |
64+
| main.go:54:46:54:59 | untrustedInput | semmle.label | untrustedInput |
65+
| main.go:55:52:55:65 | untrustedInput | semmle.label | untrustedInput |
66+
| main.go:60:21:60:31 | call to Referer | semmle.label | call to Referer |
67+
| main.go:62:14:62:61 | call to NewContent | semmle.label | call to NewContent |
68+
| main.go:62:47:62:60 | untrustedInput | semmle.label | untrustedInput |
69+
| main.go:65:16:65:22 | content | semmle.label | content |
70+
| main.go:70:21:70:31 | call to Referer | semmle.label | call to Referer |
71+
| main.go:76:14:76:61 | call to NewContent | semmle.label | call to NewContent |
72+
| main.go:76:47:76:60 | untrustedInput | semmle.label | untrustedInput |
73+
| main.go:78:50:78:56 | content | semmle.label | content |
74+
| main.go:78:59:78:65 | content | semmle.label | content |
75+
| main.go:79:16:79:22 | content | semmle.label | content |
76+
| main.go:84:21:84:31 | call to Referer | semmle.label | call to Referer |
77+
| main.go:91:37:91:50 | untrustedInput | semmle.label | untrustedInput |
78+
| main.go:93:15:93:62 | call to NewContent | semmle.label | call to NewContent |
79+
| main.go:93:48:93:61 | untrustedInput | semmle.label | untrustedInput |
80+
| main.go:95:16:95:23 | content2 | semmle.label | content2 |
81+
| main.go:113:21:113:31 | call to Referer | semmle.label | call to Referer |
82+
| main.go:116:3:116:4 | definition of mw | semmle.label | definition of mw |
83+
| main.go:116:29:116:30 | &... | semmle.label | &... |
84+
| main.go:119:28:119:41 | untrustedInput | semmle.label | untrustedInput |
85+
| main.go:124:57:124:57 | b | semmle.label | b |
86+
| main.go:124:57:124:65 | call to Bytes | semmle.label | call to Bytes |
87+
| main.go:129:21:129:31 | call to Referer | semmle.label | call to Referer |
88+
| main.go:132:3:132:4 | definition of mw | semmle.label | definition of mw |
89+
| main.go:132:29:132:30 | &... | semmle.label | &... |
90+
| main.go:135:3:135:12 | definition of formWriter | semmle.label | definition of formWriter |
91+
| main.go:136:30:136:43 | untrustedInput | semmle.label | untrustedInput |
92+
| main.go:141:57:141:57 | b | semmle.label | b |
93+
| main.go:141:57:141:65 | call to Bytes | semmle.label | call to Bytes |
6694
subpaths
Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,4 @@
11
query: Security/CWE-640/EmailInjection.ql
2-
postprocess: utils/test/PrettyPrintModels.ql
2+
postprocess:
3+
- utils/test/PrettyPrintModels.ql
4+
- utils/test/InlineExpectationsTestQuery.ql

go/ql/test/query-tests/Security/CWE-640/main.go

Lines changed: 50 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,13 @@ package main
33
//go:generate depstubber -vendor github.com/sendgrid/sendgrid-go/helpers/mail "" NewEmail,NewSingleEmail,NewContent,NewV3Mail,NewV3MailInit
44

55
import (
6+
"bytes"
67
"crypto/hmac"
78
"crypto/sha256"
89
"encoding/base64"
910
"io"
1011
"log"
12+
"mime/multipart"
1113
"net/http"
1214
"net/smtp"
1315

@@ -26,71 +28,71 @@ func main() {
2628

2729
// Not OK
2830
http.HandleFunc("/ex0", func(w http.ResponseWriter, r *http.Request) {
29-
untrustedInput := r.Referer()
31+
untrustedInput := r.Referer() // $ Source
3032

31-
smtp.SendMail("test.test", nil, "from@from.com", nil, []byte(untrustedInput))
33+
smtp.SendMail("test.test", nil, "from@from.com", nil, []byte(untrustedInput)) // $ Alert
3234

3335
})
3436

3537
// Not OK
3638
http.HandleFunc("/ex1", func(w http.ResponseWriter, r *http.Request) {
37-
untrustedInput := r.Referer()
39+
untrustedInput := r.Referer() // $ Source
3840

3941
s, _ := smtp.Dial("test.test")
40-
write, _ := s.Data()
42+
write, _ := s.Data() // $ Alert
4143
io.WriteString(write, untrustedInput)
4244
})
4345

4446
// Not OK
4547
http.HandleFunc("/ex2", func(w http.ResponseWriter, r *http.Request) {
46-
untrustedInput := r.Referer()
48+
untrustedInput := r.Referer() // $ Source
4749

4850
from := sendgrid.NewEmail("from", "from@from.com")
4951
to := sendgrid.NewEmail("to", "to@to.com")
5052
subject := "test"
5153
body := "body"
52-
sendgrid.NewSingleEmail(from, subject, to, untrustedInput, body)
53-
sendgrid.NewSingleEmail(from, subject, to, body, untrustedInput)
54+
sendgrid.NewSingleEmail(from, subject, to, untrustedInput, body) // $ Alert
55+
sendgrid.NewSingleEmail(from, subject, to, body, untrustedInput) // $ Alert
5456
})
5557

5658
// Not OK
5759
http.HandleFunc("/ex3", func(w http.ResponseWriter, r *http.Request) {
58-
untrustedInput := r.Referer()
60+
untrustedInput := r.Referer() // $ Source
5961

6062
content := sendgrid.NewContent("text/html", untrustedInput)
6163

6264
v := sendgrid.NewV3Mail()
63-
v.AddContent(content)
65+
v.AddContent(content) // $ Alert
6466
})
6567

6668
// Not OK
6769
http.HandleFunc("/ex4", func(w http.ResponseWriter, r *http.Request) {
68-
untrustedInput := r.Referer()
70+
untrustedInput := r.Referer() // $ Source
6971

7072
from := sendgrid.NewEmail("from", "from@from.com")
7173
to := sendgrid.NewEmail("to", "to@to.com")
7274
subject := "test"
7375

7476
content := sendgrid.NewContent("text/html", untrustedInput)
7577

76-
v := sendgrid.NewV3MailInit(from, subject, to, content, content)
77-
v.AddContent(content)
78+
v := sendgrid.NewV3MailInit(from, subject, to, content, content) // $ Alert
79+
v.AddContent(content) // $ Alert
7880
})
7981

8082
// Not OK
8183
http.HandleFunc("/ex5", func(w http.ResponseWriter, r *http.Request) {
82-
untrustedInput := r.Referer()
84+
untrustedInput := r.Referer() // $ Source
8385

8486
from := sendgrid.NewEmail("from", "from@from.com")
8587
to := sendgrid.NewEmail("to", "to@to.com")
8688

8789
content := sendgrid.NewContent("text/html", "test")
8890

89-
v := sendgrid.NewV3MailInit(from, untrustedInput, to, content, content)
91+
v := sendgrid.NewV3MailInit(from, untrustedInput, to, content, content) // $ Alert
9092

9193
content2 := sendgrid.NewContent("text/html", untrustedInput)
9294

93-
v.AddContent(content2)
95+
v.AddContent(content2) // $ Alert
9496
})
9597

9698
// OK
@@ -106,6 +108,39 @@ func main() {
106108
smtp.SendMail("test.test", nil, "from@from.com", nil, []byte(signature))
107109
})
108110

111+
// Not OK - mime/multipart.New.Writer test
112+
http.HandleFunc("/multipart1", func(w http.ResponseWriter, r *http.Request) {
113+
untrustedInput := r.Referer() // $ Source
114+
115+
var b bytes.Buffer
116+
mw := multipart.NewWriter(&b)
117+
118+
// Add user-controlled data directly to the multipart writer
119+
mw.WriteField("message", untrustedInput) // Injection point
120+
121+
mw.Close()
122+
123+
// Send the potentially malicious email content
124+
smtp.SendMail("test.test", nil, "from@from.com", nil, b.Bytes()) // $ Alert
125+
})
126+
127+
// Not OK - alternative multipart test
128+
http.HandleFunc("/multipart2", func(w http.ResponseWriter, r *http.Request) {
129+
untrustedInput := r.Referer() // $ Source
130+
131+
var b bytes.Buffer
132+
mw := multipart.NewWriter(&b)
133+
134+
// Create form file with untrusted content
135+
formWriter, _ := mw.CreateFormFile("attachment", "message.txt")
136+
io.WriteString(formWriter, untrustedInput) // Injection point
137+
138+
mw.Close()
139+
140+
// Send email with user-controlled form file content
141+
smtp.SendMail("test.test", nil, "from@from.com", nil, b.Bytes()) // $ Alert
142+
})
143+
109144
log.Println(http.ListenAndServe(":80", nil))
110145

111146
}

0 commit comments

Comments
 (0)