
TryHackMe의 Source 방에 대한 분석 글 및 취약점을 익스플로잇하는 파이썬 스크립트
TryHackMe의 Source 룸에 대한 분석 및 취약점을 악용하는 파이썬 스크립트
이 취약점의 발견에 대한 어떠한 공로도 제가 인정하지 않습니다. 저 같은 사람들이 배울 수 있도록 자료를 제공해 주신 다음 분들께 감사드립니다!
취약점 발견:
Özkan Mustafa Akkuş
MSF 모듈:
https://github.com/rapid7/metasploit-framework/blob/master/modules/exploits/linux/http/webmin_backdoor.rb
https://www.rapid7.com/db/modules/exploit/linux/http/webmin_backdoor/
MSF 모듈 작성자:
wvu
TryHackMe 룸:
https://tryhackme.com/room/source
THM 작성자:
https://tryhackme.com/p/DarkStar7471
참고 자료:
https://www.webmin.com/exploit.html
https://github.com/webmin/webmin/issues/947
https://www.perlmonks.org/?node_id=301355
저는 결코 노련한 보안 전문가가 아닙니다. 즉, 제가 잘못된 정보를 제공할 수도 있습니다. 만약 노련한 전문가/경험 많은 연구자이시고, 제가 작성한 내용 중 잘못된 정보를 발견하신다면, 저에게 알려주시기 바랍니다. 그래야 제가 돌아와서 잘못된 부분을 공부하고 올바른 정보를 제공할 수 있습니다. 이는 저뿐만 아니라 이 분석을 우연히 접할 수 있는 다른 초보 연구자들에게도 도움이 됩니다. 제가 잘못된 정보를 작성했다면, [email protected]으로 연락해 주시면 수정하겠습니다. 감사합니다!
1. 역사
Webmin은 유닉스 계열 시스템 관리를 위한 웹 기반 도구입니다. 2018년 1분기 어느 시점에 Webmin은 공급망 공격을 받았습니다. 알려지지 않은 공격자가 password_change.cgi 파일에 악성 코드를 삽입하여 기본 구성으로 해당 버전의 Webmin(1.890)을 호스팅하는 모든 시스템에 백도어가 열릴 수 있는 취약점을 만들었습니다. 이를 공급망 공격이라고 부르는 이유는 소프트웨어 개발자/배포자의 제품 소스 코드가 손상되었기 때문입니다. 공급자가 손상된 제품을 출시했을 때, 소프트웨어를 업데이트한 모든 사용자는 취약한 코드를 실행하게 되어 공격자가 취약한 코드를 실행하는 모든 시스템을 손상시킬 수 있게 되었습니다. 같은 해, Webmin 개발자들은 상황을 인지하고 파일을 원래 상태로 되돌렸지만, 공격자는 코드를 다시 삽입할 수 있었습니다. 이번에는 만료된 암호 변경 옵션이 활성화된 경우에만 코드가 취약했습니다. 이 취약점은 2019년 8월이 되어서야 발견되었습니다. 취약점은 Webmin 버전 1.930에서 패치되었습니다.
2. 코드
검색 끝에 Webmin 버전 1.890을 명령 삽입에 취약하게 만든 코드 라인을 찾을 수 있었습니다. 올바른 정보를 찾는 데 어려움을 겪었는데, 이 문제에는 두 개의 다른 CVE(CVE-2019-15231 / CVE-2019-15107)가 연관되어 있기 때문입니다. CVE-2019-15231은 버전 1.890의 기본 구성 취약점과 관련이 있고, CVE-2019-15107은 1.920까지의 버전에서 만료된 암호 변경 옵션이 활성화되어야 하는 취약점과 관련이 있습니다. 버전 1.890의 코드를 살펴보겠습니다. password_change.cgi의 12번째 줄에는 다음과 같은 코드가 있습니다:
$in{'expired'} eq '' || die $text{'password_expired'},qx/$in{'expired'}/;
이 글을 작성하는 현재까지 저는 perl로 어떤 코드도 작성해 본 적이 없습니다. 검색 엔진을 사용하여 이 코드 줄을 분석하여 코드가 무엇을 하는지, 왜 악용에 취약한지 더 잘 이해해 보겠습니다. || 연산자의 왼쪽에 있는 첫 번째 코드 부분은 변수($in)가 매개변수(expired)를 받아 빈 문자열 ''과 같은지(eq) 확인하는 것으로 보입니다. 중간에는 || 연산자가 있습니다. ||는 perl에서 논리 연산자 or를 사용하는 또 다른 방법입니다. perl에서 ||를 사용할 때, 연산자의 왼쪽이 참이면 오른쪽은 평가되지 않습니다. 왼쪽이 거짓이면 오른쪽이 평가됩니다. || 연산자의 오른쪽에 있는 첫 번째 코드 부분에서는 die $text{'password_expired'}를 볼 수 있습니다. perl에서 die는 스크립트 프로세스를 종료하고 오류 메시지를 표시하는 함수입니다. 메시지는 아마도 $text 변수에 암호가 만료되었다는 내용이 들어 있을 것입니다. 마지막 코드 부분이 흥미로운 부분입니다. 쉼표 , 뒤에 qx/$in{'expired'}/가 있고, 세미콜론 ;으로 줄이 끝납니다. 쉼표는 코드의 구분자 역할을 하며, 왼쪽 부분이 먼저 평가된 다음 오른쪽 부분이 평가됩니다. perl에서 qx는 호스트에서 시스템 명령어를 실행할 수 있는 함수입니다. //는 매개변수를 식별하는 데 사용되는 구분자입니다. 이 경우 qx/$in{'expired'}/는 $in{'expired'} 매개변수를 시스템 명령어로 실행합니다. $in 변수는 php의 $_GET과 비슷한 것이라고 생각합니다. 그 이유는 제가 작성한 익스플로잇 스크립트에 expired라는 매개변수가 있고, 이 매개변수에 페이로드를 저장한 후 POST 요청을 통해 서버로 보내기 때문입니다. 해당 코드는 data = {'expired':payload,}와 같습니다. $in 변수는 우리가 설정한 expired 값을 검색하여 qx 함수가 실행할 수 있도록 하는 역할을 하는 것 같습니다. 이 섹션을 마무리하자면, 취약한 코드 라인은 POST 요청의 expired 매개변수가 빈 문자열이 아님을 발견하므로 || 연산자는 오른쪽 코드를 평가하고 expired 매개변수에 저장된 페이로드를 실행합니다. 이제 TryHackMe.com의 Source 룸 분석으로 넘어가겠습니다.
포트 스캔부터 시작하겠습니다. nmap은 너무 느릴 수 있으므로 rustscan을 사용하여 광범위한 개요를 얻겠습니다.

2개의 포트(22, 10000)가 열려 있는 것 같습니다. 이제 nmap을 사용하여 각 포트에서 실행 중인 서비스를 확인하겠습니다.

SSH가 표준 포트에서 실행 중이고, HTTP 서비스가 10000번 포트에서 실행 중입니다. 10000번 포트의 페이지로 이동하여 무엇이 있는지 확인해 보겠습니다.

이 페이지에 액세스하려면 HTTPS를 사용하고 SSL 인증서 경고를 우회해야 합니다. Webmin 서비스의 로그인 페이지인 것 같습니다. 원래 이 박스를 처음 진행했을 때, 몇 가지 디렉터리 무차별 대입 시도를 해봤지만 특별히 흥미로운 것은 없었습니다. nmap 스캔에서 얻은 webmin 버전에 searchsploit을 통해 취약점이 있는지 확인해 보겠습니다.

몇 가지 옵션이 있는 것 같지만, 우리 버전과 일치하는 것은 없습니다. MSF를 열어서 어떤 작업을 할 수 있는지 살펴보겠습니다.

여기서 선택할 수 있는 몇 가지 옵션이 있습니다. nmap에서 얻은 webmin 버전을 검색하여 어떤 CVE가 있는지 확인해 보겠습니다.

취약점 요약에서 password_change.cgi 파일에 대한 언급이 있습니다. MSF 검색 결과에서 5번을 사용해 보겠습니다. 이 옵션도 password_change.cgi 파일과 동일한 공개 날짜를 언급하고 있기 때문입니다.

사실 MSF를 사용하지는 않을 것입니다. MSF도 좋지만, 직접 코드를 작성하여 무언가를 악용하는 방법을 알아내는 것만큼 재미있지는 않습니다! 저는 이 익스플로잇을 위해 루비 소스 코드를 참조하여 파이썬으로 자신만의 익스플로잇 코드를 만들었습니다. 대신 그것을 사용해 보겠습니다!

짜잔! 룸에서 루트 셸을 얻었습니다! 플래그는 공개하지 않겠습니다. 여러분이 찾을 수 있을 거라고 확신합니다! 읽어주셔서 감사합니다. 좋은 하루 되세요!