개요
최근 필자는 서버를 운영하는 과정에서 Brute-force Scanner에 의해 서버가 감지된 사례를 경험하였다. 이에 따라 Nginx 보안 설정을 강화하여 대응하였다. 본 포스트에서는 해당 사례를 소개하고, 이후 구글 봇이 로그에 잡힌 정황을 설명하며 적절한 대응이 이루어지지 않았을 경우 IP가 검색엔진에 노출될 위험성을 분석한다.
Brute-force Scanner 감지 사례
... "POST /bin/.%2e/.%2e/.%2e/.%2e/.%2e/.%2e/.%2e/.%2e/.%2e/.%2e/bin/sh HTTP/1.1" ... ... "POST /cgi-bin/%%32%65%%32%65/%%32%65%%32%65/%%32%65%%32%65/%%32%65%%32%65/%%32%65%%32%65/bin/sh HTTP/1.1" ... ... "POST /hello.world?%ADd+url_include%3d1+%ADd+auto_prepend_file%3dphp://input HTTP/1.1" ... ... "GET /vendor/php/php/src/Utll/PhP/el-stdin.php HTTP/1.1" ... ... "GET /vendor/php/php/Utll/PhP/el-stdin.php HTTP/1.1" ... ... "GET /vendor/php/src/Utll/PhP/el-stdin.php HTTP/1.1" ... ... "GET /vendor/php/Utll/PhP/el-stdin.php HTTP/1.1" ... ... "GET /vendor/php/php/LICENSE/el-stdin.php HTTP/1.1" ... ... "GET /vendor/vendor/php/php/src/Utll/PhP/el-stdin.php HTTP/1.1" ... ... "GET /php/php/src/Utll/PhP/el-stdin.php HTTP/1.1" ... ... "GET /php/php/Utll/PhP/el-stdin.php HTTP/1.1" ... ... "GET /php/src/Utll/PhP/el-stdin.php HTTP/1.1" ... ... "GET /php/Utll/PhP/el-stdin.php HTTP/1.1" ... ... "GET /lib/php/php/src/Utll/PhP/el-stdin.php HTTP/1.1" ... ... "GET /lib/php/php/Utll/PhP/el-stdin.php HTTP/1.1" ... ... "GET /lib/php/src/Utll/PhP/el-stdin.php HTTP/1.1" ... ... "GET /lib/php/Utll/PhP/el-stdin.php HTTP/1.1" ... ... "GET /lib/vendor/php/php/src/Utll/PhP/el-stdin.php HTTP/1.1" ... ... "GET /laravel/vendor/php/php/src/Utll/PhP/el-stdin.php HTTP/1.1" ... ... "GET /www/vendor/php/php/src/Utll/PhP/el-stdin.php HTTP/1.1" ... ... "GET /ws/vendor/php/php/src/Utll/PhP/el-stdin.php HTTP/1.1" ... ... "GET /yii/vendor/php/php/src/Utll/PhP/el-stdin.php HTTP/1.1" ... ... "GET /zend/vendor/php/php/src/Utll/PhP/el-stdin.php HTTP/1.1" ... ... "GET /ws/ec/vendor/php/php/src/Utll/PhP/el-stdin.php HTTP/1.1" ... ... "GET /V2/vendor/php/php/src/Utll/PhP/el-stdin.php HTTP/1.1" ... ... "GET /tests/vendor/php/php/src/Utll/PhP/el-stdin.php HTTP/1.1" ... ... "GET /test/vendor/php/php/src/Utll/PhP/el-stdin.php HTTP/1.1" ... ... "GET /testing/vendor/php/php/src/Utll/PhP/el-stdin.php HTTP/1.1" ... ... "GET /api/vendor/php/php/src/Utll/PhP/el-stdin.php HTTP/1.1" ... ... "GET /demo/vendor/php/php/src/Utll/PhP/el-stdin.php HTTP/1.1" ... ... "GET /cms/vendor/php/php/src/Utll/PhP/el-stdin.php HTTP/1.1" ... ... "GET /crm/vendor/php/php/src/Utll/PhP/el-stdin.php HTTP/1.1" ... ... "GET /admin/vendor/php/php/src/Utll/PhP/el-stdin.php HTTP/1.1" ... ... "GET /backup/vendor/php/php/src/Utll/PhP/el-stdin.php HTTP/1.1" ... ... "GET /blog/vendor/php/php/src/Utll/PhP/el-stdin.php HTTP/1.1" ... ... "GET /workspace/drupal/vendor/php/php/src/Utll/PhP/el-stdin.php HTTP/1.1" ... ... "GET /panel/vendor/php/php/src/Utll/PhP/el-stdin.php HTTP/1.1" ... ... "GET /public/vendor/php/php/src/Utll/PhP/el-stdin.php HTTP/1.1" ... ... "GET /apps/vendor/php/php/src/Utll/PhP/el-stdin.php HTTP/1.1" ... ... "GET /app/vendor/php/php/src/Utll/PhP/el-stdin.php HTTP/1.1" ... ... "GET /index.php?s=/index/\x5Cthink\x5Capp/invokefunction&function=call_user_func_array&vars[0]=md5 HTTP/1.1" ...
해당 요청은 실제와 다를 수 있으며, 대중적으로 알려진 공격임.
초기 서버 운영 중 특정 보안 스캐너(Brute-force Scanner)에 의해 서버가 감지되었다. 구체적인 정황은 다음과 같다.
- 로그 분석 결과 특정 IP에서 지속적으로 443 포트에 Port brute-force 공격을 시도한 흔적 발견.
- 경로 탐색 시도 Path traversal 공격을 시도한 흔적 발견.
특히 Brute-force Scanner가 필자의 서버를 감지한 방식은 IP 주소를 직접 수집한 것이 아니라, 서버의 존재 여부를 추측하는 방식이었던 것으로 보인다. 이에 따라 보안 강화를 위해 Nginx 설정을 변경하였다.
Nginx 보안 강화 설정
이후 보안을 강화하기 위해 Nginx 설정을 다음과 같이 구성하였다.
server { listen 80 default_server; listen [::]:80 default_server; server_name _; server_tokens off; return 444; } server { listen 443 ssl default_server; listen [::]:443 ssl default_server; server_name _; # 자체 서명된 인증서 사용 ssl_certificate /etc/nginx/conf.d/giant_flag.crt; ssl_certificate_key /etc/nginx/conf.d/giant_flag.key; server_tokens off; return 444; }
위 설정의 핵심적인 보안 요소는 다음과 같다:
server_tokens off
: Nginx의 버전을 감출 수 있도록 설정
return 444
: 잘못된 요청에 대해 응답을 하지 않고 연결을 즉시 종료하여 불필요한 트래픽을 차단
- 기본적으로 HTTP(80) 및 HTTPS(443)에 대한 모든 요청을 차단하도록 설정
이러한 설정을 통해 IP 주소를 직접 노출하지 않고, 스캐닝 도구에 의해 서버가 감지되지 않도록 하였다.
위 코드는 임의로 편집 됐으며, 실제 작동을 보장하지 않음
구글 봇 (Googlebot) 로그 탐지
추가적으로, 서버 로그를 분석하는 과정에서 구글 봇(Googlebot)의 크롤링 요청이 잡힌 정황이 발견되었다. 이는 곧 서버가 구글의 검색 색인에 포함될 가능성이 있음을 의미한다.
구글 봇이 접근한 흔적은 다음과 같다:
cool.ip.so.nice - - [32/Oct/1024 +0000] "GET /a.b.c HTTP/1.1" "-" "SAMSUNG-SGH-E250/1.0 Profile/MIDP-2.0 Configuration/CLDC-1.1 UP.Browser/ (GUI) MMP/2.0 (compatible; Googlebot-Mobile/2.1; http://www.google.com/bot.html)" "cool.ip.so.nice" cool.ip.so.nice - - [32/Oct/1024 +0000] "GET / HTTP/1.1" "-" "-" "-"
구글 봇이 이러한 접근을 시도한 것은 다음과 같은 가능성을 시사한다:
- 서버의 IP가 우회적으로 노출되었거나, 외부에 노출된 도메인을 통해 접근되었을 가능성
- 크롤러가 우연히 IP를 색인하려는 시도를 한 경우
- DNS 캐시나 트래픽 히스토리를 활용하여 검색한 경우
이와 같은 상황을 방치할 경우, 검색 엔진에 IP 주소가 노출될 가능성이 있으며, 이를 통해 불특정 다수의 접근이 발생할 수 있다.
대응 방안
이러한 보안 문제를 방지하기 위해 다음과 같은 조치를 추가적으로 취할 필요가 있다.
- 구글 봇 및 크롤러 차단
robots.txt
를 활용하여 구글 및 기타 크롤러가 색인하지 못하도록 설정.htaccess
또는nginx.conf
에서 User-Agent 기반 차단 적용
- IP 기반 접근 제어 강화
- 방화벽 설정을 통해 신뢰할 수 있는 IP에서만 접근 가능하도록 제한
- Fail2Ban 등의 도구를 활용하여 악의적인 IP를 차단
- Nginx 보안 강화
- 특정 포트에 대한 접근을 더욱 엄격하게 제한
return 444
외에도deny all
설정을 추가하여 원천 차단- TCP Wrappers를 활용하여 허용된 IP 외에는 접근하지 못하도록 설정
- 검색 엔진 색인 방지
- 구글 웹마스터를 이용하여 IP 주소가 색인되지 않도록 조치
- DNS 설정을 확인하여 불필요한 A 레코드 또는 서브도메인이 없는지 점검
결론
이번 사례를 통해 단순한 보안 설정만으로는 포트 공격 및 경로 탐색 공격을 완벽하게 차단하기 어렵다는 점을 확인할 수 있었다. 특히 검색 엔진에 IP가 노출될 가능성을 간과하면 의도치 않게 서버의 존재가 공개될 위험이 있다.
이를 방지하기 위해서는 기본적인 Nginx 보안 설정을 넘어, 추가적인 접근 제어 및 크롤러 차단을 적극적으로 수행하는 것이 필요하다. 또한 정기적인 로그 분석과 방화벽 정책 강화를 통해 악의적인 접근을 사전에 차단하는 것이 중요하다.
알아두기
이 포스팅에 공개되는 모든 공격은 대중적으로 알려진 방식이며, 유효하지 않았음을 밝힘.
공격과 별개로 추가적인 안전 조치가 취해진 후 본 포스팅을 작성함.