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의 도움을 받았습니다.

 

반응형