OpenUrlRedirect: make functions like isValidRedirect barrier guards

This commit is contained in:
Sauyon Lee
2020-01-09 01:09:19 -08:00
parent 82635a46ad
commit abfdd7ee1e
4 changed files with 38 additions and 3 deletions

View File

@@ -101,11 +101,13 @@ module OpenUrlRedirect {
}
/**
* A call to a function called `isLocalUrl` or similar, which is
* A call to a function called `isLocalUrl`, `isValidRedirect`, or similar, which is
* considered a barrier for purposes of URL redirection.
*/
class LocalUrlBarrierGuard extends BarrierGuard, DataFlow::CallNode {
LocalUrlBarrierGuard() { this.getCalleeName().regexpMatch("(?i)(is_?)?local_?url") }
class RedirectCheckBarrierGuard extends BarrierGuard, DataFlow::CallNode {
RedirectCheckBarrierGuard() {
this.getCalleeName().regexpMatch("(?i)(is_?)?(local_?url|valid_?redir(ect)?)")
}
override predicate checks(Expr e, boolean outcome) {
// `isLocalUrl(e)` is a barrier for `e` if it evaluates to `true`

View File

@@ -6,6 +6,7 @@ edges
| stdlib.go:43:13:43:18 | selection of Form : Values | stdlib.go:45:23:45:28 | target |
| stdlib.go:63:13:63:18 | selection of Form : Values | stdlib.go:66:23:66:40 | ...+... |
| stdlib.go:88:13:88:18 | selection of Form : Values | stdlib.go:91:23:91:28 | target |
| stdlib.go:133:13:133:18 | selection of Form : Values | stdlib.go:139:23:139:28 | target |
nodes
| OpenUrlRedirect.go:10:23:10:28 | selection of Form : Values | semmle.label | selection of Form : Values |
| OpenUrlRedirect.go:10:23:10:42 | call to Get | semmle.label | call to Get |
@@ -21,6 +22,8 @@ nodes
| stdlib.go:66:23:66:40 | ...+... | semmle.label | ...+... |
| stdlib.go:88:13:88:18 | selection of Form : Values | semmle.label | selection of Form : Values |
| stdlib.go:91:23:91:28 | target | semmle.label | target |
| stdlib.go:133:13:133:18 | selection of Form : Values | semmle.label | selection of Form : Values |
| stdlib.go:139:23:139:28 | target | semmle.label | target |
#select
| OpenUrlRedirect.go:10:23:10:42 | call to Get | OpenUrlRedirect.go:10:23:10:28 | selection of Form : Values | OpenUrlRedirect.go:10:23:10:42 | call to Get | Untrusted URL redirection due to $@. | OpenUrlRedirect.go:10:23:10:28 | selection of Form | user-provided value |
| stdlib.go:14:30:14:35 | target | stdlib.go:12:13:12:18 | selection of Form : Values | stdlib.go:14:30:14:35 | target | Untrusted URL redirection due to $@. | stdlib.go:12:13:12:18 | selection of Form | user-provided value |
@@ -29,3 +32,4 @@ nodes
| stdlib.go:45:23:45:28 | target | stdlib.go:43:13:43:18 | selection of Form : Values | stdlib.go:45:23:45:28 | target | Untrusted URL redirection due to $@. | stdlib.go:43:13:43:18 | selection of Form | user-provided value |
| stdlib.go:66:23:66:40 | ...+... | stdlib.go:63:13:63:18 | selection of Form : Values | stdlib.go:66:23:66:40 | ...+... | Untrusted URL redirection due to $@. | stdlib.go:63:13:63:18 | selection of Form | user-provided value |
| stdlib.go:91:23:91:28 | target | stdlib.go:88:13:88:18 | selection of Form : Values | stdlib.go:91:23:91:28 | target | Untrusted URL redirection due to $@. | stdlib.go:88:13:88:18 | selection of Form | user-provided value |
| stdlib.go:139:23:139:28 | target | stdlib.go:133:13:133:18 | selection of Form : Values | stdlib.go:139:23:139:28 | target | Untrusted URL redirection due to $@. | stdlib.go:133:13:133:18 | selection of Form | user-provided value |

View File

@@ -115,5 +115,29 @@ func serveStdlib() {
}
})
http.HandleFunc("/ex8", func(w http.ResponseWriter, r *http.Request) {
r.ParseForm()
target := r.Form.Get("target")
// GOOD: a check is done on the URL
if isValidRedirect(target) {
http.Redirect(w, r, target, 302)
} else {
// ...
}
})
http.HandleFunc("/ex9", func(w http.ResponseWriter, r *http.Request) {
r.ParseForm()
target := r.Form.Get("target")
// GOOD, but we catch this anyway: a check is done on the URL
if !isValidRedirect(target) {
target = "/"
}
http.Redirect(w, r, target, 302)
})
http.ListenAndServe(":80", nil)
}

View File

@@ -3,3 +3,8 @@ package main
const HASH = "#"
func someUrl() string { return "semmle.com" }
// placeholder
func isValidRedirect(s string) {
return true
}