go get my/vulnerabilities - Black Hat · So is this magic? 33. This is NOT PHP type simpleHandler...

45
go get my/vulnerabilities Green threads are not eco friendly threads 1

Transcript of go get my/vulnerabilities - Black Hat · So is this magic? 33. This is NOT PHP type simpleHandler...

Page 1: go get my/vulnerabilities - Black Hat · So is this magic? 33. This is NOT PHP type simpleHandler struct {} func (t *simpleHandler) ServeHTTP(w http.ResponseWriter, r *http.Request)

go get my/vulnerabilitiesGreen threads are not eco

friendly threads

1

Page 2: go get my/vulnerabilities - Black Hat · So is this magic? 33. This is NOT PHP type simpleHandler struct {} func (t *simpleHandler) ServeHTTP(w http.ResponseWriter, r *http.Request)

Who● ( Web|Mobile ) penetration tester

● Code reviewer

● Programmer

Roberto Clapis

@empijei 2

Page 3: go get my/vulnerabilities - Black Hat · So is this magic? 33. This is NOT PHP type simpleHandler struct {} func (t *simpleHandler) ServeHTTP(w http.ResponseWriter, r *http.Request)

Go

● Google’s language

● Born in 2007 (quite new)

● Widespread

3

Page 4: go get my/vulnerabilities - Black Hat · So is this magic? 33. This is NOT PHP type simpleHandler struct {} func (t *simpleHandler) ServeHTTP(w http.ResponseWriter, r *http.Request)

Cool, but how do I break it?

4

● Memory safety, Garbage Collection

● Anti-XSS/SQLi sanitization

● Built-in thread-safe constructs

Page 5: go get my/vulnerabilities - Black Hat · So is this magic? 33. This is NOT PHP type simpleHandler struct {} func (t *simpleHandler) ServeHTTP(w http.ResponseWriter, r *http.Request)

Let’s start the digging

● New features usually lead to new vulnerabilities

● Goroutines are one of the main new features introduced by Go

5

Page 6: go get my/vulnerabilities - Black Hat · So is this magic? 33. This is NOT PHP type simpleHandler struct {} func (t *simpleHandler) ServeHTTP(w http.ResponseWriter, r *http.Request)

Goroutines are concurrent function calls

go go

go fmt.Println(“Hello goroutines”)6

Page 7: go get my/vulnerabilities - Black Hat · So is this magic? 33. This is NOT PHP type simpleHandler struct {} func (t *simpleHandler) ServeHTTP(w http.ResponseWriter, r *http.Request)

Let’s try this

for i := 0; i <= 9; i++ {

go func() {

fmt.Println(i)

}()

}7

Page 8: go get my/vulnerabilities - Black Hat · So is this magic? 33. This is NOT PHP type simpleHandler struct {} func (t *simpleHandler) ServeHTTP(w http.ResponseWriter, r *http.Request)

Expectation

1

3

2

...

8

9

10

10

10

...

10

10

Reality

8

Page 9: go get my/vulnerabilities - Black Hat · So is this magic? 33. This is NOT PHP type simpleHandler struct {} func (t *simpleHandler) ServeHTTP(w http.ResponseWriter, r *http.Request)

Wait...

9

Page 10: go get my/vulnerabilities - Black Hat · So is this magic? 33. This is NOT PHP type simpleHandler struct {} func (t *simpleHandler) ServeHTTP(w http.ResponseWriter, r *http.Request)

Special functions #1: goroutines

● Concurrent

● Lightweight

● Multiplexed on OS Threads

go func(){

//Code here

}()

10

Page 11: go get my/vulnerabilities - Black Hat · So is this magic? 33. This is NOT PHP type simpleHandler struct {} func (t *simpleHandler) ServeHTTP(w http.ResponseWriter, r *http.Request)

Special functions #2: closuresfreeVar := “Hello ”

f := func(s string){

fmt.Println(freeVar + s)

}

f(“Closures”)

// Hello Closures

11

Page 12: go get my/vulnerabilities - Black Hat · So is this magic? 33. This is NOT PHP type simpleHandler struct {} func (t *simpleHandler) ServeHTTP(w http.ResponseWriter, r *http.Request)

Special functions #(1+2): closured goroutinesfor i := 0; i <= 9; i++ {

go func() {

fmt.Println(i)

}()

}

// Here i == 10 12

Page 13: go get my/vulnerabilities - Black Hat · So is this magic? 33. This is NOT PHP type simpleHandler struct {} func (t *simpleHandler) ServeHTTP(w http.ResponseWriter, r *http.Request)

Performance

● Writing to file is slow

● Aware scheduling

● Runtime waits only if necessary

13

Page 14: go get my/vulnerabilities - Black Hat · So is this magic? 33. This is NOT PHP type simpleHandler struct {} func (t *simpleHandler) ServeHTTP(w http.ResponseWriter, r *http.Request)

The (odd) fixfor i := 0; i <= 9; i++ {

i := i

go func() {

fmt.Println(i)

}()

}

14

Page 15: go get my/vulnerabilities - Black Hat · So is this magic? 33. This is NOT PHP type simpleHandler struct {} func (t *simpleHandler) ServeHTTP(w http.ResponseWriter, r *http.Request)

Channels

ch <- data

data <- ch

close(ch)

data, ok <- ch

Buffer Buffer

ch := make(chan.. go

for data := range ch {15

Page 16: go get my/vulnerabilities - Black Hat · So is this magic? 33. This is NOT PHP type simpleHandler struct {} func (t *simpleHandler) ServeHTTP(w http.ResponseWriter, r *http.Request)

Information Leakage

responses to the wrong requests

func Serve(queue chan *http.Request) {

for req := range queue {

go func() {

process(req)

}()

}

} 16

Page 17: go get my/vulnerabilities - Black Hat · So is this magic? 33. This is NOT PHP type simpleHandler struct {} func (t *simpleHandler) ServeHTTP(w http.ResponseWriter, r *http.Request)

Checkpoint

● Variable scoping is a nice point to focus on

● Aware scheduling can make it easier to abuse races

how aware is the scheduler?

17

Page 18: go get my/vulnerabilities - Black Hat · So is this magic? 33. This is NOT PHP type simpleHandler struct {} func (t *simpleHandler) ServeHTTP(w http.ResponseWriter, r *http.Request)

MPG model

M

M

P

P G

G

G

OS Threads GOMAXPROCSLogical processors

Goroutines18

Page 19: go get my/vulnerabilities - Black Hat · So is this magic? 33. This is NOT PHP type simpleHandler struct {} func (t *simpleHandler) ServeHTTP(w http.ResponseWriter, r *http.Request)

Schedule me please

Computation

I/Ogo Read buffer

Write to channel

Scheduler calls are emitted at compile time19

Page 20: go get my/vulnerabilities - Black Hat · So is this magic? 33. This is NOT PHP type simpleHandler struct {} func (t *simpleHandler) ServeHTTP(w http.ResponseWriter, r *http.Request)

Consequences are weirdgo func() {

for i := 0; true ; i++ {

}

}()

time.Sleep(2 * time.Second)

fmt.Println("Done")

20

Page 21: go get my/vulnerabilities - Black Hat · So is this magic? 33. This is NOT PHP type simpleHandler struct {} func (t *simpleHandler) ServeHTTP(w http.ResponseWriter, r *http.Request)

Cores amount matter

Endless for

sleepch := make(chan.. go End program

Endless for

sleepch := make(chan.. go End program

21

Page 22: go get my/vulnerabilities - Black Hat · So is this magic? 33. This is NOT PHP type simpleHandler struct {} func (t *simpleHandler) ServeHTTP(w http.ResponseWriter, r *http.Request)

Runs the same way everywhere...

runtime.GOMAXPROCS(1)

22

Page 23: go get my/vulnerabilities - Black Hat · So is this magic? 33. This is NOT PHP type simpleHandler struct {} func (t *simpleHandler) ServeHTTP(w http.ResponseWriter, r *http.Request)

Statically Strongly Typedgo func() {

for i := range lst {

for ; i <= 255 ; i++ {

// Computation

}

}

}()23

Page 24: go get my/vulnerabilities - Black Hat · So is this magic? 33. This is NOT PHP type simpleHandler struct {} func (t *simpleHandler) ServeHTTP(w http.ResponseWriter, r *http.Request)

Hidden problem: Garbage Collector

Request memory

Lose referencego

Garbage collector needs to stop goroutines

Garbage Collection

Stop the world Start the world

24

Page 25: go get my/vulnerabilities - Black Hat · So is this magic? 33. This is NOT PHP type simpleHandler struct {} func (t *simpleHandler) ServeHTTP(w http.ResponseWriter, r *http.Request)

Garbage Collection?

Free neededgo

GC politely asks goroutines to stop

Garbage Collection??

Stop the world Start the world

Endless for

25

Page 26: go get my/vulnerabilities - Black Hat · So is this magic? 33. This is NOT PHP type simpleHandler struct {} func (t *simpleHandler) ServeHTTP(w http.ResponseWriter, r *http.Request)

Consequences are badgo func() {

var i byte

for i = 0; i <= 255; i++ {

}

}()

runtime.Gosched() //yield execution

runtime.GC()

fmt.Println("Done")26

Page 27: go get my/vulnerabilities - Black Hat · So is this magic? 33. This is NOT PHP type simpleHandler struct {} func (t *simpleHandler) ServeHTTP(w http.ResponseWriter, r *http.Request)

Here is the solution

Weird solution: use non-inlinable function calls in loops

The correct one: use channels

27

Page 28: go get my/vulnerabilities - Black Hat · So is this magic? 33. This is NOT PHP type simpleHandler struct {} func (t *simpleHandler) ServeHTTP(w http.ResponseWriter, r *http.Request)

Checkpoint

● Scheduling must be taken into account

● Goroutines that don’t yield have potential for DoS

how do goroutines die?

28

Page 29: go get my/vulnerabilities - Black Hat · So is this magic? 33. This is NOT PHP type simpleHandler struct {} func (t *simpleHandler) ServeHTTP(w http.ResponseWriter, r *http.Request)

Goroutines end

The only way for a goroutine to terminate is for it to return, or for the program to end.

29

Page 30: go get my/vulnerabilities - Black Hat · So is this magic? 33. This is NOT PHP type simpleHandler struct {} func (t *simpleHandler) ServeHTTP(w http.ResponseWriter, r *http.Request)

Goroutines are not Garbage Collected

They must be signalled to end or they

constitute an insidious opening for DoS

30

Page 31: go get my/vulnerabilities - Black Hat · So is this magic? 33. This is NOT PHP type simpleHandler struct {} func (t *simpleHandler) ServeHTTP(w http.ResponseWriter, r *http.Request)

select the right solution?select {

case d1 <- ch1:

case d2, ok <- ch2:

default:

}

ch2 <- data2

select

ch1 <- data1

go

31

Page 32: go get my/vulnerabilities - Black Hat · So is this magic? 33. This is NOT PHP type simpleHandler struct {} func (t *simpleHandler) ServeHTTP(w http.ResponseWriter, r *http.Request)

Max execution time in PHP

<?php

set_time_limit(2);

for($i=0;;$i++){

}

?>

// Maximum execution time of

// 2 seconds exceeded 32

Page 33: go get my/vulnerabilities - Black Hat · So is this magic? 33. This is NOT PHP type simpleHandler struct {} func (t *simpleHandler) ServeHTTP(w http.ResponseWriter, r *http.Request)

Max execution time in go

So is this magic?33

Page 34: go get my/vulnerabilities - Black Hat · So is this magic? 33. This is NOT PHP type simpleHandler struct {} func (t *simpleHandler) ServeHTTP(w http.ResponseWriter, r *http.Request)

This is NOT PHPtype simpleHandler struct {}func (t *simpleHandler) ServeHTTP(w http.ResponseWriter,

r *http.Request) {time.Sleep(10 * time.Second)fmt.Println("Got here")

}func main() {

sh := &simpleHandler{}tsh := http.TimeoutHandler(sh,

time.Second*2, "Timeout!")

http.ListenAndServe(":8080", tsh)

34

Page 35: go get my/vulnerabilities - Black Hat · So is this magic? 33. This is NOT PHP type simpleHandler struct {} func (t *simpleHandler) ServeHTTP(w http.ResponseWriter, r *http.Request)

Just a click away

35

Page 36: go get my/vulnerabilities - Black Hat · So is this magic? 33. This is NOT PHP type simpleHandler struct {} func (t *simpleHandler) ServeHTTP(w http.ResponseWriter, r *http.Request)

Dive into sources// Create timer

go func() {

h.handler.ServeHTTP(tw, r)

// Signal done channel

}()

select {

case <-done:

// Handle HTTP stuff

case <-timeout:

// Write error

}36

Page 37: go get my/vulnerabilities - Black Hat · So is this magic? 33. This is NOT PHP type simpleHandler struct {} func (t *simpleHandler) ServeHTTP(w http.ResponseWriter, r *http.Request)

Mind the gap

The standard library isn’t more powerful than you are, if you can’t kill a goroutine,

neither can the stdlib.

37

Page 38: go get my/vulnerabilities - Black Hat · So is this magic? 33. This is NOT PHP type simpleHandler struct {} func (t *simpleHandler) ServeHTTP(w http.ResponseWriter, r *http.Request)

Some more problems with signals// The worker goroutinefor {

select{case job <- jobs:

process(job)case <-done:

return}

}

// The main goroutine:go worker()// Work needs to end:done <- true

38

Page 39: go get my/vulnerabilities - Black Hat · So is this magic? 33. This is NOT PHP type simpleHandler struct {} func (t *simpleHandler) ServeHTTP(w http.ResponseWriter, r *http.Request)

Other (still not) correct fixes

go worker()go worker()go worker()done <- truedone <- truedone <- true

case <-done:done <- truereturn

go worker()done <- true

39

Page 40: go get my/vulnerabilities - Black Hat · So is this magic? 33. This is NOT PHP type simpleHandler struct {} func (t *simpleHandler) ServeHTTP(w http.ResponseWriter, r *http.Request)

Even worse

case <- done

done <- truedone := make(chan.. go

done <- true

?

40

Page 41: go get my/vulnerabilities - Black Hat · So is this magic? 33. This is NOT PHP type simpleHandler struct {} func (t *simpleHandler) ServeHTTP(w http.ResponseWriter, r *http.Request)

Other (still not) correct fixescase <-done:

done <- truereturn

go worker()done <- true<- done

41

Page 42: go get my/vulnerabilities - Black Hat · So is this magic? 33. This is NOT PHP type simpleHandler struct {} func (t *simpleHandler) ServeHTTP(w http.ResponseWriter, r *http.Request)

Just close it

go worker()go worker()go worker()close(done)

42

Page 43: go get my/vulnerabilities - Black Hat · So is this magic? 33. This is NOT PHP type simpleHandler struct {} func (t *simpleHandler) ServeHTTP(w http.ResponseWriter, r *http.Request)

Close channels

close(ch)

data, ok <- chch := make(chan.. go

for data := range ch {

if !ok {

43

Page 44: go get my/vulnerabilities - Black Hat · So is this magic? 33. This is NOT PHP type simpleHandler struct {} func (t *simpleHandler) ServeHTTP(w http.ResponseWriter, r *http.Request)

Conclusions

44

● Mind race conditions

● Dive into sources

● Follow signals

● Check for yielding calls

Page 45: go get my/vulnerabilities - Black Hat · So is this magic? 33. This is NOT PHP type simpleHandler struct {} func (t *simpleHandler) ServeHTTP(w http.ResponseWriter, r *http.Request)

Thanks

Roberto Clapis

@empijei

45