metatron-discovery security review speed run

서론

7월 26일 슬랙에 특성 회사 Github 저장소에 스타를 누를경우 선착순으로 경품을 준다는 메시지가 올라왔다. “처음엔 뭔 이런 이벤트가 다있지?” 하는 마음에 넘어갔지만 며칠 뒤 아래 게시글을 통해 사건의 발단되었다.

ㅋㅋㅋㅋ 그냥 웃고 넘어가려고 했는데 회사 슬랙에 @wooeong이 메시지를 보냈다.

링크를 눌러보니 이 프로젝트의 코드 퀄리티를 대충이나마 짐작할 수 있었다.

와!!!!!!!!!! (Command Injection?)

몇 개월동안 블로그를 방치해두기도 했고 빠르게 작성할 수 있을 것 같아 저녁시간을 이용해서 @wooeong과 함께 speed-run을 진행하고 그 결과를 쉐어해기로 했다. speed-run은 매년 Power Of Community라는 infosec conference에서 우리 회사가 진행하는 해킹 이벤트다. 주어진 짧은 시간(보통 10분~15분)에 해킹 문제를 풀면된다. 해킹이 생소하신 개발자분들은 해커톤 느낌으로다가 생각해주시면 될 것 같다.

우선 저장소에 나와있는 순서대로 빌드부터 해보기로 했다.

빌드가 되긴 한다…

국산 오픈소스 프로젝트의 국룰을 어기고 빌드가 성공적으로 진행된다. 다만 아래 사진처럼 철지난 npm 패키지들을 무수히 사용해 48개의 취약점이 발견되었다. 확인 해보지는 않았지만 regex DoS라던지 XSS 던지 하는 것들이 있을 것 같다.

실행하고 싶어요..

conf에 대한 예제가 있는데 이걸 어떻게 인자로 넣어야 하는지에 대한 설명은 readme 어느 곳에도 없었다. 깔끔하게 손절하려고 하던 순간, https://metatron.app/download/guide_vm/ vm image로 제공해준다.

[metatron@localhost ~]$ cat how_to_get_latest_binaries 
wget https://sktmetatronkrsouthshared.blob.core.windows.net/metatron-public/discovery-dist/latest/druid-0.9.1-latest-hadoop-2.7.3-bin.tar.gz

wget https://sktmetatronkrsouthshared.blob.core.windows.net/metatron-public/discovery-dist/latest/metatron-discovery-latest-bin.tar.gz
[metatron@localhost ~]$ 

홈 디렉토리에 저런 파일이 있다. get하는 방법만 알려주고 run하는 방법은 어디에도 나와있지 않기 때문에 실제 데모페이지가 돌아가고 있는 3.2.6 버전으로 audit을 하기로 했다. 블랙/화이트 박스 테스팅을 모두 진행하였고 전체의 아키텍쳐를 이해하지 않은 상태에서 간단한 스트링서치로만 audit을 진행했다. 한 버그클래스에 여러 버그 케이스가 존재하는 경우는 대표적인 것 하나만 작성했다. 아래는 speed-run을 통해 발견된 취약점들이다.

취약점

IDOR (Insecure Direct Object Reference)

대부분의 엔드포인트에서 권한 분리가 제대로 적용되어있지 않다. 펜딩 멤버와 같이 어드민만 볼 수 있는 API를 호출하는 것이 가능하다. 어드민 덧글을 게스트 유저가 수정해보겠다. 참고로 게스트는 다른 덧글을 수정할 수 있는 권한이 없다. (많은 엔드포인트에서 비슷한 취약점이 발생한다.)

Guest Token
Admin이 작성한 덧글 수정 요청
수정 완료

Arbitrary File Read + Path traversal

확장자 체크없이 인풋 받은 path를 그대로 읽어 출력해준다. 이쯤되면 “기능인가?” 의심해볼 필요가 있다.

SSRF

Host / Port 그리고 GET Parameter 조작이 가능하다.

Default username/password

metatron에서 호스팅해주는 데모 서버에 VM이미지를 받았을 때 존재하는 계정 정보로 로그인이 가능하다. (원래는 pending state를 거쳐야 함) — https://discovery.metatron.app/(polaris / polaris)

결론

전체적으로 코드가 많이 난잡하다. (지금 졸려서 내 글도 난잡한 것 같다.) 잠재적인 취약점이 많이 보이는데 회사일도 아니고 시간 도 없어서 말을 줄이겠다. 빅데이터 관련된 지식에 문외한이라 뭘 하는 프로그램인지는 모르겠지만 뭔가 좋은 것 같다. 이것저것 눌러보니 비주얼라이징이 이쁘게 된다. (한국) 기업치고 자사 프로덕트를 오픈소스하기 까지 쉽지 않았을텐데 코드 퀄리티를 떠나서 이 점은 칭찬하고 싶다. 다만 Github Star를 돈으로 산 행위는 이해할 수 없다. ㅋ.ㅋ

https://github.com/metatron-app/metatron-discovery/blob/f019b72a69e1713e38b5e958daf2b0919b7a5d77/discovery-server/src/main/java/app/metatron/discovery/domain/dataprep/PrepDatasetStagingDbService.java#L248-L249

오픈소스를 마음 먹었으면 이런 주석정도는 지울 수 있지 않나..

업데이트

[13:35 30-Jul-19] Github issue를 통해 오픈소스 메인테이너에게 리포트 ( https://github.com/metatron-app/metatron-discovery/issues/2406 )

맥 카카오톡 이미지 클립보드 붙여넣기가 안될때 해결

장장 3개월을 몰라서 포맷할까? 생각도 하고,, 엄청난 삽질을 했었다. 문제는 다음과 같다.

CMD + SHIFT 3, 4 + CTRL 을 통해 이미지를 클립보드에 저장하고 카카오톡에 붙여넣기를 하면 정상적으로 되질 않는다. 파일로 저장한 후 복사/붙여넣기 할때는 제대로 된다.

이유를 몰라 엄청 헤맸었는데 이유를 찾았다. 어떻게 찾았는지가 더 재밌는데 어제 자기전 상상속에서 생각을 하다가 CTF문제를 풀기위해 맥 스크린샷 포맷을 JPEG로 바꾼 것이 생각났다. 분명 비슷한 시기에 클립보드 붙여넣기가 안된거 같고. 이때 슬랙이나 다른 메신저로 붙여넣기는 정상적으로 되었다.. 하여튼 포맷을 PNG로 바꾸니깐 다시 잘 된다! 행복!

defaults write com.apple.screencapture type PNG

터미널에 위 명렁어를 치면 된다..

Screen Shot 2018-10-03 at 3.39.03 AM.PNG
근데 워드프레스는 붙여넣기가 안되네, 안습..

Latest Gnuboard version XSS to SQL Injection

 “3월의 나” 계획(브라우저 해킹)을 해놓고 2월의 나는 어디에 써놓았는지 기억이 안난다. OS X Kernel을 부시기로 했는데 조만간 부실 수 있을것 같다. 대신 OS X, iOS에서 발생하는 Exploitable할것 같은 버그를 찾았다. 열심히 분석해야겠다. 월간 임준오가 쉬면 곤란하니깐 2월엔 GnuBoard 취약점을 공개하겠다.

Summary

 BoB 과제를 진행하면서 찾은 취약점이다. 작년 시큐인사이드에서 adm1nkyj가 냈던 문제의 취약점과 매우 유사하다. 그 문제의 취약점도 그누보드 모티브다. 여기서 중요한건 패치를 전부 해야되는데 한곳만 해서 유사한 코드나 벡터를 통해 한번더 0-day로 만들 수 있다는 점이다.
 관리자 페이지에서 발생한 SQL Injection이라 관리자 권한을 흭득하는 XSS가 필요하다. 물론 XSS도 찾았기 때문에 같이 설명하겠다.

Vulnerability

– XSS

듣기로 그누보드 관리자 페이지에는 무수히 많은 XSS취약점이 존재한다. serialization동작 없이 `echo $variable;`을 하다보니 당연할 수 밖에 없다. 소스코드 리뷰를 진행하니 금방 찾을 수 있었다. adm/mail_select_form.php 파일 71, 114줄에  취약점이 존재한다.

value="">

그누보드에서는 모든 피라미터에 addslash하여 XSS를 방어한다. html tag를 파싱할때 attribute안에 있는 \”는 “라고 인식하지 않고 attribute의 종료로 인식된다. 따라서 다음과 같은 상황이 발생한다.


value="\">alert(1);">

성공적으로 공격이 가능하다,, Chrome XSS Auditor를 Bypass하려면 약간의 Trick을 주면 된다.- SQL Injectionaddslash를 하기 때문에 basic한 sql injection이 발생한 가능성이 없다. 그러므로 advanced한 취약점을 찾아야하는데,, 작년에 adm1nkyj가 secuinside때 낸 문제가 떠올랐다. 그 문제도 그누보드를 사용한 third-party앱에서 찾은 취약점을 기반해 낸것이다. 관련된 코드를 찾으니 아직 패치가 되지 않은 한 부분이 있었다.. adm/auth_list_delete.php 파일 12~24줄을 보면 된다. 요약하면 다음과 같다.인자를 Array로 받는 로직중 그 Array의 값을 그대로 sql query에 사용했을때 발생하는 문제다.

$b = $_GET['b'];
for ($i=0; $i<strlen($a); $i++) {
    $query = "select * from table1 where a='{$a[i]}' and b='{$b}';";
}
b는 addslash때문에 sqlinjection이 불가능하다. a는 Array를 줘야한다. 하지만 a가 String이 되어 버리면 어떻게 될까? 1 byte씩 들어가기 때문에 \를 하나 넣을 수 있게된다. 그렇게 되면…

// a : \ → addslash → \\
// b: Attack Query
$query = "select * from table1 where a='\' and b='Attack Query#';";<span id="mce_SELREST_start" style="overflow:hidden;line-height:0;"></span>

따단..


업데이트

26th Mar.

크레딧 상태가 이상하지만, 뭐 .. 어쩔 수 없다.

커밋 로그를 살펴보니 admin 페이지 말고도 file board쪽에서도 하나 더 있었나 보다, 뭐 이런류의 취약점은 많을거라 생각한다.

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