Language/PHP
PHP, Windows, IIS) PHP 7,8 취약점 위험성과 대응 방안
소소한 늙은 개발자의 메모장
2026. 10. 22. 12:55
반응형
PHP, Windows, IIS) PHP 7,8 취약점 위험성과 대응 방안
최근(2026-10-22 기준) 이슈가 되는 PHP 신규 보안 취약점(CVE-2026-109618, CVE-2026-109619)과 관련하여, 8.5 버전은 패치가 제공 되나, 지원이 종료(EOL, End-of-Life)된 PHP 7 버전 등은 문제가 있으며, 특히 Windows기반의 IIS를 활용하고 있어 일단 해결책이 필요하여 Gemini의 지원을 받아 해결하여 해당 정보를 공휴하고자 한다.
보안 취약점
- PHP 보안 취약 점 : CVE-2026-109618, CVE-2026-109619
- allow_url_include,- allow_url_fopen, expose_php 설정(PHP: Description of core php.ini directives - Manual)의 취약점
- 취약점 이용 방법이 공개됨에 따라 보안 취약은 알고 있었어도, 방법을 몰랐던 악성 사용자(해커)들도 알게 됨에 따라 취약점 방어는 필수
대응 방법 (Windows 환경에서 )
- Apache + PHP-CGI(또는 XAMPP 기본 설정) : 모듈 방식(mod_php)이나 FastCGI(php-fpm) 전용 안전 설정으로 전환
- IIS + PHP : 처리기 매핑에서 모듈 방식 FastCgiModule으로 변경
Windows/IIS 환경 기준
- web.config 기반 긴급 차단 룰 적용
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<system.webServer>
<rewrite>
<rules>
<rule name="Block PHP-CGI Argument Injection (CVE-2024-4577)" stopProcessing="true">
<match url=".*\.php$" ignoreCase="true" />
<conditions logicalGrouping="MatchAny">
<!-- 소프트 하이픈 인코딩 및 하이픈 옵션 주입 패턴 차단 -->
<add input="{UNENCODED_URL}" pattern=".*(%ad|%AD|-d|-s|-w).*" />
<add input="{QUERY_STRING}" pattern=".*(%ad|%AD|-d|-s|-w).*" />
</conditions>
<action type="CustomResponse" statusCode="403" subStatusCode="0" statusReason="Forbidden" statusDescription="Blocked by Security Policy" />
</rule>
</rules>
</rewrite>
</system.webServer>
</configuration>
- PowerShell 자동화 스크립트
# ==============================================================================
# PHP CGI Argument Injection Mitigation for IIS on Windows Server 2022
# ==============================================================================
# 1. 관리자 권한 확인 및 IIS 모듈 로드
Import-Module WebAdministration
$SiteName = "Default Web Site" # 적용할 IIS 사이트명으로 변경
$RuleName = "Block-PHP-CGI-Arg-Injection"
Write-Host "[+] IIS URL Rewrite 모듈 설치 여부 확인 중..." -ForegroundColor Cyan
$rewriteModule = Get-WebConfiguration -pspath "MACHINE/WEBROOT/APPHOST" -filter "system.webServer/globalModules/add[@name='RewriteModule']"
if (-not $rewriteModule) {
Write-Warning "[!] IIS URL Rewrite 모듈이 설치되어 있지 않습니다."
Write-Warning " https://www.iis.net/downloads/microsoft/url-rewrite 에서 다운로드 후 설치하십시오."
return
}
Write-Host "[+] '$SiteName'에 CVE-2024-4577 완화 규칙 적용 중..." -ForegroundColor Cyan
# 중복 룰 방지를 위해 기존 동일 이름 규칙 삭제
Clear-WebConfiguration -pspath "IIS:\Sites\$SiteName" -filter "system.webServer/rewrite/rules/rule[@name='$RuleName']" -ErrorAction SilentlyContinue
# 새 규칙 추가
Add-WebConfigurationProperty -pspath "IIS:\Sites\$SiteName" -filter "system.webServer/rewrite/rules" -name "." -value @{
name = $RuleName
stopProcessing = "True"
}
# Match URL 설정 (*.php)
Set-WebConfigurationProperty -pspath "IIS:\Sites\$SiteName" -filter "system.webServer/rewrite/rules/rule[@name='$RuleName']/match" -name "url" -value ".*\.php$"
# Action 설정 (403 Custom Response)
Set-WebConfigurationProperty -pspath "IIS:\Sites\$SiteName" -filter "system.webServer/rewrite/rules/rule[@name='$RuleName']/action" -name "type" -value "CustomResponse"
Set-WebConfigurationProperty -pspath "IIS:\Sites\$SiteName" -filter "system.webServer/rewrite/rules/rule[@name='$RuleName']/action" -name "statusCode" -value 403
Set-WebConfigurationProperty -pspath "IIS:\Sites\$SiteName" -filter "system.webServer/rewrite/rules/rule[@name='$RuleName']/action" -name "statusReason" -value "Forbidden"
# Conditions 설정 (%ad, -d 등 주입 탐지)
Add-WebConfigurationProperty -pspath "IIS:\Sites\$SiteName" -filter "system.webServer/rewrite/rules/rule[@name='$RuleName']/conditions" -name "." -value @{
input = "{QUERY_STRING}"
pattern = ".*(%ad|%AD|-d|-s).*"
}
Write-Host "[+] URL Rewrite 보안 차단 규칙이 성공적으로 배포되었습니다." -ForegroundColor Green
- php.ini FastCGI 매핑 추가 점검 사항 (소스 확인 후 적용 / 차단 룰로 우선 적용)
allow_url_include = Off
allow_url_fopen = Off
expose_php = Off
점검절차 (curl 이용)
- 정상 요청 확인 (기대값: HTTP 200 OK)
curl -I -s -o /dev/null -w "%{http_code}\n" "http://localhost/index.php?test=normal"
- CVE-2024-4577 악용 패턴 테스트 (기대값: HTTP 403 Forbidden)
# 1) 소문자 소프트 하이픈(%ad) 주입 테스트
curl -i "http://localhost/index.php?%add+allow_url_include%3don"
# 2) 대문자 소프트 하이픈(%AD) 주입 테스트
curl -i "http://localhost/index.php?%ADd+allow_url_include%3don"
# 3) 직접 인자 플래그(-d) 주입 테스트
curl -i "http://localhost/index.php?-d+allow_url_include=1"
진단 스크립트 (PowerShell)
- 접속 확인
$testUrl = "http://localhost/index.php?test=1"
try {
$res = Invoke-WebRequest -Uri $testUrl -Method Head -UseBasicParsing -TimeoutSec 5
Write-Host "연결 성공: HTTP $($res.StatusCode)" -ForegroundColor Green
} catch {
Write-Host "연결 실패 세부 에러:" -ForegroundColor Red
Write-Host $_.Exception.ToString()
}
- 보안 적용 확인
# 실제 환경에 맞게 주소 변경 (포트나 HTTPS 여부 확인)
$baseUrl = "http://localhost/index.php"
$tests = @(
@{ Name = "정상 요청"; Query = "?page=1" },
@{ Name = "소프트 하이픈(%ad)"; Query = "?%add+allow_url_include=1" },
@{ Name = "대문자 하이픈(%AD)"; Query = "?%ADd+auto_prepend_file=php://input" },
@{ Name = "직접 인자 주입(-d)"; Query = "?-d+expose_php=0" }
)
foreach ($test in $tests) {
$targetUrl = $baseUrl + $test.Query
try {
$response = Invoke-WebRequest -Uri $targetUrl -Method Head -UseBasicParsing -TimeoutSec 5
Write-Host "[$($response.StatusCode)] $($test.Name) - 통과 (200 OK)" -ForegroundColor Yellow
} catch {
if ($_.Exception.Response) {
$statusCode = [int]$_.Exception.Response.StatusCode
if ($statusCode -eq 403) {
Write-Host "[$statusCode] $($test.Name) - 정상 차단됨 (보안 룰 작동)" -ForegroundColor Green
} else {
Write-Host "[$statusCode] $($test.Name) - HTTP 오류 발생" -ForegroundColor DarkYellow
}
} else {
Write-Host "[연결 실패] $($test.Name) - 서버에 도달하지 못함: $($_.Exception.Message)" -ForegroundColor Red
}
}
}
PowerShell 보안 오류 발생시
- 1회성 Bypass 실행 (가장 권장)
powershell -ExecutionPolicy Bypass -File .\[파일명]
- 현재 열려 있는 Powershell창에서만
Set-ExecutionPolicy -Scope Process -ExecutionPolicy RemoteSigned -Force
.\[파일명]
- 시스템 전역 허용 (관리자 권한)
Set-ExecutionPolicy -Scope LocalMachine -ExecutionPolicy RemoteSigned -Force
.\[파일명]
※ 본 글은 직접 작성하였으며, 점검 절차 및 PowerShell 소스는 제미나이(Gemini) 3.8 Flash의 도움을 받았습니다.
반응형