Attack Block Chain Node’s JSON RPC with Efficient DNS Rebinding Attack

 구글의 타비스가 Blizzard 앱에서RPC auth mechanism이 DNS Rebinding를 통해 공격이[1] 가능하다는것을 언급했다. 며칠 뒤 페이스북이랑 트위터에서 geth(go-ethereum) RPC와 몇가지 블록체인 노드들의 RPC에 DNS Rebinding Attack이 가능하다는 여러가지 이야기가 들려왔다.
 우선 이더리움 Geth에서 비오비 프로젝트를 하면서우리 팀이 찾았던 CORS이슈와 제시했던 패치 방안과 대해서 설명한다. 타 블록체인 노드에서 발생한 0-day 그리고 공격에 사용되었던 효율적인 DNS Rebinding Attack을 소개한다.

DNS Rebinding Attack

 0ctf 2016의 Monkey 문제가 DNS Rebinding Attack을 소개하는 글중에 하나이다. [7] 아마 이 문제 이후에 용진이형이 알려줬었다. 더 알아보고 싶으면 용휘형이 예전에 번역했던 글을 참고해서 읽어도 좋다. (http://gooverto.tistory.com/entry/the-power-of-dns-rebinding-stealing-wifi-passwords-with-a-website-translated) 일반적으로 말하는 DNS Rebinding Attack Browser의 SOP를 우회하기 위한 기술중 하나이다. 플로우차트를 그려보면 다음과 같다.
1. junoim.kr을 NS에 요청하면 174.138.24.108을 반환한다.
2. 네임서버의 레코드를 빠르게 바꾸고 브라우저에서 DNS Cache가 flush될때까지 기다린다.
3. 그 후 NS에 요청을 보내면 127.0.0.1을 반환하게 된다.
이러한 요청은 브라우저에서 domain뿐만 아니라 ip까지 확인하면 되지만 벤더사들은 클라이언트 단에서 미티게이션을 추가하는것은 false negative한 case들 때문에 불가능하다고 생각해 wontfix처리 했다. [2]
위 방법을 사용하면 브라우저의 DNS Cache가 비워질때까지 기다려야 하기 때문에 60초가 필요하다. 뭐 eviction을 하면서 다른 값으로 덮어서 없앨 수도 있는데 그래도 20초 이상이 필요하다. optimization을 하기 위해 사용한 방법은 다음과 같다.
0. 도메인의 A레코드에 정상적인 서버의 아이피와 127.0.0.1를 등록해둔다. (with order fixed option)
1. junoim.kr을 NS에 요청하면 174.138.24.108을 반환한다.
2. 첫 요청이 들어오면 서버를 끄던가 요청된 IP를 iptables를 이용해 블락한다.
3. 브라우저에서 바로 다음 요청을 보내면 공격자의 서버에서는 TCP RST 패킷을 보내게 된다.

4. RST 패킷을 받으면 브라우저에서는 다음 레코드를 사용하게 된다. (127.0.0.1)

Tendermint Node RPC 0-day

 떡락이의 블록체인연구소 (https://www.facebook.com/blockchain.gazua/) 에서 tendermint를 언급한적이 있다. 뭐.. 자세한건 안봐서 모르겠지만 얘도 노드를 사용한다 ! RPC 통신도 지원한다!
tendermint.exe node –proxy_app=dummy
명령어를 통해 실행할 수 있다. 데모 영상이다.

Mitigation

 매우 간단한 패치로 공격을 막을 수 있다. 서버 측에서 Request측의 IP와 HTTP 헤더의 host, origin를 검사하면 된다. 이런식으로 패치해도 타 process에서 보내거나 extension에서 보내게 되면 막을 방법이 없기 때문에 신뢰할 수 있는 종단간 암호화를 통한 인증과정을 도입시켜야 된다. e.g.) username/password

Others

Ethereum Geth RPC에 Dns Rebinding Attack 문제는 오래전 부터 있었다. [4], [8] 물론 비슷한 케이스로 CORS Bypass 문제도 있었다. 비오비 프로젝트를 하면서 찾은 취약점 중에 하나인데 바운티에 신고를 했을때 다음과 같은 답장이 왔었다.
This is actually a known issue, one of the first we got via the bug bounty program. Nevertheless, we’ve decided to change the behaviour, but we won’t change anything before Byzantium: since people will be forced to update for the fork, we don’t want to force a potentially breaking API-change on people/businesses.
2016년에 이미 관련된 이슈가 제보 되었다는걸 알려주었다. 뭐 CORS 이슈라 아래와 같이 패치방안을 제공해주었다. 사실 이대로만 패치 되었더라도 DNS Rebinding Attack은 바로 막히는데 아쉽다.
if not request.headers['origin'] in allowedOrigin:
    return Error("WTF! your origin is not in allowedOrigin list.")

Victim의 Public IP Address를 모르는 상황에서 공격하는 시나리오였기 때문에 요청한 IP Address를 검사하는 로직도 추가되어야 한다. (0.0.0.0로 바인드 하는 상황이면)위와 비슷하게 Cisco Talos가 Parity 에서도 동일한 취약점을 찾았다. [9]

Ref

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.