들어가며

이전 WeVO 공유기 제품군 펌웨어에는 인증 없이 공유기 설정을 바꿀 수 있고, 더 나아가서 잘못 작성된 공유기 설정 페이지로 인해 Command injection 공격을 수행할 수 있는 취약점이 존재하였습니다. 이 취약점은 KISA 버그 바운티 프로그램을 통해 제보되었고, 제조사는 *일단은* 버그픽스를 릴리즈하였습니다.

하지만 이 제조사의 버그픽스에는 큰 문제가 존재하였습니다. WeVO 의 패치는 해당 취약점 세트에 있던 취약점 중, 인증 없이 설정 API 엔드포인트에 접근할 수 있는 문제만 수리하였고, 나머지 커맨드 인젝션 취약점은 남겨두었습니다. 또한 API 엔드포인트에 CSRF 방어 메커니즘 구현이 아예 존재하지 않아, CSRF 를 통해 커멘드 인젝션을 트리거할 수 있는 문제가 발생하였습니다.

이후, 이를 KISA에 2018년 10월에 제보하였으나, KISA는 이를 제조사의 EOL 선언을 이유로 패치 발행 요청을 하기를 거부하였습니다. 이에 저는 이 취약점을 알리고, 대안 펌웨어로 사람들을 유도하는 것이 이 취약점을 묻어두는 것보다 공공의 이득이 더 클 것으로 판단해 해당 취약점을 공개합니다.

취약점 발생 원인

이 취약점이 발생하게 된 큰 원인은 다음 두 가지입니다

  1. 검증되지 않은 사용자 데이터를 이용해 만든 커멘드 명령을 system(3) 콜을 이용해 실행하였음
  2. API 엔드포인트에 CSRF 방어 매커니즘이 구현되어있지 않음.

이제 이 두 가지가 어떻게 일어났는지 알아봅시다

커맨드 인젝션

해당 펌웨어에서, 사용자의 POST 요청을 처리하는 CGI 엔드포인트들 중,
cgi-bin/internet.cgi
파일을 strings 명령으로 살펴보면 다음과 같은 결과를 얻을 수 있습니다.

route del
255.255.255.255
-host
-net
%s netmask %s
%s dev %s

이러한 문자열의 존재로부터 이 CGI 엔드포인트는 아마도 다음과 같은 방법으로 동작할 것이라고 가설을 세울 수 있습니다.

  1. 사용자 파라미터를 받는다.
  2. 사용자 파라미터를 sprintf(3) 과 같은 함수를 이용해, 템플릿에 채워 넣는다.
  3. 해당 파라미터를 system(3) 에 넘겨 실행한다.

이 과정에서, 사용자 파라미터를 무조건적으로 신뢰할 경우, command injection 을 비롯한 여러 가지 문제점이 발생하게 됩니다.

이제, 해당 바이너리를 Ghidra 를 이용해 열어봅시다

rodata

해당 바이너리의 .rodata 섹션을 보면, 아까 확인했던 것과 같은 format string 들이 있는 것을 확인할 수 있습니다. 이제 “%s netmask %s” 라는 포멧 스트링을 참조하고 있는 set_add_routing 펑션으로 따라가 보면

다음과 같이 form multipart 데이터를 받아서

다음과 같이 sprintf(3) 를 이용해 커맨드라인을 빌드하는 것을 볼 수 있습니다. 이는 처음의 추정과 일치하며, command injection 공격과 sprintf(3) 를 통한 스택 버퍼 오버플로우의 가능성을 열어주게 됩니다.

CSRF 방어 매커니즘

해당 공유기 웹 페이지에서 일어나는 POST 요청들을 웹 개발자 도구로 살펴보면 다음과 같은 결과를 얻을 수 있습니다.

이 결과로부터, 이 웹 페이지는 CSRF 토큰을 전송하지 않고 있음을 알 수 있고, 이는 전통적인 CSRF 공격이 해당 웹 페이지를 대상으로 통할 확률이 매우 높다는 직감을 전해줍니다.

취약점 검증

  • WeVO 의 설정 엔드포인트는 form multipart 데이터를 POST 로 받아서 동작합니다. 이는 단순한 HTML form 태그를 이용해 Same origin policy 에 얽매이지 않는 POST 요청을 보낼 수 있음을 의미합니다.
  • 이를 트리거하기 위한 폼 코드는 다음과 같습니다.
  • 이 HTML페이지에서 Reboot! 버튼을 누르면, dest 필드에 111.111.111.111; reboot; 을 넣어서 Form multipart 데이터를 http://192.168.10.1/cgi-bin/internet.cgi 로 전송하게 되고, 이는 커맨드 인젝션을 통해 공유기를 재부팅 시키게 됩니다.

취약점을 이용한 PoC와 OpenWRT 설치 툴

이제 이 포스팅의 최종 목적인, 해당 취약점을 이용해 OpenWRT 를 설치하는 도구를 공개합니다.

많이 다듬어지지 않은 스크립트이며, 잠재적으로 문제를 일으킬 수 있습니다. 이 툴 사용에 따른 문제에 대해서는 어떤 책임도 지지 않습니다. Use at your own risk.

https://github.com/perillamint/WeVO-CSRF-Demo

Q&A

Q. 이 문제에 대해 일반인이 취할 수 있는 대응 방법은 뭔가요?
A. 적어도 “본 제품은 외부 해킹 공격자로부터 사생활 보호 및 개인정보 유출 우려를 방지하기 위해 KISA 보안 규격 권고안을 준수하고 있음.” 같은 야부리만 터는 회사보다는 보안에 더 신경쓰는 OpenWRT 펌웨어로 갈아타세요

Q. 왜 WeVO 펌웨어 업데이트 인터페이스를 사용할 수 없나요
A. WeVO 펌웨어 파일은 uImage 외에 별도의 데이터가 더 붙어 있는 구조입니다. 이를 호환시키기 위해서는 해당 파일을 검사하는 루틴을 리버싱해서 펌웨어 생성 툴(mkwevofw) 을 만들어야 하는데 제가 그걸 하기에는 인생의 여유가 없어서…


Q. 왜 mkwevofw 안 만들어요?
A. 더 뜯기엔 인생에 여유 시간이 없어요 ㅜㅜ 시간 생기면 해 볼 지도…


UPDATE 2019-09-11T23:53:00+0900: mkwevofw 만들었습니다. https://blog.quendi.moe/2019/09/11/ko-wevo-%ea%b3%b5%ec%9c%a0%ea%b8%b0-%ed%8e%8c%ec%9b%a8%ec%96%b4-%ec%97%85%eb%8d%b0%ec%9d%b4%ed%8a%b8-%eb%a3%a8%ed%8b%b4-%eb%a6%ac%eb%b2%84%ec%8a%a4-%ec%97%94%ec%a7%80%eb%8b%88%ec%96%b4%eb%a7%81/