본문 바로가기

카테고리 없음

[CVE-2016-6277] NETGEAR R7000 공유기 취약점 분석

동향 파악을 위해 자료를 수집하던 중 WINS 블로그(http://www.wins21.co.kr/blog/blog-sub-01.html?t=31&num=1286)에서 Mirai 변종이 NETGEAR 제품의 취약점을 공격한다는 내용을 접했습니다. 어떤 취약점인지 궁금했는데, 블로그에는 분석 내용이 없어서 링크되어 있는 ExploitDB(https://www.exploit-db.com/exploits/41598)에서 공격 페이로드를 확인하고, 펌웨어를 분석해서 'Root cause'를 확인했습니다.


최근에 IoT 취약점 분석과 펌웨어 리버싱에 관련된 질문이 많아서 간단하게라도 한번 공유하는게 좋을 것 같아서 서툰 실력으로 블로그를 작성하게 되었습니다. 앞으로 재미있는 대상이나 흥미로운 취약점 같은 유의미한 결과물이 있을 때 종종 블로그에 글을 작성하려고 합니다.


그럼 취약점 분석으로 한번 훅~ 들어가 보겠습니다.


먼저, 취약점 분석을 위해 ExploitDB에 있는 공격 페이로드를 확인했습니다.

[그림-1] ExploitDB에서 확인한 공격 페이로드 (https://www.exploit-db.com/exploits/41598)


화면 캡처에 보이는 것처럼 HTTP URI에 OS 명령어 삽입 취약점이 존재한다는 것을 유추할 수 있습니다.


취약점이 발생하는 포인트를 확인했으니 이제 분석할 펌웨어 버전을 확인해야 합니다. 위 공격 코드는 Metasploit으로 작성되어 있는데, Metasploit에 등록하는 공격 코드의 대부분은 'Description' 필드에 취약한 소프트웨어 버전이 명시되어 있습니다.

[그림-2] 펌웨어 버전 확인


NETGEAR R7000 v1.0.7.2 버전과 그 이전에 릴리즈된 펌웨어가 취약한 것으로 확인됩니다.


이제 펌웨어를 다운로드 해야합니다. NETGEAR는 글로벌 벤더답게 펌웨어 관리가 잘되는 회사 중 하나입니다.

NETGEAR Download Center(https://www.netgear.com/support/download/default.aspx)에서 각 제품별로 현재까지 릴리즈된 모든 펌웨어를 다운로드 할 수 있습니다.


아래 보이는 것처럼 제품명을 입력하고 엔터를 누르면 펌웨어와 애플리케이션 정보 등이 출력됩니다. 과거 버전을 찾고 싶으면 우측 하단의 빨간색 박스 안에 있는 버튼을 클릭하면 됩니다.

[그림-3] 펌웨어 다운로드

펌웨어를 다운로드 한 뒤, 취약점 분석을 위해 펌웨어에서 파일시스템(RootFS)를 추출해야 합니다.

R7000 펌웨어는 ZIP으로 압축되어 있습니다. 압축을 해제하고 binwalk를 사용하면 다음과 같이 SquashFS 파일시스템이 펌웨어에 포함되어 있는 것을 확인할 수 있습니다.

[그림-4] 펌웨어 구조 확인


이렇게 확인한 파일시스템을 dd로 추출해서 unsquashfs(https://www.systutorials.com/docs/linux/man/1-unsquashfs/)로 바이너리를 추출해도 되지만, binwalk의 -e와 -o 옵션을 사용하면 보다 편하게 바이너리를 추출할 수 있습니다.


[그림-5] 루트 파일시스템 추출 및 확인


NETGEAR의 웹 서버 데몬은 /bin/httpd 바이너리이므로 해당 바이너리를 분석하면 취약점의 'Root cause'를 확인할 수 있습니다. 이렇게 사전에 정보를 알고 있으면 제품이 없어도 분석할 수 있지만, 그렇지 않은 경우에는 grep 같은 도구를 사용해서 1차로 바이너리를 선정하고, 선정된 바이너리를 분석해서 취약한 바이너리를 찾아내야 합니다. 말 그대로 노가다죠 ... 돈이 최고입니다. 그냥 사면 한방에 해결되요. 하지만, NEGEAR R7000은 프리미엄 게이밍 공유기로 싯가가 무려 18만원...(눈물 또르륵..)


/bin/httpd 바이너리를 IDA로 열어서 가장 먼저, cgi-bin 문자열을 참조하는 코드를 확인했습니다.

[그림-6] cgi-bin 문자열을 참조하는 코드 확인


위 화면 캡처에 보이는 것처럼 딱 봐도 무언가 인젝션 될 것 같은 위험한 문자열이 특정 함수(sub_36C44)에서 사용되는 것을 확인했습니다. 언제나 그렇지만... 문자열 검색에서 %s를 만나면 심장이 바운스~바운스~, 왠지 취약점이 나올 것만 같죠 ?

%s 포멧을 사용하는 모든 문자열이 취약한건 아니지만... in my experience에 따르면 취약점이 잘 관리된 소프트웨어는 문자열을 포멧팅할 때, 사용자 입력값이 포함되는 부분을 '(single-quotes)로 감싸는 경우가 많았습니다.

취약점이 존재하는지 확인하기 위해 sub_36C44 함수를 분석했습니다.

아래 화면 캡처에 보이는 것처럼 sub_36C44 함수는 URL에서 사용자가 요청한 CGI 이름과 쿼리스트링 값을 추출합니다.


데이터 추출 예시 : http://127.0.0.1/cgi-bin/[cgiName]?[queryString]

[그림-8] sub_36C44 함수 분석 #1


그리고, 이렇게 추출한 값을 HTTP 메서드에 따라 특정 명령어를 실행하는데 사용합니다. 코드를 보니 CGI를 실행하고, /tmp/[HTTP_METHOD]_result 파일에 실행 결과를 기록하기 위한 것으로 보입니다. 화면 캡처에 주석이 달린 것처럼 system 함수를 실행할 때, 사용자 입력값인 CGI 이름(cgiName)에 대한 아무런 검증도 진행하지 않기 때문에 /cgi-bin/;wget blah~blah~;처럼 OS 명령어를 삽입할 수 있는 취약점이 발생합니다.

[그림-8] sub_36C44 함수 분석 #2



취약점이 확인되었습니다. 거의 99% 확신하지만, 그래도 혹시 모르니 sub_36C34 함수를 호출하는 코드들을 확인해봤습니다.

handle_post, handle_options, handle_get 함수에서 호출하는 것을 확인할 수 있었습니다. 즉, sub_36C34는 GET, POST, OPTIONS 요청을 처리하기 위해 호출되는 함수이며, 해당 함수에서 사용자 입력값인 URL을 처리할 때, CGI 이름에 대한 검증 미흡으로 인해 OS 명령어를 삽입할 수 있는 취약점이 발생하는 것입니다.[그림-9] sub_36C44를 호출하는 코드 확인


이렇게 급 마무리를 해야할 것 같습니다.

오랜만에 아침부터 글을 썼더니... 눈도 침침하고, 배도 고프네요.


"다음에 다시 봐요 ... 제발..."