1. 2026년 10월 PHP 사례가 드러낸 구조적 문제
2026년 10월, PHP 핵심 엔진에서 인증 없이 원격 코드 실행이 가능한 두 건의 취약점이 공시되었습니다. 이 사례는 취약점 관리 체계를 점검하기에 적합한 교재입니다. 단일 취약점의 기술적 세부사항보다, 조직이 대응 과정에서 무엇을 증명해야 하는가를 선명하게 보여주기 때문입니다.
| 항목 | 내용 |
|---|---|
| 취약점 식별자 | CVE-2026-109618, CVE-2026-109619 (통칭 PHP2Shell) |
| 심각도 | CVSS v4.0 기준 9.2 — 두 건 모두 인증되지 않은 공격자의 원격 코드 실행 가능 |
| 원인 | 치명적 오류 처리 과정에서 요청 메모리가 초기화되지 않은 상태로 남거나, 전역 메모리가 이미 해제된 영역을 가리키게 되어 이후 요청에서 참조되는 문제 |
| 패치 버전 | PHP 8.5.12, 8.4.27, 8.3.36, 8.2.35 (2026년 10월 21일 긴급 배포) |
| 지원 종료 버전 | PHP 8.1 이하는 지원이 종료된 상태로, 패치가 제공되지 않습니다 |
| 노출 규모 | 외부 조사 기준 2,260만 개 이상의 인터넷 노출 인스턴스가 영향 가능 범위로 집계 |
| 완화 설정의 한계 | 설정 변경만으로는 완전히 보호되지 않으며, 패치 적용만이 근본 해결책으로 안내되었습니다 |
공시 이후의 경과는 다음과 같습니다.
- 2026-10-21 PHP 그룹이 두 건의 취약점에 대한 긴급 패치를 배포했습니다. 미국 사이버보안 당국은 같은 날 즉시 패치를 권고하고, 즉시 패치가 불가한 경우 시스템을 오프라인으로 전환하거나 웹 애플리케이션 방화벽을 임시 보호 수단으로 배치하도록 안내했습니다.
-
2026-10-23
패치 배포 이틀 뒤, 특수한 세션 구성에서 코드 실행이 가능한 별건의 취약점(
CVE-2026-115560)이 추가로 공지되었습니다. 긴급 패치는 제공되지 않았고, 정기 배포 전까지session.upload_progress.enabled=0설정이 권고되었습니다. - 2026-10-25 일부 보안 업체가 초기에 보고한 침해 사례와 해당 취약점의 연관성에 대해 “특정 PHP2Shell 취약점과 초기 침투의 연관성을 확인할 수 없다”며 주장을 철회했습니다. 공시 초기의 위협 정보는 며칠 사이에도 변경됩니다.
이 경과에서 세 가지 사실이 도출됩니다.
- 일회성 대응으로 끝나지 않습니다. 패치 적용 이틀 만에 후속 취약점이 공지되었습니다. 대응은 사건이 아니라 상시 운영 절차여야 합니다.
- 패치가 불가능한 자산이 반드시 존재합니다. 지원 종료 버전에는 패치 자체가 없습니다. 이 구간을 어떻게 통제했는지 설명할 수 있어야 합니다.
- 초기 정보는 유동적입니다. 최초 판단을 고정하지 않고 재평가하는 절차가 필요합니다.
2. ISMS-P가 요구하는 것은 아키텍처가 아니라 프로세스
긴급 취약점 사례가 발생하면 “서버리스로 전환하면 이런 문제가 없는가”와 같은 논의가 나옵니다. 그러나 심사 관점에서 이는 답이 되지 않습니다. 런타임을 교체하는 작업은 수 개월이 소요되는 반면, 긴급 취약점의 조치 기한은 수 일 단위입니다. 시간 척도가 맞지 않습니다.
ISMS-P의 취약점 관리와 보안 사고 예방 항목이 요구하는 것은 아키텍처의 종류가 아니라 다음 네 가지의 기록입니다.
- 인지 — 취약점 정보를 언제, 어떤 경로로 인지했는가
- 산정 — 자산 목록을 근거로 영향 범위를 어떻게 식별했는가
- 조치 — 정해진 기한 내에 무엇을 적용했는가, 적용하지 못한 자산은 어떻게 통제했는가
- 검증 — 조치가 완료되었음을 무엇으로 확인했는가
이 네 가지는 모두 기록입니다. 그리고 기록을 사람이 수작업으로 남기면 긴급 상황에서 가장 먼저 누락됩니다. 실제 심사에서 지적을 받는 지점도 조치 미이행보다 조치 기록 부재인 경우가 많습니다. 여기가 Lambda의 역할입니다. Lambda는 취약한 런타임을 대체하는 수단이 아니라, 인지부터 검증까지의 흐름을 기록과 함께 수행하는 오케스트레이터입니다.
3. 당국 권고 절차와 ISMS-P 요구사항의 매핑
2026년 10월 권고에서 제시된 조치 순서는 ISMS-P가 요구하는 취약점 관리 절차와 사실상 동일합니다. 권고를 그대로 자동화 단계로 전환할 수 있습니다.
| 당국 권고 조치 | 대응 요구사항 | 자동화 구현 |
|---|---|---|
| 조직 전체에서 해당 소프트웨어를 사용하는 시스템을 식별하고 목록화 | 자산 관리, 취약점 점검 범위 산정 | Lambda가 SSM Inventory·Inspector·ECR 스캔 결과를 조회해 영향 자산 목록 생성 |
| 인터넷 노출 시스템을 우선하여 즉시 패치 | 조치 우선순위, 조치 기한 준수 | 노출 여부를 태그·보안 그룹·대상 그룹으로 판정해 우선순위 부여 |
| 즉시 패치가 불가하면 오프라인 전환 | 위험 완화, 사고 예방 | 승인 후 대상 그룹 분리 또는 보안 그룹 축소를 자동 실행 |
| 웹 애플리케이션 방화벽을 임시 보호 수단으로 배치 | 보상 통제 적용 | WAF 규칙을 자동 배포하여 패치 완료까지 시간 확보 |
| 의심 활동 모니터링 | 침해 시도 탐지 및 대응 | GuardDuty·CloudWatch 경보를 사고 대응 채널로 연계 |
4. 자동화 아키텍처
그림 1. 긴급 취약점 대응 자동화 구성 — 인지부터 증적 적재까지
5. 1단계공시 수집과 트리거
자동화의 시작점은 세 가지 경로를 모두 수용해야 합니다. 긴급 취약점은 스캐너가 탐지하기 전에 공시되는 경우가 많기 때문입니다. 2026년 10월 사례에서도 공시 시점에 모든 스캐너가 즉시 탐지 서명을 보유하지는 않았습니다.
- 탐지 기반 — Inspector 또는 Security Hub의 신규 발견 사항을 EventBridge 규칙으로 수신
- 수동 트리거 — 담당자가 CVE 식별자와 영향 소프트웨어·버전 범위를 입력해 즉시 실행. 긴급 상황에서 실제로 가장 많이 사용되는 경로입니다
- 정기 재평가 — 미조치 항목을 일 1회 재평가. 초기 정보가 변경되거나 후속 취약점이 공지되는 상황에 대응
수동 트리거 입력 형식 — 담당자가 공시 정보를 그대로 기입
{
"advisory_id": "CVE-2026-109618",
"software": "php",
"affected_versions": "<8.2.35 || >=8.3,<8.3.36 || >=8.4,<8.4.27 || >=8.5,<8.5.12",
"fixed_versions": ["8.2.35", "8.3.36", "8.4.27", "8.5.12"],
"severity": "critical",
"sla_hours": 72,
"internet_facing_sla_hours": 24,
"compensating_control": "waf",
"source_url": "https://www.php.net/..."
}
sla_hours)을 입력 항목으로 둔 이유는,
심사에서 확인하는 것이 “조치했는가”가 아니라 “정해진 기한 내에 조치했는가”이기 때문입니다.
기한은 내부 정책으로 사전에 정의하고, 자동화는 그 기한을 기준으로 경과 여부를 판정해야 합니다.
인터넷 노출 자산에 더 짧은 기한을 적용하는 것은 당국 권고의 우선순위 지침과도 일치합니다.
6. 2단계영향 자산 산정
“우리 환경에 해당 소프트웨어가 어디에 설치되어 있는가”에 즉시 답하지 못하는 것이 긴급 대응의 첫 번째 병목입니다. SSM Inventory를 사전에 활성화해 두면 이 질문을 질의로 해결할 수 있습니다.
영향 자산 산정 Lambda — 설치 소프트웨어 목록 조회 후 버전 비교
import boto3
ssm = boto3.client("ssm")
def find_affected(software: str, fixed_versions: list[str]) -> list[dict]:
"""SSM Inventory에서 해당 소프트웨어가 설치된 인스턴스를 조회한다."""
affected = []
paginator = ssm.get_paginator("get_inventory")
for page in paginator.paginate(
Filters=[{
"Key": "AWS:Application.Name",
"Values": [software],
"Type": "BeginWith",
}],
ResultAttributes=[{"TypeName": "AWS:Application"}],
):
for entity in page["Entities"]:
for item in entity.get("Data", {}).get("AWS:Application", {}).get("Content", []):
installed = item.get("Version", "")
if is_vulnerable(installed, fixed_versions):
affected.append({
"instance_id": entity["Id"],
"software": item.get("Name"),
"installed_version": installed,
})
return affected
버전 비교 함수는 소프트웨어마다 체계가 다르므로 패키지 버전 비교 규칙을 별도로 구현해야 합니다.
문자열 단순 비교는 8.2.9와 8.2.35를 잘못 판정하므로 사용할 수 없습니다.
산정 결과에는 다음 정보를 함께 부여합니다. 이 분류가 조치 우선순위와 기한을 결정합니다.
| 분류 | 판정 근거 | 처리 |
|---|---|---|
| 인터넷 노출 자산 | 퍼블릭 IP 보유, ALB 대상 그룹 등록, 보안 그룹에 광범위 인바운드 허용 | 최우선 단축된 기한 적용, 보상 통제 즉시 배포 |
| 내부 자산 | 프라이빗 서브넷, 내부 전용 대상 그룹 | 후순위 정기 패치 주기 내 처리 |
| 컨테이너 이미지 | ECR 스캔 결과에서 해당 패키지 버전 확인 | 재빌드 기준 이미지 교체 후 배포 |
| 패치 불가 자산 | 지원 종료 버전, 벤더 지원 종료, 애플리케이션 호환성 제약 | 보상 통제 별도 관리 대장 등록 및 소명 문서 작성 |
| 관리 범위 외 | SSM 에이전트 미설치, 인벤토리 미수집 | 사각지대 자산 목록 정확성 결함으로 별도 보고 |
7. 3단계보상 통제 — 패치까지의 시간 확보
긴급 취약점에서 패치와 점검 창 사이에는 반드시 공백이 생깁니다. 당국 권고가 웹 애플리케이션 방화벽을 임시 보호 수단으로 제시한 이유가 여기에 있습니다. Lambda가 이 배포를 수행하면 공백 구간을 분 단위로 줄일 수 있습니다.
보상 통제 적용 Lambda — 속도 제한 규칙을 우선순위 상단에 삽입
import boto3
waf = boto3.client("wafv2", region_name="us-east-1") # CloudFront 범위
def apply_rate_limit(web_acl_name, web_acl_id, limit=300):
acl = waf.get_web_acl(Name=web_acl_name, Id=web_acl_id, Scope="CLOUDFRONT")
rules = acl["WebACL"]["Rules"]
if any(r["Name"] == "EmergencyRateLimit" for r in rules):
return "already_applied"
rules.insert(0, {
"Name": "EmergencyRateLimit",
"Priority": 0,
"Statement": {
"RateBasedStatement": {"Limit": limit, "AggregateKeyType": "IP"}
},
"Action": {"Block": {}},
"VisibilityConfig": {
"SampledRequestsEnabled": True,
"CloudWatchMetricsEnabled": True,
"MetricName": "EmergencyRateLimit",
},
})
waf.update_web_acl(
Name=web_acl_name, Id=web_acl_id, Scope="CLOUDFRONT",
DefaultAction=acl["WebACL"]["DefaultAction"],
Rules=rules,
VisibilityConfig=acl["WebACL"]["VisibilityConfig"],
LockToken=acl["LockToken"],
)
return "applied"
보상 통제로 적용 가능한 수단과 그 성격은 다음과 같습니다.
| 수단 | 효과 | 기록 시 표현 |
|---|---|---|
| 관리형 규칙 그룹 적용 | 부분 | 알려진 악성 요청 패턴 차단 — 해당 취약점 전용 차단 아님 |
| 속도 기반 규칙 | 부분 | 반복 시도 기반 공격의 성공률 저감 |
| 노출 경로 축소 | 유효 | 불필요한 엔드포인트·포트 폐쇄로 공격 표면 제거 |
| 오프라인 전환 | 유효 | 위험 제거. 서비스 영향이 크므로 사전 승인 절차 필수 |
| 설정 기반 완화 | 제한 | 공급자가 유효성을 명시한 경우에만 적용. 임의 판단 금지 |
8. 4단계패치 실행과 승인 게이트
패치 실행은 서비스 영향을 수반하므로 완전 무인 자동화에 적합하지 않습니다. Step Functions의 대기 상태를 이용해 승인 게이트를 두는 구성을 권장합니다. 승인 요청과 승인 결과가 모두 기록으로 남으므로, 변경 관리 항목의 증적이 자동으로 생성되는 부수 효과가 있습니다.
- 인터넷 노출 자산 — 담당자 승인 후 즉시 패치. 승인 대기 시간도 기록합니다.
- 내부 자산 — 다음 점검 창에 Patch Manager 기준으로 일괄 적용
- 컨테이너 — 기준 이미지를 패치 버전으로 교체하고 재빌드·재배포. 이미지 태그를 고정하지 않은 환경에서는 재배포만으로 해결되지 않으므로 기준 이미지 버전을 명시적으로 관리해야 합니다.
- 롤백 기준 — 패치 후 오류율 임계치를 초과하면 자동 롤백하도록 배포 설정과 연동
패치 실행 Lambda — 대상 태그 기준 일괄 실행
def run_patch(instance_ids: list[str], approval_id: str):
resp = ssm.send_command(
InstanceIds=instance_ids,
DocumentName="AWS-RunPatchBaseline",
Parameters={"Operation": ["Install"]},
Comment=f"emergency patch approval={approval_id}",
MaxConcurrency="25%", # 동시 영향 범위 제한
MaxErrors="0", # 실패 발생 시 중단
)
return resp["Command"]["CommandId"]
MaxConcurrency를 낮게 설정하면 패치로 인한 장애가 전체 서비스로 번지는 것을 방지할 수 있습니다.
긴급 상황에서 속도를 높이려는 압박이 있으나, 패치 실패로 서비스가 중단되면 가용성 항목에서 별건의 문제가 발생합니다.
조치 기한과 동시성 한도는 사전에 정책으로 정해 두어야 합니다.
9. 5단계심사 증적 자동 생성
이 단계가 자동화의 실질적 가치입니다. 대응 과정의 모든 판단과 실행을 항목 단위로 적재하면, 심사 시점에 조회만으로 증적을 제출할 수 있습니다.
대응 이력 적재 — 항목 단위 기록 구조
{
"advisory_id": "CVE-2026-109618",
"asset_id": "i-0abc123def456",
"detected_at": "2026-10-21T09:14:02Z",
"detection_source": "manual_trigger",
"installed_version": "8.2.21",
"internet_facing": true,
"sla_deadline": "2026-10-22T09:14:02Z",
"compensating_control": {
"type": "waf_rate_limit",
"applied_at": "2026-10-21T09:21:35Z",
"note": "패치 전 위험 완화 — 취약점 전용 차단 아님"
},
"remediation": {
"status": "completed",
"method": "AWS-RunPatchBaseline",
"approved_by": "security-lead",
"executed_at": "2026-10-21T14:02:11Z",
"verified_version": "8.2.35",
"verified_at": "2026-10-21T14:19:40Z"
},
"sla_met": true
}
이 구조로 적재하면 심사에서 요구되는 다음 질문에 조회로 답할 수 있습니다.
- 해당 취약점을 언제 인지했으며 인지 경로는 무엇인가
- 영향 자산은 몇 건이며 산정 근거는 무엇인가
- 조치 기한은 어떻게 정했고 기한 내 조치율은 얼마인가
- 기한을 초과한 자산은 무엇이며 그 사유는 무엇인가
- 패치하지 못한 자산에 어떤 보상 통제를 적용했는가
- 조치 완료를 무엇으로 검증했는가
- 보상 통제는 언제 해제했으며 해제 근거는 무엇인가
보고서는 S3에 월 단위로 적재하고 Object Lock을 적용해 사후 변경을 차단합니다. 보존 기간은 조직의 기록 보관 정책에 맞추되, 연 1회 사후 심사와 3년 주기 갱신 심사를 고려해 최소 3년 이상을 권장합니다.
10. 패치할 수 없는 자산 — 가장 어려운 구간
2026년 10월 사례에서 지원 종료 버전에는 패치가 제공되지 않았습니다. 이런 자산이 존재한다는 사실 자체가 지적 사항이 되는 것은 아닙니다. 문제는 그 상태를 조직이 인지하고 통제하고 있음을 증명하지 못할 때 발생합니다.
패치 불가 자산은 다음 네 가지를 문서로 갖추어야 합니다.
- 불가 사유 — 지원 종료, 애플리케이션 호환성, 벤더 계약 종료 등 구체적 사유와 확인 근거
- 위험 평가 — 해당 자산의 노출 수준, 처리 정보의 중요도, 침해 시 영향 범위
- 보상 통제 — 적용한 통제와 그 한계, 잔여 위험 수준
- 해소 계획 — 교체·업그레이드 일정과 책임자. 기한 없는 “검토 중”은 통제로 인정되지 않습니다
자동화는 이 중 1번과 3번의 현황을 자동으로 수집할 수 있습니다. 2번과 4번은 조직의 판단이 필요한 영역이므로, 자동화 보고서에 판단 대기 상태로 남겨 담당자가 작성하도록 설계합니다. 여기서 지원 종료 버전을 운영 중인 자산 목록이 자동으로 집계되면, 긴급 취약점이 공시될 때마다 반복되는 조사 작업이 제거됩니다.
11. 자동화 자체에 적용하는 통제
취약점 대응 자동화는 패치 실행과 방화벽 규칙 변경 권한을 보유합니다. 이 자동화가 침해되면 공격자가 환경 전체를 조작할 수 있으므로, 자동화 자체도 통제 대상입니다.
| 항목 | 조치 |
|---|---|
| 실행 역할 최소 권한 | 함수별로 역할을 분리합니다. 산정 함수는 읽기 권한만, 조치 함수만 실행 권한을 보유하도록 구성합니다. |
| 조치 대상 범위 제한 | IAM 정책의 리소스 조건에 태그 기준을 적용하여, 자동화가 지정된 자산군 외부를 변경하지 못하도록 제한합니다. |
| 승인 게이트 | 서비스 영향이 있는 조치는 사람의 승인을 거치도록 하고, 승인자와 시점을 기록합니다. |
| 코드 무결성 | 함수 코드를 형상 관리하고 코드 서명을 적용합니다. 콘솔 직접 편집은 차단합니다. |
| 실행 감사 | CloudTrail로 자동화의 모든 API 호출을 기록하고, 함수 로그 보존 기간을 기록 보관 정책에 맞춥니다. |
| 비밀 관리 | 외부 연동 자격 증명은 Secrets Manager에 보관하고 환경 변수에 평문으로 두지 않습니다. |
12. 도입 시 유의사항
- 자산 인벤토리가 선행 조건입니다. SSM 에이전트 배포와 인벤토리 수집이 되어 있지 않으면 자동화의 산정 결과를 신뢰할 수 없습니다. 자동화보다 인벤토리 완성도를 먼저 확보해야 합니다.
- 조치 기한 정책이 없으면 기한 준수 판정이 불가합니다. 심각도별 기한을 내부 규정으로 먼저 정의하시기 바랍니다.
- 보상 통제를 조치 완료로 기재하지 않습니다. 상태 구분을 코드 수준에서 강제해 혼용을 방지합니다.
- 초기 정보 변경에 대비합니다. 공시 직후 판단을 고정하지 않고, 정기 재평가로 영향 범위와 심각도를 갱신합니다.
- 자동화 실패도 기록합니다. 함수 오류로 산정이 누락된 구간이 있다면 그 사실을 보고서에 남겨야 합니다. 침묵하는 자동화가 수작업보다 위험합니다.
- 단계적으로 도입합니다. 1단계와 2단계(수집·산정)만 먼저 구축해도 긴급 대응 시간이 크게 단축됩니다. 조치 자동화는 그 다음입니다.
13. 결론
2026년 10월 PHP 사례의 교훈은 특정 런타임의 취약성이 아닙니다. 패치만이 해결책인 취약점이 공시되고, 이틀 뒤 후속 취약점이 나오고, 구버전에는 패치가 제공되지 않는 상황이 앞으로도 반복된다는 점입니다. 이때 조직에 필요한 것은 더 나은 아키텍처가 아니라, 인지에서 검증까지를 기록과 함께 수행하는 절차입니다.
Lambda를 이 맥락에 배치할 때의 역할은 명확합니다.
- 취약한 런타임의 대체가 아닙니다. 서버리스 전환은 중장기 해소 계획의 항목입니다.
- 인지·산정·조치·검증의 오케스트레이터입니다. 사람이 긴급 상황에서 누락하는 기록을 자동으로 남깁니다.
- 보상 통제의 적용 속도를 분 단위로 단축합니다. 패치까지의 공백을 줄이는 것이 실질적 위험 저감입니다.
- 심사 증적을 자동으로 생성합니다. 조회만으로 제출할 수 있는 상태를 상시 유지합니다.
취약점 관리에서 심사 지적을 받는 사례는 대부분 조치 미이행이 아니라 조치 기록 부재입니다. 긴급 상황에서 사람이 가장 먼저 포기하는 작업이 기록이기 때문입니다. 자동화의 목적을 조치 속도가 아니라 기록의 완전성에 두시기 바랍니다. 제이씨클라우드는 취약점 진단 및 대응 자동화, ISMS-P 대응 증적 체계 구축을 지원하고 있습니다.
참고 자료
- 정보보호 및 개인정보보호 관리체계 인증 등에 관한 고시 — 과학기술정보통신부·개인정보보호위원회
- Critical Vulnerabilities in PHP Require Immediate Patching — CISA (2026-10-21)
- PHP2Shell — Critical vulnerabilities in PHP: detection, analysis, and remediation — Datadog Security Labs
- Threat Brief: CVE-2026-109618, CVE-2026-109619 — Palo Alto Networks Unit 42 (2026-10-25 갱신)
- Responding to core PHP vulnerabilities — Google Cloud
- PHP shares mitigation for new and unpatched RCE vulnerability — BleepingComputer (CVE-2026-115560)
- AWS Systems Manager, Amazon Inspector, AWS WAF, AWS Step Functions 개발자 안내서 — AWS 공식 문서
관련 글: AWS 환경에서 ISMS-P 대응 인프라 구성하기 · AWS CSPM 설정 · 국내 보안 인증 제도와 Amazon CloudFront
