-
Notifications
You must be signed in to change notification settings - Fork 126
Fix and improve taint-tracking through function arguments #129
Changes from all commits
d0e8d6e
5b0c48e
5e8e519
e632c75
be94f2b
5a96b0e
60a6c96
b177d58
a79f2b4
08f5451
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,2 @@ | ||
| lgtm,codescanning | ||
| * The query "Clear-text logging of sensitive information" has been improved to recognize more logging APIs, which may lead to more alerts. |
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -30,17 +30,9 @@ module EmailData { | |||||||||||||||||||||||||||||||||||||||
| private class SmtpData extends Range { | ||||||||||||||||||||||||||||||||||||||||
| SmtpData() { | ||||||||||||||||||||||||||||||||||||||||
| // func (c *Client) Data() (io.WriteCloser, error) | ||||||||||||||||||||||||||||||||||||||||
| exists(Method data, DataFlow::CallNode write, DataFlow::Node writer, int i | | ||||||||||||||||||||||||||||||||||||||||
| exists(Method data | | ||||||||||||||||||||||||||||||||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Since, we are changing this, we should also change the codeql-go/ql/src/semmle/go/frameworks/HTTP.qll Lines 144 to 162 in ca0d9cc
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In principle I agree, but in practice that is a little more difficult to change, since that class wants to refer both to the original source of the data as well as to the writer it is written to. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, I missed that. This can now be resolved. |
||||||||||||||||||||||||||||||||||||||||
| data.hasQualifiedName("net/smtp", "Client", "Data") and | ||||||||||||||||||||||||||||||||||||||||
| writer = data.getACall().getResult(0) and | ||||||||||||||||||||||||||||||||||||||||
| ( | ||||||||||||||||||||||||||||||||||||||||
| write.getTarget().hasQualifiedName("fmt", "Fprintf") | ||||||||||||||||||||||||||||||||||||||||
| or | ||||||||||||||||||||||||||||||||||||||||
| write.getTarget().hasQualifiedName("io", "WriteString") | ||||||||||||||||||||||||||||||||||||||||
| ) and | ||||||||||||||||||||||||||||||||||||||||
| writer.getASuccessor*() = write.getArgument(0) and | ||||||||||||||||||||||||||||||||||||||||
| i > 0 and | ||||||||||||||||||||||||||||||||||||||||
| write.getArgument(i) = this | ||||||||||||||||||||||||||||||||||||||||
| this.(DataFlow::SsaNode).getInit() = data.getACall().getResult(0) | ||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||
| or | ||||||||||||||||||||||||||||||||||||||||
| // func SendMail(addr string, a Auth, from string, to []string, msg []byte) error | ||||||||||||||||||||||||||||||||||||||||
|
|
@@ -55,15 +47,15 @@ module EmailData { | |||||||||||||||||||||||||||||||||||||||
| bindingset[result] | ||||||||||||||||||||||||||||||||||||||||
| private string sendgridMail() { result = "github.com/sendgrid/sendgrid-go/helpers/mail" } | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| /* Gets the value of the `i`th content parameter of the given `call` */ | ||||||||||||||||||||||||||||||||||||||||
| private DataFlow::Node getContent(DataFlow::CallNode call, int i) { | ||||||||||||||||||||||||||||||||||||||||
| exists(DataFlow::CallNode cn, DataFlow::Node content | | ||||||||||||||||||||||||||||||||||||||||
| private class NewContent extends TaintTracking::FunctionModel { | ||||||||||||||||||||||||||||||||||||||||
| NewContent() { | ||||||||||||||||||||||||||||||||||||||||
| // func NewContent(contentType string, value string) *Content | ||||||||||||||||||||||||||||||||||||||||
| cn.getTarget().hasQualifiedName(sendgridMail(), "NewContent") and | ||||||||||||||||||||||||||||||||||||||||
| cn.getResult() = content and | ||||||||||||||||||||||||||||||||||||||||
| content.getASuccessor*() = call.getArgument(i) and | ||||||||||||||||||||||||||||||||||||||||
| result = cn.getArgument(1) | ||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||
| this.hasQualifiedName(sendgridMail(), "NewContent") | ||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { | ||||||||||||||||||||||||||||||||||||||||
| input.isParameter(1) and output.isResult() | ||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| /** A data-flow node that is written to an email using the sendgrid/sendgrid-go package. */ | ||||||||||||||||||||||||||||||||||||||||
|
|
@@ -77,18 +69,45 @@ module EmailData { | |||||||||||||||||||||||||||||||||||||||
| or | ||||||||||||||||||||||||||||||||||||||||
| // func NewV3MailInit(from *Email, subject string, to *Email, content ...*Content) *SGMailV3 | ||||||||||||||||||||||||||||||||||||||||
| exists(Function newv3MailInit | | ||||||||||||||||||||||||||||||||||||||||
| newv3MailInit.hasQualifiedName(sendgridMail(), "NewV3MailInit") | ||||||||||||||||||||||||||||||||||||||||
| | | ||||||||||||||||||||||||||||||||||||||||
| this = getContent(newv3MailInit.getACall(), any(int i | i >= 3)) | ||||||||||||||||||||||||||||||||||||||||
| or | ||||||||||||||||||||||||||||||||||||||||
| this = newv3MailInit.getACall().getArgument(1) | ||||||||||||||||||||||||||||||||||||||||
| newv3MailInit.hasQualifiedName(sendgridMail(), "NewV3MailInit") and | ||||||||||||||||||||||||||||||||||||||||
| this = newv3MailInit.getACall().getArgument(any(int i | i = 1 or i >= 3)) | ||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||
| or | ||||||||||||||||||||||||||||||||||||||||
| // func (s *SGMailV3) AddContent(c ...*Content) *SGMailV3 | ||||||||||||||||||||||||||||||||||||||||
| exists(Method addContent | | ||||||||||||||||||||||||||||||||||||||||
| addContent.hasQualifiedName(sendgridMail(), "SGMailV3", "AddContent") and | ||||||||||||||||||||||||||||||||||||||||
| this = getContent(addContent.getACall(), _) | ||||||||||||||||||||||||||||||||||||||||
| this = addContent.getACall().getAnArgument() | ||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| /** | ||||||||||||||||||||||||||||||||||||||||
| * A taint model of the `Writer.CreatePart` method from `mime/multipart`. | ||||||||||||||||||||||||||||||||||||||||
| * | ||||||||||||||||||||||||||||||||||||||||
| * If tainted data is written to the multipart section created by this method, the underlying writer | ||||||||||||||||||||||||||||||||||||||||
| * should be considered tainted as well. | ||||||||||||||||||||||||||||||||||||||||
| */ | ||||||||||||||||||||||||||||||||||||||||
| private class MultipartWriterCreatePartModel extends TaintTracking::FunctionModel, Method { | ||||||||||||||||||||||||||||||||||||||||
| MultipartWriterCreatePartModel() { | ||||||||||||||||||||||||||||||||||||||||
| this.hasQualifiedName("mime/multipart", "Writer", "CreatePart") | ||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { | ||||||||||||||||||||||||||||||||||||||||
| input.isResult(0) and output.isReceiver() | ||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| /** | ||||||||||||||||||||||||||||||||||||||||
| * A taint model of the `NewWriter` function from `mime/multipart`. | ||||||||||||||||||||||||||||||||||||||||
| * | ||||||||||||||||||||||||||||||||||||||||
| * If tainted data is written to the writer created by this function, the underlying writer | ||||||||||||||||||||||||||||||||||||||||
| * should be considered tainted as well. | ||||||||||||||||||||||||||||||||||||||||
| */ | ||||||||||||||||||||||||||||||||||||||||
| private class MultipartNewWriterModel extends TaintTracking::FunctionModel { | ||||||||||||||||||||||||||||||||||||||||
| MultipartNewWriterModel() { this.hasQualifiedName("mime/multipart", "NewWriter") } | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { | ||||||||||||||||||||||||||||||||||||||||
| input.isResult() and output.isParameter(0) | ||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,37 +1,43 @@ | ||
| edges | ||
| | email.go:24:10:24:17 | selection of Header : Header | email.go:27:56:27:67 | type conversion | | ||
| | email.go:34:21:34:31 | call to Referer : string | email.go:36:57:36:78 | type conversion | | ||
| | email.go:42:21:42:31 | call to Referer : string | email.go:46:25:46:38 | untrustedInput | | ||
| | email.go:42:21:42:31 | call to Referer : string | email.go:45:3:45:7 | definition of write | | ||
| | email.go:51:21:51:31 | call to Referer : string | email.go:57:46:57:59 | untrustedInput | | ||
| | email.go:51:21:51:31 | call to Referer : string | email.go:58:52:58:65 | untrustedInput | | ||
| | email.go:63:21:63:31 | call to Referer : string | email.go:65:47:65:60 | untrustedInput | | ||
| | email.go:73:21:73:31 | call to Referer : string | email.go:79:47:79:60 | untrustedInput | | ||
| | email.go:63:21:63:31 | call to Referer : string | email.go:68:16:68:22 | content | | ||
| | email.go:73:21:73:31 | call to Referer : string | email.go:81:50:81:56 | content | | ||
| | email.go:73:21:73:31 | call to Referer : string | email.go:81:59:81:65 | content | | ||
| | email.go:73:21:73:31 | call to Referer : string | email.go:82:16:82:22 | content | | ||
| | email.go:87:21:87:31 | call to Referer : string | email.go:94:37:94:50 | untrustedInput | | ||
| | email.go:87:21:87:31 | call to Referer : string | email.go:96:48:96:61 | untrustedInput | | ||
| | email.go:87:21:87:31 | call to Referer : string | email.go:98:16:98:23 | content2 | | ||
| nodes | ||
| | email.go:24:10:24:17 | selection of Header : Header | semmle.label | selection of Header : Header | | ||
| | email.go:27:56:27:67 | type conversion | semmle.label | type conversion | | ||
| | email.go:34:21:34:31 | call to Referer : string | semmle.label | call to Referer : string | | ||
| | email.go:36:57:36:78 | type conversion | semmle.label | type conversion | | ||
| | email.go:42:21:42:31 | call to Referer : string | semmle.label | call to Referer : string | | ||
| | email.go:46:25:46:38 | untrustedInput | semmle.label | untrustedInput | | ||
| | email.go:45:3:45:7 | definition of write | semmle.label | definition of write | | ||
| | email.go:51:21:51:31 | call to Referer : string | semmle.label | call to Referer : string | | ||
| | email.go:57:46:57:59 | untrustedInput | semmle.label | untrustedInput | | ||
| | email.go:58:52:58:65 | untrustedInput | semmle.label | untrustedInput | | ||
| | email.go:63:21:63:31 | call to Referer : string | semmle.label | call to Referer : string | | ||
| | email.go:65:47:65:60 | untrustedInput | semmle.label | untrustedInput | | ||
| | email.go:68:16:68:22 | content | semmle.label | content | | ||
| | email.go:73:21:73:31 | call to Referer : string | semmle.label | call to Referer : string | | ||
| | email.go:79:47:79:60 | untrustedInput | semmle.label | untrustedInput | | ||
| | email.go:81:50:81:56 | content | semmle.label | content | | ||
| | email.go:81:59:81:65 | content | semmle.label | content | | ||
| | email.go:82:16:82:22 | content | semmle.label | content | | ||
| | email.go:87:21:87:31 | call to Referer : string | semmle.label | call to Referer : string | | ||
| | email.go:94:37:94:50 | untrustedInput | semmle.label | untrustedInput | | ||
| | email.go:96:48:96:61 | untrustedInput | semmle.label | untrustedInput | | ||
| | email.go:98:16:98:23 | content2 | semmle.label | content2 | | ||
| #select | ||
| | email.go:27:56:27:67 | type conversion | email.go:24:10:24:17 | selection of Header : Header | email.go:27:56:27:67 | type conversion | Email content may contain $@. | email.go:24:10:24:17 | selection of Header | untrusted input | | ||
| | email.go:36:57:36:78 | type conversion | email.go:34:21:34:31 | call to Referer : string | email.go:36:57:36:78 | type conversion | Email content may contain $@. | email.go:34:21:34:31 | call to Referer | untrusted input | | ||
| | email.go:46:25:46:38 | untrustedInput | email.go:42:21:42:31 | call to Referer : string | email.go:46:25:46:38 | untrustedInput | Email content may contain $@. | email.go:42:21:42:31 | call to Referer | untrusted input | | ||
| | email.go:45:3:45:7 | definition of write | email.go:42:21:42:31 | call to Referer : string | email.go:45:3:45:7 | definition of write | Email content may contain $@. | email.go:42:21:42:31 | call to Referer | untrusted input | | ||
| | email.go:57:46:57:59 | untrustedInput | email.go:51:21:51:31 | call to Referer : string | email.go:57:46:57:59 | untrustedInput | Email content may contain $@. | email.go:51:21:51:31 | call to Referer | untrusted input | | ||
| | email.go:58:52:58:65 | untrustedInput | email.go:51:21:51:31 | call to Referer : string | email.go:58:52:58:65 | untrustedInput | Email content may contain $@. | email.go:51:21:51:31 | call to Referer | untrusted input | | ||
| | email.go:65:47:65:60 | untrustedInput | email.go:63:21:63:31 | call to Referer : string | email.go:65:47:65:60 | untrustedInput | Email content may contain $@. | email.go:63:21:63:31 | call to Referer | untrusted input | | ||
| | email.go:79:47:79:60 | untrustedInput | email.go:73:21:73:31 | call to Referer : string | email.go:79:47:79:60 | untrustedInput | Email content may contain $@. | email.go:73:21:73:31 | call to Referer | untrusted input | | ||
| | email.go:68:16:68:22 | content | email.go:63:21:63:31 | call to Referer : string | email.go:68:16:68:22 | content | Email content may contain $@. | email.go:63:21:63:31 | call to Referer | untrusted input | | ||
| | email.go:81:50:81:56 | content | email.go:73:21:73:31 | call to Referer : string | email.go:81:50:81:56 | content | Email content may contain $@. | email.go:73:21:73:31 | call to Referer | untrusted input | | ||
| | email.go:81:59:81:65 | content | email.go:73:21:73:31 | call to Referer : string | email.go:81:59:81:65 | content | Email content may contain $@. | email.go:73:21:73:31 | call to Referer | untrusted input | | ||
| | email.go:82:16:82:22 | content | email.go:73:21:73:31 | call to Referer : string | email.go:82:16:82:22 | content | Email content may contain $@. | email.go:73:21:73:31 | call to Referer | untrusted input | | ||
| | email.go:94:37:94:50 | untrustedInput | email.go:87:21:87:31 | call to Referer : string | email.go:94:37:94:50 | untrustedInput | Email content may contain $@. | email.go:87:21:87:31 | call to Referer | untrusted input | | ||
| | email.go:96:48:96:61 | untrustedInput | email.go:87:21:87:31 | call to Referer : string | email.go:96:48:96:61 | untrustedInput | Email content may contain $@. | email.go:87:21:87:31 | call to Referer | untrusted input | | ||
| | email.go:98:16:98:23 | content2 | email.go:87:21:87:31 | call to Referer : string | email.go:98:16:98:23 | content2 | Email content may contain $@. | email.go:87:21:87:31 | call to Referer | untrusted input | |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,9 @@ | ||
| | mail.go:15:73:15:94 | type conversion | | ||
| | mail.go:18:19:18:23 | definition of write | | ||
| | mail.go:26:49:26:52 | text | | ||
| | mail.go:26:76:26:79 | text | | ||
| | mail.go:27:20:27:23 | text | | ||
| | mail.go:31:33:31:39 | content | | ||
| | mail.go:36:52:36:55 | text | | ||
| | mail.go:36:79:36:86 | content2 | | ||
| | mail.go:37:20:37:27 | content3 | |
This file was deleted.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am not sure I understand this well yet but why is the index start from -1?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If there is more than one result, we number them starting from zero. If there is only a single result, we number it as -1. It's an implementation detail that isn't exposed in the API, so nothing to worry about.