this will cut you

this will cut you gos sharper edges human.txt thomas shadwell, - PowerPoint PPT Presentation

this will cut you gos sharper edges human.txt thomas shadwell, information security engineer @ twitch since ?? 2 years ago but who is counting haha am I right I used to, and still do bug bounties and white hat vuln reports, but

  1. this will cut you go’s sharper edges

  2. human.txt ● thomas shadwell, information security engineer @ twitch since ?? 2 years ago but who is counting haha am I right ● I used to, and still do bug bounties and white hat vuln reports, but these days almost entirely around areas I’m interested in (video games) ● video games (are good) ○ also good: video game communities ● we build a lot of things in Go

  3. purpose ● vulns like shellshock, heartbleed are exciting ● but most issues in software are common patterns of vulnerability that stem from the software ecosystem ● we can expend less energy looking for all the failure cases if we design our apis to be hard to write vulnerabilities with ● Go is a ‘no magic’ language, which makes security hard to do by accident; traditional abstraction can often lead to more difficulty

  4. lemma

  5. sidetrack lemma 2 ˈlɛmə/ noun BOTANY noun: lemma ; plural noun: lemmata ; plural noun: lemmas 1. the lower bract of the floret of a grass. mid 18th century (denoting the husk or shell of a fruit): from Greek, from lepein ‘to peel’.

  6. lemma 1: Reading Forever 1. standard way to read user input in Go a. bt, err := ioutil.ReadAll(r.Body) if err = json.Unmarshal(&structure); err != nil { return } b. If err := json.NewDecoder(r.Body).Decode(&strucure); err != nil { return} 2. input is read directly into memory or directly into the parser 3. parsers are not smart and don’t know when to stop 4. go kills itself when it runs out of memory 5. specially crafted inputs can DoS unprotected Go servers

  7. expanding on that ● exploitation ○ for JSON consuming applications you can push {“k… ○ for HTML consuming applications like `go get`, <a… ○ for applications using ioutil.ReadAll, essentially anything ○ if the planets align, you’re looking at as much bandwidth as the node has ram with as many connections as the max body size to kill the server ○ the cloud makes this transfer pretty fast ● caveats and mitigations ○ put your server behind nginx! ■ most http servers put in front of go will use a sensible limit ■ though it’s often disabled for user uploads ○ io.LimitedReader (simple), http.LimitedReader (more useful)

  8. sidetrack 2: deeper mitigations, static analysis ● go’s compiler is written in go ● you can make calls to the same libraries the compiler uses ● these days, they’re not that awful ● you can use SSA and call graph analysis to ask questions about the structure of programs pretty easily ● we can perform a callgraph analysis and ask if there are any possible paths between a user entry point such as request.Body and a function with the signature XXX.(Decode|Unmarshal)

  9. lemma 2: Content-Type Sniffing 1. several patterns can allow attackers to control the first few bytes of output a. if err != nil { // feed back error to user fmt.Fprintf(w, “%s”, err.Error()) } b. bt, err := json.Marshal(object) fmt.Fprintf(w, “%s(%s)”, request.Header.Get(“callback”), bt) 2. where unspecified by directly setting Content-Type header, it’s sniffed out of the first few bytes of the response body 3. Content-Types like XML, SVG and HTML result in XSS

  10. some attempts at taming content types ● for jsonp, prepend a comment(/* */) ● set the content type you’re expecting before you send any data ● try to use consistent content-types per endpoint if possible ● set your safest content-type first, and replace it with response.Header().Set when you want to return html, svg or xml data ● Just don’t let a user set the first few bytes of the page

  11. lemma 3: WriteHeader is Sneaky 1. send a 500; return a description a. response.SetHeader(500) response.Header().Set( “Content-Type”, “text/plain”) template.Error.Exec(response, err) 2. the attempt to set content-type is ignored and the content is sniffed 3. the content appears correctly and there’s no warning, it’s easy to miss ✨

  12. lemma 4: It’s hard to manage errors 1. many handler functions look something like this a. operation() if err != nil { handleError(err, rw) return // often missed } show contents… 2. return is missed, execution continues, other content is appended with the wrong Content-Type due to WriteHeader

  13. opinions on managing errors ● perform all error handling in one parent function at the mux / router level, manage status in this function ○ func ServeHTTP(w http.ResponseWriter, r *http.Request) { err, status := s.serveHTTP(w, r) //func(http.ResponseWriter, http.Request) (status int, err error) // a zero status indicates success unless there is an error if err == nil && status == 0 { status = 200 } // an error or a non-200 status indicates an error to feed back to the user if err != nil || status != 200 { ● when an error occurs in a sub-handler, we simply return it

  14. closing comments ● still a lot of space for breaking new ground in Go security ● html/template is a really elegant library that should be used whenever html is generated, it’s a great example of a hard api to use badly too ○ that said, be very(!) careful using template.HTML, template.HTMLAttr, JS, JSStr which are used to side-step its protections ● always expose go’s http server through a standard http server like nginx, go does not protect you against dns rebinding attacks ● go doesn’t come with csrf protection. If you’re building something that’s not an API, make sure to use a library for it, like gorilla’s. ● be careful what, and how reaches a user

  15. Thank you ● ●


More recommend