Whats wrong with WebSocket APIs? Unveiling vulnerabilities in - - PowerPoint PPT Presentation

what s wrong with websocket apis
SMART_READER_LITE
LIVE PREVIEW

Whats wrong with WebSocket APIs? Unveiling vulnerabilities in - - PowerPoint PPT Presentation

Whats wrong with WebSocket APIs? Unveiling vulnerabilities in WebSocket APIs Mikhail Egorov / @0ang3el #DeepSec2019 # whoami Security researcher / full-time bug hunter https://bugcrowd.com/0ang3el https://hackerone.com/0ang3el


slide-1
SLIDE 1

Mikhail Egorov / @0ang3el

What’s wrong with WebSocket APIs?

Unveiling vulnerabilities in WebSocket APIs

#DeepSec2019

slide-2
SLIDE 2

# whoami

2

▪ Security researcher / full-time bug hunter

▪ https://bugcrowd.com/0ang3el ▪ https://hackerone.com/0ang3el

▪ Conference speaker

▪ https://www.slideshare.net/0ang3el ▪ https://speakerdeck.com/0ang3el

slide-3
SLIDE 3

Previous work

3

▪ https://media.blackhat.com/bh-us- 12/Briefings/Shekyan/BH_US_12_Shekyan_Toukharian_Hacking_Websocket_Slides .pdf ▪ https://www.nccgroup.trust/us/about-us/newsroom-and- events/blog/2017/may/wssip-a-websocket-manipulation-proxy/ ▪ https://chybeta.github.io/2018/04/07/spring-messaging-Remote-Code-Execution- %E5%88%86%E6%9E%90-%E3%80%90CVE-2018-1270%E3%80%91/ ▪ https://www.twistlock.com/labs-blog/demystifying-kubernetes-cve-2018-1002105- dead-simple-exploit/ ▪ https://github.com/andresriancho/websocket-fuzzer ▪ https://www.irongeek.com/i.php?page=videos/derbycon9/stable-35-old-tools-new- tricks-hacking-websockets-michael-fowl-nick-defoe

slide-4
SLIDE 4

4

WebSocket protocol essentials

slide-5
SLIDE 5

WebSocket protocol – RFC 6455

5

▪ Efficient two-way communication protocol ▪ WebSocket is stateful (HTTP is stateless) ▪ Two main parts: handshake and data transfer

slide-6
SLIDE 6

WebSocket protocol – RFC 6455

6

▪ Extensibility: subprotocols and extensions ▪ Subprotocols

▪ https://www.iana.org/assignments/websocket/websocket.xml#subpro tocol-name ▪ Wamp ▪ Stomp ▪ Soap ▪ …

slide-7
SLIDE 7

WebSocket protocol – RFC 6455

7

▪ Extensibility: subprotocols and extensions ▪ Extensions

▪ https://www.iana.org/assignments/websocket/websocket.xml#extens ion-name ▪ permessage-deflate ▪ bbf-usp-protocol

slide-8
SLIDE 8

WebSocket protocol – RFC 6455

8

▪ Origin-based security model (Browser clients) ▪ No authentication ▪ Client must do client-to-server masking

slide-9
SLIDE 9

WebSocket protocol support

9

▪ Major web browsers ▪ Web servers / Proxies

▪ Apache httpd, Nginx, IIS, … ▪ HAProxy, Traefik, Varnish, Envoy, …

▪ Cloud providers

▪WebSocket API (api gateways) ▪WebSocket proxying (load balancers)

slide-10
SLIDE 10

WebSocket handshake over HTTP/1.1

10

Upgrade request Base64(Random nonce) Protocol version Required HTTP version

slide-11
SLIDE 11

WebSocket handshake over HTTP/1.1

11

Required status code BASE64(SHA1(Sec-WebSocket-Key || CONST ))

slide-12
SLIDE 12

WebSocket data transfer

12

\x00 – continuation frame \x01 – text frame \x02 – binary frame \x08 – close frame \x09 – ping \x0A – pong

  • ther values are reserved
slide-13
SLIDE 13

WebSocket data transfer - masking

13

▪ Masking key is 32-bit long passed inside frame

▪ Client must send masked data ▪ MASKED = MASK ^ DATA (^ - XOR) ▪ Mechanism protects against cache poisoning and smuggling attacks

slide-14
SLIDE 14

WebSocket protocol and HTTP/2

14

▪ RFC 8441

▪ Bootstrapping WebSocket with HTTP/2

▪ Not yet widely supported by proxies / web servers

▪ nghttp2 - https://github.com/nghttp2/nghttp2

slide-15
SLIDE 15

WebSocket handshake over HTTP/2

15

SETTINGS_ENABLE_CONNECT_PROTOCOL

slide-16
SLIDE 16

WebSocket handshake over HTTP/2

16

Protocol name WebSocket version HTTP method

slide-17
SLIDE 17

WebSocket handshake over HTTP/2

17

Required status code

slide-18
SLIDE 18

18

Cross-Site WebSocket Hijacking

slide-19
SLIDE 19

WebSocket security for Web Browser

19

▪ SOP doesn’t work for WebSocket in web browser

▪ Read from WebSocket cross-origin ▪ Write to WebSocket cross-origin

▪ Header Origin should be checked on handshake step (origin-based security model)

slide-20
SLIDE 20

CSWSH

20

▪ Cookies are used to authenticate upgrade request ▪ Header Origin isn’t checked or checked poorly

slide-21
SLIDE 21

CSWSH

21

▪ CORS tricks from @albinowax are applicable to WebSocket

▪ https://portswigger.net/research/exploiting-cors-misconfigurations- for-bitcoins-and-bounties ▪ Null origin ▪ Pre-domain wildcard ▪ Post-domain wildcard ▪ …

slide-22
SLIDE 22

CSWSH – Null origin

22

▪ nullorigin.html

<iframe src="data:text/html, <script>const socket = new WebSocket('wss://example.com'); </script>"></iframe>

slide-23
SLIDE 23

CSWSH

23

▪ Playground

▪ https://portswigger.net/web-security/websockets/cross-site- websocket-hijacking

slide-24
SLIDE 24

CSWSH – template for attack

5

slide-25
SLIDE 25

Demo

5

slide-26
SLIDE 26

26

Authentication / IDOR issues

slide-27
SLIDE 27

Authentication

27

▪ WebSocket protocol doesn’t offer authentication ▪ Developers have to roll out their own AuthN ▪ It’s secure to check AuthN only during handshake ▪ Common secure implementations

▪ Session cookies ▪ Tokens

slide-28
SLIDE 28

Broken authentication – Case 1

28

▪ Some ID / GUID is required in Upgrade request

▪ Guess ID ▪ Leak GUID (minor IDOR, …)

slide-29
SLIDE 29

Broken authentication – Case 2

29

▪ No authentication during handshake step ▪ Some ID / GUID required in API messages

▪ Guess ID ▪ Leak GUID (minor IDOR, …)

slide-30
SLIDE 30

Broken authentication – Case 2

30

▪ Exposing GraphQL subscriptions w/o AuthN

▪ https://github.com/righettod/poc-graphql#subscriptions- websocket-endpoint-default-enabling

▪ Path /subscriptions

slide-31
SLIDE 31

Insecure Direct Object Reference issues

31

▪ Strong authentication during handshake step ▪ Some ID / GUID required in API messages

▪ Guess ID ▪ Leak GUID (minor IDOR, …)

slide-32
SLIDE 32

32

Smuggling through WebSocket

slide-33
SLIDE 33

Reverse proxying WebSocket connection

33

Client Frontend Reverse proxy Backend

/socket.io/ Public WebSocket API

slide-34
SLIDE 34

Reverse proxying WebSocket connection

34

Client Frontend Reverse proxy

Upgrade request Upgrade request

Backend

/socket.io/

slide-35
SLIDE 35

Reverse proxying WebSocket connection

35

Client Frontend Reverse proxy

Upgrade request Upgrade request HTTP/1.1 101 HTTP/1.1 101

Backend

/socket.io/

slide-36
SLIDE 36

Reverse proxying WebSocket connection

36

Client Frontend Reverse proxy

Upgrade request Upgrade request HTTP/1.1 101 HTTP/1.1 101 WebSocket connection direct WebSocket connection Client - Backend

Backend

/socket.io/

slide-37
SLIDE 37

Smuggling through WebSocket connection

37

Client Frontend Reverse proxy (vulnerable)

Private REST API Public WebSocket API

Backend

/internal /socket.io/

slide-38
SLIDE 38

38

Backend Client Frontend Reverse proxy (vulnerable)

/internal Upgrade request /socket.io/

Sec-WebSocket-Version: 1337

Upgrade request

Sec-WebSocket-Version: 1337

Version correctness isn’t checked!

Smuggling through WebSocket connection

slide-39
SLIDE 39

39

Backend Client Frontend Reverse proxy (vulnerable)

/internal Upgrade request /socket.io/

Sec-WebSocket-Version: 1337

Upgrade request

Sec-WebSocket-Version: 1337

HTTP/1.1 426 HTTP/1.1 426 Response correctness isn’t checked!

Smuggling through WebSocket connection

slide-40
SLIDE 40

40

Backend Client Frontend Reverse proxy (vulnerable)

/internal Upgrade request /socket.io/

Sec-WebSocket-Version: 1337

Upgrade request

Sec-WebSocket-Version: 1337

HTTP/1.1 426 HTTP/1.1 426 TLS connection direct TLS connection Client – Backend not WebSocket!!! Client can access /internal

Smuggling through WebSocket connection

slide-41
SLIDE 41

Challenge – challenge.0ang3el.tk

41

▪ URL

▪ https://challenge.0ang3el.tk/websocket.html

▪ You need to access flag on localhost:5000 ▪ Seems no one solved

slide-42
SLIDE 42

Challenge – challenge.0ang3el.tk

42

▪ Frontend

▪ Not disclosed WebSocket reverse proxy ▪ socket.io.js ▪ Proxies only WebSocket API - /socket.io/ path

▪ Backend

▪ Flask, Flask-SoketIO, Flask-Restful ▪ Listens on localhost:5000 only

slide-43
SLIDE 43

challenge1.py

slide-44
SLIDE 44

challenge1.py - DEMO

slide-45
SLIDE 45

Vulnerable reverse proxies

45

▪ Vulnerable

▪ Varnish, Envoy proxy <= 1.8.0, other non-disclosed

▪ Not vulnerable

▪ Nginx, HAProxy, Traefik, others

slide-46
SLIDE 46

Varnish response

46

▪ WebSocket proxying configuration

▪ https://varnish-cache.org/docs/6.3/users-guide/vcl-example- websockets.html

slide-47
SLIDE 47

Smuggling through WebSocket connection

47

Client Frontend Reverse proxy (Nginx or another)

Private REST API Public WebSocket API & REST API

Backend

/internal /api/socket.io/ /api/health

slide-48
SLIDE 48

Smuggling through WebSocket connection

48

Client Frontend Reverse proxy (Nginx or another) Backend

/internal /api/socket.io/ /api/health example.com GET HTTP/1.1 200

slide-49
SLIDE 49

Smuggling through WebSocket connection

49

Client Frontend Reverse proxy (Nginx or another) Backend

/internal /api/socket.io/ /api/health Only Upgrade: websocket header is checked! POST /api/health?u= POST /api/health?u=

slide-50
SLIDE 50

Smuggling through WebSocket connection

50

Client Frontend Reverse proxy (Nginx or another) Backend

/internal /api/socket.io/ /api/health attacker.com GET HTTP/1.1 101 HTTP/1.1 101 HTTP/1.1 101 Only status code is checked for response! POST /api/health?u= POST /api/health?u=

slide-51
SLIDE 51

Smuggling through WebSocket connection

51

Client Frontend Reverse proxy (Nginx or another) Backend

/internal /api/socket.io/ /api/health HTTP/1.1 101 HTTP/1.1 101 TLS connection direct TLS connection Client – Backend not WebSocket!!! Client can access /internal POST /api/health?u= POST /api/health?u= Client-to-Server masking isn’t checked by proxy!!!

slide-52
SLIDE 52

Challenge2 – challenge2.0ang3el.tk

52

▪ URL

▪ https://challenge2.0ang3el.tk/websocket.html

▪ You need to access flag on localhost:5000 ▪ Seems no one solved

slide-53
SLIDE 53

Challenge2 – challenge2.0ang3el.tk

53

▪ Frontend

▪ Nginx as WebSocket reverse proxy ▪ socket.io.js ▪ Proxies only /api/public path (socket.io and healthcheck)

▪ Backend

▪ Flask, Flask-SoketIO, Flask-Restful ▪ Listens on localhost:5000 only

slide-54
SLIDE 54

Challenge2 – challenge2.0ang3el.tk

54

▪ Nginx config

slide-55
SLIDE 55

Challenge2 – challenge2.0ang3el.tk

55

▪ REST API - healthcheck

slide-56
SLIDE 56

Challenge2.py

5

slide-57
SLIDE 57

Challenge2.py - Demo

5

slide-58
SLIDE 58

Vulnerable reverse proxies

58

▪ Almost all proxies are affected ▪ But exploitation is limited

▪ External SSRF is required that returns status code ▪ …

slide-59
SLIDE 59

What about RFC 8441 and HTTP/2 !?

59

▪ It’s not widely supported yet ▪ Should be supported by both proxy and backend

▪ Nghttp2 – https://github.com/nghttp2/nghttp2 ▪ Quart / Hypercorn - https://github.com/pgjones/quart ▪ Nghttpx + Quart / Hypercorn – not vulnerable

slide-60
SLIDE 60

What about RFC 8441 and HTTP/2 !?

60

▪ Vulnerable scenarios

▪ SETTINGS_ENABLE_CONNECT_PROTOCOL not checked by proxy ▪ Status code not checked by proxy (in response for CONNECT request)

slide-61
SLIDE 61

61

Discovering WebSocket APIs

slide-62
SLIDE 62

Discovering WebSocket API

62

▪ Monitor Upgrade requests ▪ Analyze JavaScript files ▪ Try to establish WebSocket connection to each URL ▪ …

slide-63
SLIDE 63

63

Conclusion

slide-64
SLIDE 64

Key takeaways

64

▪ WebSocket API is a good target for bug hunting

▪ Overlooked ▪ Traditional server-side vulns + WebSocket-related vulns

slide-65
SLIDE 65

Key takeaways

65

▪ WebSocket smuggling

▪ https://github.com/0ang3el/websocket-smuggle

slide-66
SLIDE 66

Further research

66

▪ Security of WebSocket subprotocols ▪ More smuggling techniques

▪ HTTP/2 and WebSocket ▪ …

slide-67
SLIDE 67

Thank you!

@0ang3el