운영 중인 서비스 픽플에 어느 날부터 지속적인 비정상 요청이 발생하기 시작했다. 로그를 확인해보니 아래와 같은 에러가 반복적으로 찍히고 있었다
java.lang.IllegalArgumentException: Invalid character found in the request target [/index.php?s=/index/think\app/invokefunction&function=call_user_func_array&vars[0]=md5&vars[1][]=Hello].
valid characters are defined in RFC 7230 and RFC 3986
반복적으로
call_user_func_array
,md5
,vars[]
등이 포함된 요청이 수천 건씩 찍히는 상황.
이는 외부에서 PHP 기반 RCE(Remote Code Execution) 공격 시도였고, 특히 ThinkPHP 프레임워크의 취약점을 타겟으로 한 패턴이었다.
해당 서비스는 Java/Spring 기반이라 직접적인 영향은 없었지만, 지속적인 요청으로 인해 로그가 과도하게 쌓이고, 서버 리소스가 낭비되는 현상이 발생하고 있었다.
공격 요청의 공통점은 국내에서 발생하지 않은 트래픽이라는 점이었다. 이에 따라 다음과 같은 결정했다.
"KR 외의 IP로부터의 접근은 모두 차단하자."
운영 중인 웹 서버는 Nginx
였고, 우리는 GeoIP 설정을 통해 국가 기반의 차단 정책을 도입했다.
apt install geoip-database
http {
geoip_country /usr/share/GeoIP/GeoIP.dat;
map $geoip_country_code $allowed_country {
default no;
KR yes;
}
server {
if ($allowed_country = no) {
return 444;
}
...
}
}
return 444
는 nginx 특유의 응답 코드로, 응답 없이 연결을 끊어 서버 리소스를 아끼는 방식이다.
nginx -s reload
적용 이후, 비정상 요청은 급격히 줄어들었고 서버 리소스 사용률과 로그 저장량도 안정화되었다.
/wp-login.php
, /index.php
등의 요청도 계속 유입되고 있어, 장기적으로는 WAF 또는 클라우드 기반 방어 체계도 검토 중이다.운영 시스템은 언제든 예상하지 못한 위협에 노출될 수 있다. 비록 실제 피해는 없었지만, 이번 RCE 시도 대응을 통해 로그 모니터링의 중요성과 방화벽의 유연한 구성의 가치를 다시 한번 깨달았다.
기술적 보완도 중요하지만, "이상징후를 빠르게 감지할 수 있는 시스템"이 결국 가장 강력한 방어다.