
CTF_WRITEUPS/TryHackMe /CVE-2021-41773/
CTF_WRITEUPS/TryHackMe /CVE-2021-41773/
간략한 역사
2021년 10월 5일, Apache HTTP Server v2.4.49의 경로 탐색 공격을 상세히 설명하는 CVE가 발표되었습니다. CVE-2021-41773 번호가 할당되었으며, 다음과 같은 설명과 함께 발표되었습니다:
Apache HTTP Server 2.4.49의 경로 정규화 변경에서 발견된 결함입니다. 공격자는 경로 탐색 공격을 사용하여 URL을 예상 문서 루트 외부의 파일에 매핑할 수 있습니다. 문서 루트 외부의 파일이 "require all denied"로 보호되지 않는 경우 이러한 요청이 성공할 수 있습니다. 또한 (sic) 이 결함은 CGI 스크립트와 같은 해석된 파일의 소스를 유출할 수 있습니다. 이 문제는 야생에서 악용되고 있는 것으로 알려져 있습니다. 이 문제는 Apache 2.4.49에만 영향을 미치며 이전 버전에는 영향을 미치지 않습니다.
이를 분석하여 실제로 우리에게 무엇을 의미하는지 살펴보겠습니다:
많은 수정 후...
그래서 Apache는 이 버그를 수정하고 v2.4.50을 출시했습니다. 끝난 이야기죠? 글쎄요, 그렇지 않습니다. 불과 이틀 후인 10월 7일에 이전 CVE를 인용하는 새로운 CVE가 발표되었습니다. 이 CVE는 이전 경로 탐색 공격에 대한 수정이 불완전했으며, 해당 경로가 Alias 지시문을 사용하여 URL을 파일 시스템에 매핑한 경우 여전히 탐색이 가능하다고 언급합니다. CVE-2021-42013 번호가 할당되었으며, 다음과 같은 설명이 있습니다:
Apache HTTP Server 2.4.50에서 CVE-2021-41773에 대한 수정이 불충분한 것으로 밝혀졌습니다. 공격자는 경로 탐색 공격을 사용하여 Alias와 같은 지시문으로 구성된 디렉토리 외부의 파일에 URL을 매핑할 수 있습니다. 이러한 디렉토리 외부의 파일이 일반적인 기본 구성인 "require all denied"로 보호되지 않는 경우 이러한 요청이 성공할 수 있습니다. 또한 이러한 aliased pathes (sic)에 CGI 스크립트가 활성화된 경우 원격 코드 실행이 가능할 수 있습니다. 이 문제는 Apache 2.4.49 및 Apache 2.4.50에만 영향을 미치며 이전 버전에는 영향을 미치지 않습니다.
이전과 마찬가지로 여기서 몇 가지를 배울 수 있습니다:
이 혼란을 처리하는 동안, 다음 과제에서 필요한 구성을 살펴보겠습니다.
아래 질문에 답하세요
이론의 약간
경로 탐색 익스플로잇은 경로 해석 및/또는 정규화의 결함을 남용하여 일반적으로 접근할 수 없는 리소스에 접근하려는 공격입니다. 우리는 일반적으로 .. 구문을 사용하여 가상의 루트를 넘어 뒤로 이동(또는 탐색이라고도 함)함으로써 이 유형의 공격을 악용합니다.
정규화? 뭐?
일반적으로 파일을 찾기 위해 코드에 경로를 제공할 때는 절대 경로가 필요합니다. 이를 표준 경로(canonical path)라고 부르겠습니다. 대신 상대 경로가 주어지면, 그 경로를 사용하는 OS 라이브러리가 해당 리소스를 찾을 수 있도록 표준 형식으로 정규화되어야 합니다. 물론 이는 지나친 단순화이지만 요점은 동일합니다.
일반적으로 이 정규화를 수행하는 플랫폼 라이브러리가 존재하지만, C/C++에서는 보통 모든 것을 직접 처리해야 합니다. 이는 약간의 유연성을 제공할 수 있지만, 구현이 완벽하지 않으면 쉽게 결함을 도입할 수 있습니다.
URL 정규화
HTTP 서버는 제공할 올바른 파일을 찾기 위해 URL을 파일 시스템의 표준 경로로 변환해야 합니다. 문서 루트를 넘어 탐색하지 못하도록 방지하는 필터가 분명히 있지만, 일부 사용 사례는 쉽게 간과될 수 있습니다. 이 경우 익스플로잇은 URL 인코딩(잠시 후에 다루겠습니다)뿐만 아니라 Alias 모듈의 경로 정규화 결함(추정상)을 이용합니다.
URL 인코딩에 대한 부가 설명
RFC 3986 섹션 2에 정의된 URL 인코딩은 URL 내에서 특수 또는 예약 문자를 인코딩하는 데 사용되는 체계입니다. 예를 들어, URL의 공백은 + 문자로 인코딩됩니다(특히 쿼리 매개변수에서). 실제 더하기 기호를 인코딩하려면 "퍼센트 인코딩(percent-encoding)"이라고 하는 것을 사용해야 합니다. 이는 단순히 문자에 대한 US-ASCII 16진수 코드 앞에 % 기호를 붙이는 것입니다. 예를 들어, + 기호는 %2B로 인코딩될 수 있습니다.
모든 문자는 URL 인코딩될 수 있으며, 완전히 URL 인코딩된 URL은 인코딩되지 않은 버전과 기능적으로 동일합니다. RFC에 따르면: 두 URI가 퍼센트 인코딩된 옥텟에 사용된 16진수 숫자의 대소문자만 다른 경우 동일합니다.
그래서 Apache에는 무슨 일이 일어났나요?
Apache 서버의 경로 정규화 모듈의 최근 변경으로 인해 특수하게 조작된 URL이 필터를 우회하고 문서 루트를 넘어 탐색할 수 있게 되어, 구성이 허용하는 경우 시스템에서 임의의 파일 읽기가 가능해졌습니다. 또한 CGI 모듈이 활성화된 경우 임의 파일 실행도 가능합니다!
아래 질문에 답하세요
A) 서버에서 처리할 임의의 원격 파일을 포함합니다. B) 서버에서 처리할 임의의 로컬 파일을 포함합니다. C) 서버에서 임의의 파일이 노출되도록 허용합니다. D) 위 중 어느 것도 아님.
재미로 Apache 해킹하기
이제 이론은 끝났으니, 이 결함을 악용해 봅시다. 먼저 취약한 버전의 Apache가 필요합니다. 다행히도 이를 위해 docker가 있습니다 :)```
user@machine$ docker pull httpd:2.4.49
2.4.49: Pulling from library/httpd
07aded7c29c6: Already exists
05bb40c8f148: Already exists
0827b74117da: Already exists
35a526fdcc7d: Pull complete
59fed288cd32: Pull complete
Digest: sha256:dcba0d12e2362fb0c50ec524ae8aa1cca4a4ba7216617a57e7bbca20767e79cc
Status: Downloaded newer image for httpd:2.4.49
docker.io/library/httpd:2.4.49
**설정**
이 익스플로잇이 작동하려면 Apache가 문서 루트 외부의 파일에 접근할 수 있도록 설정해야 합니다. 특정 디렉터리를 정확히 지정할 수도 있고, YOLO 방식으로 모든 것에 접근 권한을 줄 수도 있습니다. 우리의 목적에는 모든 것에 접근하는 것이 적합합니다. 시작하려면 컨테이너를 실행하고 설정을 살펴보겠습니다. 이러한 수정 사항은 취약한 두 Apache 버전 모두에서 작동합니다.```
user@machine$ docker run --name vuln-httpd -p 8080:80 -d httpd:2.4.49
a4dfc0376d93dc62183982a527b0bef62543e7a91178116bb0480a42ecc0c8dd
user@machine$ docker cp vuln-httpd:/usr/local/apache2/conf/httpd.conf .
user@machine$ grep -C4 -n "Require all denied" httpd.conf
246-# <Directory> blocks below.
247-#
248-<Directory />
249- AllowOverride none
250: Require all denied
251-</Directory>
252-
253-#
254-# Note that from this point forward you must specifically allow
--
303-# The following lines prevent .htaccess and .htpasswd files from being
304-# viewed by Web clients.
305-#
306-<Files ".ht*">
307: Require all denied
308-</Files>
309-
310-#
311-# ErrorLog: The location of the error log file.
user@machine$ sed "250s/denied/granted/" httpd.conf > httpd.new.conf
user@machine$ docker cp http.new.conf vuln-httpd:/usr/local/apache2/conf/httpd.conf
user@machine docker container restart vuln-httpd
vuln-httpd
참고로, 당신은 언제나 설정을 수동으로 수정할 수 있습니다. 우리는 다음 부분을 수정하려고 합니다:``` AllowOverride none Require all denied
그리고 denied를 granted로 바꿔야 합니다. 이렇게 하면 Apache가 전체 파일시스템에 접근할 수 있게 됩니다(물론 절대 좋은 방법이 아니므로 프로덕션에서는 절대 이렇게 하지 마세요).
**그 맛있는 RCE를 위한 설정**
접근 제어를 수정하는 것만으로는 데이터 노출만 가능할 뿐 RCE는 불가능합니다. 작은 PoC에서 RCE를 얻으려면 접근 권한과 더불어 CGI 모듈을 활성화하기만 하면 됩니다. 그러면 CGI 모듈이 스크립트를 호출할 때 단순히 내용을 표시하는 대신 스크립트를 실행하게 됩니다. CGI를 활성화하려면 LoadModule 설정의 주석 처리를 해제하기만 하면 됩니다. 앞서 수정한 컨테이너가 아직 있다고 가정하면 다음과 같이 할 수 있습니다:```
user@machine$ docker cp vuln-httpd:/usr/local/apache2/conf/httpd.conf .
user@machine$ grep -C4 -n "mod_cgi" httpd.conf
180-#LoadModule asis_module modules/mod_asis.so
181-#LoadModule info_module modules/mod_info.so
182-#LoadModule suexec_module modules/mod_suexec.so
183-<IfModule !mpm_prefork_module>
184: #LoadModule cgid_module modules/mod_cgid.so
185-</IfModule>
186-<IfModule mpm_prefork_module>
187: #LoadModule cgi_module modules/mod_cgi.so
188-</IfModule>
189-#LoadModule dav_fs_module modules/mod_dav_fs.so
190-#LoadModule dav_lock_module modules/mod_dav_lock.so
191-#LoadModule vhost_alias_module modules/mod_vhost_alias.so
--
385-
386-<IfModule cgid_module>
387- #
388- # ScriptSock: On threaded servers, designate the path to the UNIX
389: # socket used to communicate with the CGI daemon of mod_cgid.
390- #
391- #Scriptsock cgisock
392-</IfModule>
393-
user@machine$ sed "184,187s/#//" httpd.conf > httpd.new.conf
user@machine$ docker cp http.new.conf vuln-httpd:/usr/local/apache2/conf/httpd.conf
user@machine docker container restart vuln-httpd
vuln-httpd
물론 사용 가능한 텍스트 편집기를 사용하여 파일을 수정할 수 있습니다. grep/sed 방식은 컨테이너 내 셸에서 작동하며, 텍스트 편집기가 제공되지 않습니다.
드디어 익스플로잇으로 넘어가자!
이제 컨테이너를 설정했으니, 드디어 이 CVE를 익스플로잇할 수 있습니다. 방법은 상당히 간단하며, 경로를 탐색할 때 각 URL 경로 세그먼트에 있는 . 기호 중 하나를 URL-인코딩하는 방식입니다. 또한 별칭이 지정된 경로에서 탐색해야 합니다. 다행히도 구성 파일을 읽어보면 기본적으로 cgi-bin 경로에 별칭이 지정되어 있으므로, 이를 활용합시다! 익스플로잇은 버전 2.4.49와 2.4.50 사이에 약간 차이가 있지만, 후자는 전자에서도 작동합니다.
Apache 2.4.49에서 CGI가 활성화되지 않은 경우