hacktricks/network-services-pentesting/pentesting-web/nginx.md
2024-02-10 21:30:13 +00:00

16 KiB
Raw Blame History

Nginx

htARTE (HackTricks AWS Red Team Expert)에서 AWS 해킹을 처음부터 전문가까지 배워보세요!

HackTricks를 지원하는 다른 방법:

취약점 평가 및 펜테스트를 위한 즉시 사용 가능한 설정. 20개 이상의 도구 및 기능을 사용하여 어디에서나 전체 펜테스트를 실행하십시오. 우리는 펜테스터를 대체하지 않습니다 - 대신 펜테스터가 더 깊이 파고들고, 쉘을 팝하고, 재미를 느낄 수 있도록 사용자 정의 도구, 탐지 및 공격 모듈을 개발합니다.

{% embed url="https://pentest-tools.com/" %}

누락된 루트 위치

Nginx 루트 디렉토리 구성 요소

Nginx 서버를 구성할 때 root 지시문은 파일이 제공되는 기본 디렉토리를 정의하여 중요한 역할을 합니다. 아래 예시를 고려하세요:

server {
root /etc/nginx;

location /hello.txt {
try_files $uri $uri/ =404;
proxy_pass http://127.0.0.1:8080/;
}
}

이 구성에서는 /etc/nginx가 루트 디렉토리로 지정되었습니다. 이 설정은 /hello.txt와 같은 지정된 루트 디렉토리 내의 파일에 대한 액세스를 허용합니다. 그러나 중요한 점은 특정 위치(/hello.txt)만 정의되어 있다는 것입니다. 루트 위치(location / {...})에 대한 구성이 없습니다. 이 생략은 루트 지시문이 전역적으로 적용되어 / 경로의 요청이 /etc/nginx 아래의 파일에 액세스할 수 있게 됨을 의미합니다.

이 구성에서 중요한 보안 고려 사항이 발생합니다. /nginx.conf와 같은 간단한 GET 요청은 /etc/nginx/nginx.conf에 위치한 Nginx 구성 파일을 제공함으로써 민감한 정보를 노출시킬 수 있습니다. 루트를 /etc와 같이 덜 민감한 디렉토리로 설정하면 이러한 위험을 완화할 수 있지만, 여전히 다른 중요한 파일(다른 구성 파일, 액세스 로그 및 HTTP 기본 인증에 사용되는 암호화된 자격 증명 포함)에 대한 의도하지 않은 액세스를 허용할 수 있습니다.

Alias LFI Misconfiguration

Nginx의 구성 파일에서 "location" 지시문에 대해 주의 깊게 검사해야 합니다. Local File Inclusion (LFI)이라고 하는 취약점은 다음과 유사한 구성을 통해 우발적으로 도입될 수 있습니다:

location /imgs {
alias /path/images/;
}

이 구성은 서버가 /imgs../flag.txt와 같은 요청을 해석하여 의도한 디렉토리 외부의 파일에 접근하려는 시도로 간주하고 /path/images/../flag.txt로 해석하기 때문에 LFI 공격에 취약합니다. 이 결함으로 인해 공격자는 웹을 통해 액세스해서는 안 되는 서버 파일을 검색할 수 있습니다.

이 취약점을 완화하기 위해 구성을 조정해야 합니다:

location /imgs/ {
alias /path/images/;
}

더 많은 정보: https://www.acunetix.com/vulnerabilities/web/path-traversal-via-misconfigured-nginx-alias/

Accunetix 테스트:

alias../ => HTTP status code 403
alias.../ => HTTP status code 404
alias../../ => HTTP status code 403
alias../../../../../../../../../../../ => HTTP status code 400
alias../ => HTTP status code 403

안전하지 않은 경로 제한

다음 페이지를 확인하여 다음과 같은 지시문을 우회하는 방법을 알아보세요:

location = /admin {
deny all;
}

location = /admin/ {
deny all;
}

안전하지 않은 변수 사용

Nginx 구성에서의 취약점은 아래의 예시로 설명됩니다:

location / {
return 302 https://example.com$uri;
}

HTTP 요청에서 \r (캐리지 리턴) 및 \n (라인 피드) 문자는 새 줄 문자를 나타내며, URL 인코딩 된 형식은 %0d%0a로 표시됩니다. 이러한 문자를 요청에 포함시키면 (예: http://localhost/%0d%0aDetectify:%20clrf) 잘못 구성된 서버에서는 Detectify라는 새 헤더를 발행합니다. 이는 $uri 변수가 URL 인코딩 된 새 줄 문자를 디코딩하기 때문에 응답에서 예기치 않은 헤더가 발생합니다.

HTTP/1.1 302 Moved Temporarily
Server: nginx/1.19.3
Content-Type: text/html
Content-Length: 145
Connection: keep-alive
Location: https://example.com/
Detectify: clrf

CRLF 주입 및 응답 분할의 위험에 대해 자세히 알아보려면 https://blog.detectify.com/2019/06/14/http-response-splitting-exploitations-and-mitigations/를 참조하십시오.

임의 변수

특정 상황에서 사용자 제공 데이터Nginx 변수로 처리될 수 있다는 것이 발견되었습니다. 이 동작의 원인은 여전히 약간 모호하지만, 드물지 않고 확인하기도 어렵지 않습니다. 이 이상한 동작은 HackerOne의 보안 보고서에서 강조되었으며, 여기에서 확인할 수 있습니다. 오류 메시지에 대한 추가 조사를 통해, 이 문제가 Nginx의 코드베이스의 SSI 필터 모듈 내에서 발생한다는 것을 확인하였으며, 이는 Server Side Includes (SSI)가 근본 원인임을 밝혀냈습니다.

이 구성 오류를 감지하기 위해 다음 명령을 실행할 수 있습니다. 이 명령은 변수 출력을 테스트하기 위해 referer 헤더를 설정하는 것을 포함합니다:

$ curl -H Referer: bar http://localhost/foo$http_referer | grep foobar

시스템 간의 이러한 구성 오류를 검사한 결과, 사용자가 Nginx 변수를 출력할 수 있는 여러 인스턴스가 발견되었습니다. 그러나 취약한 인스턴스의 수가 감소한 것으로 보아, 이 문제를 수정하기 위한 노력이 어느 정도 성공적이었습니다.

원시 백엔드 응답 읽기

Nginx는 proxy_pass를 통해 백엔드에서 생성된 오류와 HTTP 헤더를 가로챌 수 있는 기능을 제공합니다. 이는 Nginx가 내부 오류 메시지와 헤더를 숨기기 위해 사용됩니다. 이를 위해 Nginx는 백엔드 오류에 대한 사용자 정의 오류 페이지를 제공합니다. 그러나 Nginx가 잘못된 HTTP 요청을 만나는 경우에는 문제가 발생합니다. 이러한 요청은 받은 그대로 백엔드로 전달되며, 백엔드의 원시 응답은 Nginx의 개입 없이 클라이언트로 직접 전송됩니다.

uWSGI 애플리케이션을 사용한 예시 시나리오를 고려해보겠습니다:

def application(environ, start_response):
start_response('500 Error', [('Content-Type', 'text/html'), ('Secret-Header', 'secret-info')])
return [b"Secret info, should not be visible!"]

이를 관리하기 위해 Nginx 구성에서 특정 지시문을 사용합니다:

http {
error_page 500 /html/error.html;
proxy_intercept_errors on;
proxy_hide_header Secret-Header;
}
  • proxy_intercept_errors: 이 지시문은 Nginx가 상태 코드가 300보다 큰 백엔드 응답에 대해 사용자 정의 응답을 제공하도록 설정합니다. 이 예제에서는 uWSGI 애플리케이션의 500 에러 응답이 Nginx에 의해 가로채지고 처리되도록 보장합니다.
  • proxy_hide_header: 이름에서 알 수 있듯이, 이 지시문은 지정된 HTTP 헤더를 클라이언트로부터 숨깁니다. 이는 개인 정보 보호와 보안을 강화합니다.

유효한 GET 요청이 수행되면 Nginx는 정상적으로 처리하여 비밀 헤더를 공개하지 않는 표준 오류 응답을 반환합니다. 그러나 잘못된 HTTP 요청은 이 메커니즘을 우회하여 비밀 헤더와 오류 메시지를 포함한 원시 백엔드 응답이 노출됩니다.

merge_slashes를 off로 설정

기본적으로 Nginx의 merge_slashes 지시문은 **on**으로 설정되어 URL에서 여러 슬래시를 단일 슬래시로 압축합니다. 이 기능은 URL 처리를 간소화하지만 특히 Nginx 뒤에 있는 취약한 애플리케이션(로컬 파일 포함(LFI) 공격에 취약한 애플리케이션)에서 취약성을 감추는 경우가 있습니다. 보안 전문가 Danny Robinson과 Rotem Bar는 특히 Nginx가 리버스 프록시로 작동할 때 이러한 기본 동작과 관련된 잠재적인 위험성을 강조했습니다.

이러한 위험을 완화하기 위해 취약성이 있는 애플리케이션에 대해 merge_slashes 지시문을 끄는 것이 권장됩니다. 이렇게 하면 Nginx가 URL 구조를 변경하지 않고 애플리케이션에 요청을 전달하므로 기존의 보안 문제를 가리지 않습니다.

자세한 정보는 Danny Robinson과 Rotem Bar를 확인하세요.

Map 지시문의 기본값

Nginx 구성에서 map 지시문은 종종 인가 제어에 역할을 합니다. 일반적인 실수는 기본값을 지정하지 않는 것으로, 이는 무단 액세스로 이어질 수 있습니다. 예를 들어:

http {
map $uri $mappocallow {
/map-poc/private 0;
/map-poc/secret 0;
/map-poc/public 1;
}
}
server {
location /map-poc {
if ($mappocallow = 0) {return 403;}
return 200 "Hello. It is private area: $mappocallow";
}
}

default가 없으면, 악의적인 사용자/map-poc 내의 정의되지 않은 URI에 접근하여 보안을 우회할 수 있습니다. Nginx 매뉴얼은 이러한 문제를 피하기 위해 기본값을 설정하는 것을 권장합니다.

DNS 스푸핑 취약점

일부 조건에서 Nginx에 대한 DNS 스푸핑이 가능합니다. 공격자가 Nginx가 사용하는 DNS 서버를 알고 있고 DNS 쿼리를 가로챌 수 있다면, DNS 레코드를 스푸핑할 수 있습니다. 그러나 Nginx가 DNS 해결을 위해 **localhost (127.0.0.1)**를 사용하도록 구성된 경우에는 이 방법이 효과가 없습니다. Nginx는 다음과 같이 DNS 서버를 지정할 수 있습니다:

resolver 8.8.8.8;

proxy_passinternal 지시문

proxy_pass 지시문은 요청을 다른 서버로 내부적으로 또는 외부적으로 리디렉션하는 데 사용됩니다. internal 지시문은 특정 위치에 대한 액세스를 Nginx 내에서만 허용합니다. 이러한 지시문은 그 자체로는 취약점이 아니지만, 보안 결함을 방지하기 위해 구성을 주의 깊게 검토해야 합니다.

proxy_set_header Upgrade & Connection

nginx 서버가 Upgrade 및 Connection 헤더를 전달하도록 구성된 경우 h2c 스머글링 공격을 통해 보호된/내부 엔드포인트에 액세스할 수 있습니다.

{% hint style="danger" %} 이 취약점을 통해 공격자는 proxy_pass 엔드포인트(http://backend:9999인 경우)와 직접 연결을 설정할 수 있으며, 해당 내용은 nginx에서 확인되지 않습니다. {% endhint %}

여기에서 /flag를 도용하는 취약한 구성의 예시:

server {
listen       443 ssl;
server_name  localhost;

ssl_certificate       /usr/local/nginx/conf/cert.pem;
ssl_certificate_key   /usr/local/nginx/conf/privkey.pem;

location / {
proxy_pass http://backend:9999;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $http_connection;
}

location /flag {
deny all;
}

{% hint style="warning" %} proxy_passhttp://backend:9999/socket.io와 같은 경로를 가리키고 있더라도 연결은 http://backend:9999로 수립됩니다. 따라서 내부 엔드포인트 내의 다른 경로에 연락할 수 있으므로, proxy_pass의 URL에 경로가 지정되어 있는지 여부는 중요하지 않습니다. {% endhint %}

직접 해보기

Detectify는 이 기사에서 다루는 몇 가지 잘못된 구성을 가진 취약한 Nginx 테스트 서버를 Docker를 사용하여 설정할 수 있는 GitHub 저장소를 만들었습니다. 이 저장소를 사용하여 스스로 이러한 구성을 찾아보세요!

https://github.com/detectify/vulnerable-nginx

정적 분석 도구

GIXY

Gixy는 Nginx 구성을 분석하는 도구입니다. Gixy의 주요 목표는 보안 구성 오류를 방지하고 결함을 자동으로 감지하는 것입니다.

Nginxpwner

Nginxpwner는 일반적인 Nginx 구성 오류와 취약점을 찾기 위한 간단한 도구입니다.

참고 자료

취약성 평가 및 펜테스트를 위한 즉시 사용 가능한 설정. 20개 이상의 도구 및 기능을 갖춘 완전한 펜테스트를 어디에서나 실행하세요. 우리는 펜테스터를 대체하지 않습니다. 대신, 펜테스터들에게 더 깊이 파고들고, 쉘을 열고, 재미를 느낄 수 있도록 사용자 정의 도구, 탐지 및 공격 모듈을 개발합니다.

{% embed url="https://pentest-tools.com/" %}

htARTE (HackTricks AWS Red Team Expert)를 통해 AWS 해킹을 처음부터 전문가까지 배워보세요!

HackTricks를 지원하는 다른 방법: