
Proof-of-concept 익스플로잇 및 HiSilicon hi3520d DVR/NVR 장치에 대한 취약점 공개. 웹 인터페이스를 통한 RCE, 백도어 자격 증명, 버퍼 오버플로 분석을 시연합니다.
= HiSilicon DVR 해킹 Istvan Toth [email protected] v1.0, 2017-09-06 :source-highlighter: pygments :toc: preamble :toclevels: 5 :toc-title: 목차 :image_width: 100%
[abstract] 이 보고서는 HiSilicon hi3520d 및 유사한 시스템 온 칩(SoC)을 사용하는 DVR/NVR 장치의 심각한 취약점(개념 증명(PoC) 코드 포함)을 공개합니다. 이 취약점을 악용하면 웹 인터페이스만으로 인증되지 않은 원격 코드 실행(RCE)이 가능해지며, 악용된 장치를 완전히 장악할 수 있습니다. 업그레이드된 펌웨어가 없기 때문에 이러한 장치를 사용하는 것은 권장되지 않습니다. 2016년 12월 이전에 공급업체에 연락했지만 여전히 응답이 없습니다. 공개 날짜는 2017년 2월입니다.
== 서문
몇 년 전에 나는 eBay에서 값싼 중국제 DVR 장치를 하나 샀다. 장치의 부팅 로고에는 "SECULINK - Security Monitoring"이라고 적혀 있다. IT 보안 애호가로서, 그 보안 모니터링 서비스가 얼마나 "안전한지" 확인하기 위해 장치를 자세히 살펴보기로 했다. 주제에 대해 구글링하던 중 흥미로운 자료를 몇 가지 발견했지만, 더 깊이 파고들자 그 장치에 대해 훨씬 더 흥미롭고 훨씬 더 심각한 문제(0-days)를 발견했다.
처음부터 전체 해킹 과정을 살펴보자. (새롭고 독자적인 성과는 물론 기존에 알려진 것들도 함께 언급할 것이다.)
== DVR 살펴보기
먼저 공식 사용자 인터페이스를 익힌 다음 더 깊이 파고들어 펌웨어를 얻으려고 시도해 보자. 취약점을 발견할 가능성은 펌웨어와 함께 높아진다.
=== DVR 첫인상
테스트용 DVR 장치는 "Seculink" 브랜드로 판매된다.
image::./seculink_device.png[Seculink DVR 장치]
사용 가능한 물리적 인터페이스:
공식 사용자 인터페이스:
직접 액세스 가능한 설정 인터페이스는 사용자 인증(사용자 이름, 비밀번호)으로 보호된다. 기본 슈퍼유저는 'admin'이고 기본 비밀번호는 비어 있다.
강력한 비밀번호를 설정한 후에는 자신의 카메라 화면을 다른 사람이 볼 수 없다고 느낄 수 있다. 사람들은 종종 DVR 장치의 웹 포트(tcp/80)를 안전한 LAN에서 WAN 쪽으로 포워딩하여 외부에서 DVR 스트림에 접근한다 (예를 들어 적절한 Shodan 검색으로 확인할 수 있다 ;) ).
=== 펌웨어 획득
펌웨어를 얻는 방법은 여러 가지가 있을 수 있다:
여기서는 후자(다운로드) 방법이 작동하고 가장 쉽지만, 첫 번째 방법을 시도해 보자. 첫 번째 방법은 장치에 대한 다른 정보도 제공하기 때문이다.
=== 서비스 스캐닝
DVR에 대해 전체 포트 스캔을 수행해 보자. (root로 실행할 때 기본인) SYN 스캔은 드롭된 패킷 때문에 매우 느리지만, 전체 TCP 연결 스캔은 몇 분 안에 끝난다.
Nmap scan report for dvr.lan (192.168.88.127) Host is up (0.028s latency). Not shown: 65529 closed ports PORT STATE SERVICE VERSION 23/tcp open telnet BusyBox telnetd 80/tcp open http uc-httpd 1.0.0 554/tcp open rtsp LuxVision or Vacron DVR rtspd 9527/tcp open unknown 34567/tcp open dhanalakshmi? 34599/tcp open unknown MAC Address: 00:12:12:15:B3:E7 (Plus ) Service Info: Host: LocalHost; Device: webcam
요약 및 수동 테스트:
rtsp 스트림을 여는 데에도 자격 증명이 필요하다는 점에 유의하라.
여기서 이 장치는 아마도 Linux 계열 시스템일 것이라고 말할 수 있다.
9527/tcp에 (raw netcat으로) 연결하면 로깅 메시지와 로그인 프롬프트가 있는 애플리케이션 콘솔이 표시된다. 정의된 애플리케이션 자격 증명 중 하나로 로그인하면 작동한다. 프롬프트에서 help를 입력하면 콘솔 명령에 대한 간단한 설명이 표시된다. shell 명령이 가장 흥미로워 보인다. 그렇다, 장치에 루트 셸을 제공한다. ;)
이것은 분명히 심각한 보안 문제이다. (낮은 권한의) 애플리케이션 사용자가 장치에서 자동으로 루트 셸을 얻어서는 안 되기 때문이다.
=== 루트 셸
루트 셸에서 장치를 탐색해 보면 (예: dmesg) DVR이 Linux 커널(버전 3.0.8)을 실행하고 있고 ARMv7 CPU를 가지며 SoC 모델이 hi3520d라는 것이 분명해진다.
실행 중인 프로세스 목록(ps)에서 DVR 애플리케이션이 /var/Sofia이며, 이는 nmap이 탐지한 위의 tcp 포트 외에도 34568/udp 및 34569/udp에서도 수신 대기 중임을 알 수 있다 (netstat -nlup).
마운트된 디스크 목록(mount 명령)에서 펌웨어 이미지가 /dev/mtdblockX 장치(X=0,1,2,3,4,5)에 있음이 분명하다.
펌웨어는 작고 따라서 제한적이므로, 장치에서/로 파일을 복사하려면 창의적이어야 한다. 다행히 NFS를 지원하므로 데스크톱 머신에 NFS 서버를 설정하고 DVR에서 마운트하면 문제가 해결된다:
이제 펌웨어를 얻는 것은 간단하다:
파일(원시 이미지뿐만 아니라)을 얻을 수도 있다:
=== 텔넷 인터페이스
텔넷 인터페이스(포트 23/tcp)를 통해 장치에 접근하려면 OS 자격 증명이 필요할 수 있다. /etc/passwd를 보면 root 사용자의 비밀번호 해시가 있다:
root 외에는 다른 사용자가 없으며 모든 것이 전체 권한으로 실행된다는 점에 유의하라. (그래서 누군가 어떻게든 장치에 침입하면 장벽이 없으며, 공격자는 즉시 완전한 권한을 얻는다.)
6자리 영숫자(소문자) 비밀번호를 가정하면 hashcat은 위의 약한 DES 해시를 빠르게 크랙한다:
$ ./hashcat64.bin -a3 -m1500 absxcfbgXtb3o -1 ?l?d ?1?1?1?1?1?1
absxcfbgXtb3o:xc3511
Session..........: hashcat Status...........: Cracked Hash.Type........: descrypt, DES (Unix), Traditional DES Hash.Target......: absxcfbgXtb3o Time.Started.....: Sun Sep 3 03:25:07 2017 (2 mins, 29 secs) Time.Estimated...: Sun Sep 3 03:27:36 2017 (0 secs) Guess.Mask.......: ?1?1?1?1?1?1 [6] Guess.Charset....: -1 ?l?d, -2 Undefined, -3 Undefined, -4 Undefined Guess.Queue......: 1/1 (100.00%) Speed.Dev.#1.....: 815.9 kH/s (203.13ms) Recovered........: 1/1 (100.00%) Digests, 1/1 (100.00%) Salts Progress.........: 121360384/2176782336 (5.58%) Rejected.........: 0/121360384 (0.00%) Restore.Point....: 93440/1679616 (5.56%) Candidates.#1....: sa8711 -> h86ani HWMon.Dev.#1.....: N/A
따라서 사용자 root와 비밀번호 xc3511을 사용하면 포트 23/tcp의 텔넷 인터페이스를 통해 로그인할 수 있다. 닫을 수 없는 텔넷 인터페이스에서 접근 가능한 이 하드코딩된 root 계정은 분명히 백도어이다.
이러한 결과는 우리의 연구 이전에 다른 사람들에 의해 거의 알려져 있었지만, 다음 내용은 완전히 새로운 것이다.
== 펌웨어 리버싱
펌웨어를 탐색해 보면 바이너리 /var/Sofia가 비디오 처리 등을 제외한 모든 인터페이스를 구현하는 주요 애플리케이션임을 알 수 있다. 따라서 이 바이너리가 우리에게 가장 흥미로워 보인다.
불행히도 (정적으로 링크되어 있고) 스트립(stripped)되어 있어 정적 분석이 더 어렵다:
따라서 정적 분석(radare2 또는 IDA 사용) 외에도 동적 분석이 매우 유용할 것이다.
=== 원격 gdb
동적 분석을 위해서는 원격 /var/Sofia 애플리케이션에 GNU 프로젝트 디버거(GDB)를 연결하는 것이 유리할 것이다. 권장되는 방법은 원격 장치에서 gdbserver를 실행(및 연결)하고 로컬 머신에서 gdb로 연결하는 것이다.
물론 적절한 ARM 아키텍처용으로 (가급적 정적으로) 컴파일된 gdbserver가 필요하다. 이를 빌드하려면 임베디드 시스템(우리의 DVR과 같은)에 권장되는 C 라이브러리인 https://www.uclibc.org/[µClibc]를 사용할 수 있다. 사용 가능한 빌드는 동적 빌드인데, 이는 우리 DVR에서 문제가 되므로 직접 맞춤형 정적 빌드를 만들어야 한다. https://buildroot.org/[Buildroot]라는 훌륭한 빌드 환경이 있으며, 이를 사용하면 바로 빌드할 수 있다 (make menuconfig로 필요한 앱(예: gdb)을 선택하고, 정적 라이브러리를 선택하는 것을 잊지 말고, make를 실행하면 된다).
짧은 빌드 시간(~10-15분) 후에 필요한 모든 도구를 사용할 수 있다. 정적 바이너리는 앞서 언급한 NFS 방법으로 장치에 전송할 수 있다. Sofia 바이너리가 포함된 /var 디렉토리는 ramfs이므로 재부팅 후에도 유지되지 않는다는 점에 유의하라. 바이너리를 (거의) 영구적으로 전송하려면 구성 파일이 포함된 rw 파티션 /mnt/mtd가 적합한 대상이 될 것이다. openssh 패키지도 빌드하면 scp를 사용할 수 있어 파일 전송이 더 쉬워진다.
이제 펌웨어는 리버싱할 준비가 되었다. 원격으로 gdbserver를 연결하는 것이 이제 작동한다 (Sofia 프로세스의 PID는 ps로 쉽게 얻을 수 있다):
로컬 머신에서 연결:
일부 GDB 확장(예: http://gef.readthedocs.io/en/master/[GEF])을 사용하는 것이 좋다. 어떤 이유로 애플리케이션 일시 중지(C-c)가 작동하지 않으면 Sofia 프로세스에 TRAP 신호를 보내면(kill -TRAP 610) 일시 중지될 것이다.
=== 인증 절차 검사
정적 분석을 위한 권장 도구는 당연히 Hex-Ray의 https://www.hex-rays.com/products/ida/[IDA Pro]이다. 불행히도 저렴하지는 않지만 다른 어떤 도구보다 훨씬 낫다.
초기 자동 분석 후 15,000개 이상의 함수가 있지만, IDA를 사용하면(간단한 Python 스크립팅으로) 인증 함수를 찾는 것은 순식간이다. 아래의 https://www.hex-rays.com/products/ida/support/idapython_docs/[IDAPython] 스니펫은 "Users" and "Password"와 관련된 모든 것을 (동시에) 참조하는 함수를 검색한다:
결과는 단 하나의 함수뿐이다: sub_2D857C. 이 함수를 빠르게 분석해 보면 이것이 인증 함수임을 확인할 수 있다.