[ 본 이슈는 해결 된 상태이며, 취약점은 한국시각으로 2019년 3월 16일 오전 4시 47분에 공개되었습니다. Valve에 리포팅 되었으며, 해당 프로그램과 서버는 Steam의 자산입니다. 취약점의 종류는 Classic Buffer Overflow이며, 포상금은 $18000달러로 한화로 약 2048만원 입니다. 해당 취약점은 해당 도메인에서 9.6/10의 심각성을 내포하고 있습니다. ]
소개
스팀 게임과 다른 valve게임(카스글옵, 하프라이프, 팀포2)에서는 서버 브라우저라고 불리는 게임 서버를 찾을 수 있는 기능이 있습니다. 이 서버들의 정보를 불러오기 위해서 서버 브라우저는 서버 쿼리라고 불리는 특정한 UDP 프로토콜과 통신합니다. 이 프로토콜은 온라인 개발자 스팀 메뉴얼에 잘 기술되어 있습니다. 저희는 커스텀 파이썬 서버를 실행하였으며 이것은 이 문서에 있는 동일한 정보를 활용한 프로토콜에만 응답하는 것입니다. 프로토콜의 성공적인 시행(implementation) 이후 저희는 몇 개의 파라미터를 퍼징하고 알아차리게 된 것이 있었는데 저희의 커스텀 서버로부터 응답을 받을 때 스팀 클라이언트가 크래쉬났던 것이었습니다. 더 구체적으로, A2S_PLAYER 응답에 쓰이는 긴 플레이어 이름에 대답할 때 클라이언트가 크래쉬가 납니다. 디버거를 붙였을 때 저희는 스택에 기반한 버퍼 오버플로우 때문에 크래시가 났다는 것을 깨달을 수 있었습니다.
이건 명백하게 무언가가 잘못되었다는 것을 시사하는 것이고 저희는 버퍼 오버플로우 공격을 가능하게 하기 위해 더 조사를 했습니다. 더 많은 조사끝에, 저희는 오버플로우가 서버 브라우저 라이브러리에서 발생한다는 것을 알 수 있었습니다. 어떤 지점에서는 플레이어의 이름이 유니코드로 변경되고 오버플로우가 나는데 이 것은 바운더리 체킹을 하지 않았기 때문입니다. 게다가, 그곳에는 (스택)카나리 보호기법 역시 적용되지 않고 있습니다. 이를 통해 저희가 리턴 주소를 덮어쓸 수 있고 윈도우즈에서 임의의 코드를 실행시킬 수 있었습니다.
공격 상세 설명
저희는 공격의 영향력을 증명하고 공격을 수행해보고 싶었습니다. 먼저, 리턴 주소를 덮어씀으로써 저희는 리눅스에서 테스트했고 실행 흐름을 즉시 제어할 수 있었습니다. 그러나 리눅스에서, 저희는 두 바이트의 EIP 레지스터만을(예를 들어, 0x00004141) 제어할 수 있었고 더 이상의 공격은 수행하지 않았습니다. OSX에서는, 프로세스가 SIGABRT에서 끝나는데, 이 말은 (스택)카나리 보호기법이 OSX 라이브러리에 적용되어있을 수도 있다는 의미입니다. 그리고 저희는 윈도우즈에서 공격을 시도해보았고 성공했습니다(윈도우즈 8.1과 10버전에서 테스트했습니다).
윈도우즈에서, A*1100와 같이 UDP를 통해 플레이어 이름을 전송한다면 결과적으로 스택 레이아웃은 다음과 같게 됩니다 :
유니코드 변환(wide-char) 때문에 이런 현상이 나타나는데요, 플레이어 이름이 유니코드 문자를 쓸 수 있기 때문에 그러합니다. u”\u4141″*1100와 같이 유니코드 문자로 플레이어 이름을 전송하면 다음과 같은 결과를 받아볼 수 있게 됩니다 :
그러나, 우리가 함수가 리턴되기 전에 스택과 레지스터를 변조(corrupting) 시켰기 때문에, 저희는 EIP 레지스터에 대한 제어권이 없습니다. EDI 레지스터를 역참조한 후에 프로그램은 충돌이 났지만, 제어를 할 수 있게 되었습니다. 저희는 이런 Steam.exe 바이너리의 상수 값을 이용한 특정한 조건을 만족시켰습니다:
special condition
그리고서, 우리는 스택이 실행될 수 있도록하고 cmd.exe를 실행시키기 위해서 우리의 유니코드 쉘코드로 점프할 수 있는 VirtualProtect를 동적으로 호출하기 위해, Steam.exe에서 가져온 도구를 사용해 유니코드 ROP체인을 만들었습니다. 문자열이 끊기기 때문에 우리는 0x00000040과 같은 값을 사용하지 못했고 이것은 큰 난제였습니다. 또한 우리는 u”\uda01″과 같은 유효하지 않은 유니코드 문자들도 사용하지 못했습니다. 왜냐하면 해당 라이브러리는 이 문자들을 물음표 ? – 0x003F로 대체하기 때문입니다.
참고: Steam.exe 베이스 주소 값을 기반으로 모든 것이 계산되었습니다. 이 주소 값은 당신이 스팀을 재실행할 때가 아니라 당신이 윈도우즈 8이나 10을 다시시작할 때 바뀝니다. 만약 당신이 취약점 공격을 할 때마다 베이스 주소를 수정해준다면 해당 공격은 100% 신뢰할만 합니다. 그러나 당신은 ASLR 때문에 희생자 컴퓨터의 베이스 주소 값을 예측할 수 없습니다. 그럼에도 불구하고, 우리는 두 가지의 공격 시나리오를 세웠습니다:
9바이트만을 랜덤화한다: 공격자는 0.2% (1/512)의 가능성을 가지고 희생자를 성공적으로 공격할 수 있는데, 이것은 공격자가 모든 스팀 유저에게 대량의 분산 공격을 하는 것 보다 많은 수 입니다(평균적으로 모든 512시도에서 새로운 희생자 1명).
이 취약점을 100%의 신뢰성을 가지게 하기 위해서 다른 메모리 유출 취약점과 연결시켜 공격할 수 있습니다.
공격이 발생되는 과정
먼저, 스팀이 깔려있어야 합니다. 만약 당신이 베타 버전을 사용중이라면, 공격 코드의 베타버전 가젯의 주석을 풀어주세요.
첨부파일을 다운로드 받습니다: steam_serverinfo_exploit.py (F395515)
이뮤니티 디버거와 같은 디버거를 사용하고 스팀을 엽니다.
Steam.exe의 베이스 주소 값을 가져옵니다(View-> Executable modules) 그리고 100%의 신뢰성을 위해 steam_serverinfo_exploit.py의 STEAM_BASE 변수를 수정합니다.
사용할 수 있는 아무 서버 상에서(예를 들어, localhost) 공격을 수행시킵니다: python steam_serverinfo_exploit.py
POC.html 코드를 수정한 후 iframe src의 서버 IP주소를 변경합니다.
브라우저를 열고 cmd.exe가 실행되길 기다립니다.
메뉴(View -> Servers)를 통해 서버 브라우저를 열 수 있고 View server info를 클릭해서 공격을 트리거할 수 있습니다(만약 당신이서버를 동일한 네트워크에서 실행중이라면 그것은 LAN section에서 보일 겁니다).
개념 증명(PoC)
Steamclient_POC_Windows10.mp4: 윈도우즈 10 환경에서 스팀 서버 브라우저를 통한 공격을 담은 영상
SteamURL_POC_Windows10.mp4: 윈도우즈10환경에서 숨겨진 자동적인 공격을 유발하는 iframe이 숨겨진 악의적인 웹 페이지를 통해 공격이 수행되는 영상
해커원 영상 링크 PoC SteamURL 비디오에 쓰인 html 페이지 공격 코드 입니다.
공격 코드
영향
우리의 악의적인 서버의 서버 info를 보는 어떠한 스팀 유저라도 공격자의 악의적인 임의의 코드 실행으로부터 공격받을 수 있습니다. 보통 공격자는 희생자의 컴퓨터의 제어권을 얻기위해 C2 기반구조와 연결되는 백도어를 실행합니다. 그곳에서부터 공격자는 공격자가 원하는 어떠한 것이라도 할 수 있습니다(예를 들어, 계정 탈취, 스팀 유저의 모든 아이템 훔치기, OS에 추가적인 악성프로그램 설치, 문서 빼내기 등).
공격 코드를 실행하기 위해서 사용자를 속이는 몇 가지 방법이 있습니다:
스팀 클라이언트 서버 브라우저의 서버 info를 사용자가 본다.
스팀 브라우저 프로토콜 요청이 실행되는 곳에서 사용자는 악의적인 웹 페이지를 방문한다: steam://connect/1.2.3.4
추가적으로, 공격 가능성을 높이기 위한 몇가지 방법이 있습니다:
스팀 브라우저 프로토콜을 이용한 웹사이트를 통해 공격이 유발됩니다.
많은 사용자들이 브라우저의 Open Steam 버튼을 누를 필요가 없습니다(항상 이러한 종류의 링크들은 관련된 애플리케이션에서 열립니다).
첫번째의 info 응답에 공격이 포함되어있지 않다면 이는 사용자를 속일 수 있는 좋은 방법이 됩니다.
해당 서버를 유저가 이용하도록 서버 이름을 잘 골라야 합니다.
(해당 서버에) 접속해있는 인원을 많게 설정할수록 더 많은 사람들이 접속할 가능성이 높습니다.
사람들이 접속하길 유도하기 위해 맵 이름을 흥미롭게 지어야 합니다.
해당 서버의 플레이어의 수가 이 서버가 수용할 수 있는 최대치에 도달한다면 서버 info 박스가 자동적으로 열리게 되며 첫번째 자동 새로고침 후 공격은 성공적으로 수행되게 됩니다.
Vinnie Vanhoecke @vinnievan and André Baptista @0xacb올림.