테마
06. 서버사이드 인젝션: Command·SSRF·XXE
서버가 대신 실행하거나 대신 요청하거나 대신 파싱하는 기능은 편리하지만, 입력 경계가 무너지면 서버 권한으로 위험한 동작이 일어난다.
학습 목표
- OS 명령 주입, SSRF, XXE가 공통적으로 어떤 구조에서 발생하는지 설명할 수 있다.
- 쉘 호출을 우회하는 안전한 서버 API 사용 원칙을 이해한다.
- 외부 URL 요청과 XML 파서에서 무엇을 제한해야 하는지 설명할 수 있다.
- 오래된 실습 중심 설명 대신 현재 기준의 방어 설계를 이해한다.
1. 세 취약점의 공통점
셋 다 본질은 같다.
- 입력값이 단순 데이터가 아니라
- 서버가 가진 실행 권한, 네트워크 권한, 파일 접근 권한으로
- 추가 해석을 하게 만드는 문제다
즉, "사용자 입력을 어디까지 해석하게 둘 것인가"가 핵심이다.
2. OS 명령 주입은 가능한 한 구조 자체를 없앤다
원문은 시스템 명령을 직접 실행하는 예시를 중심으로 설명하지만, 현재 기준에서는 명령어 실행을 하지 않는 구조가 1순위다.
좋은 방향
- 네트워크 진단이 필요하면 언어 라이브러리 사용
- 파일 압축이 필요하면 표준 라이브러리 사용
- 이미지 처리가 필요하면 안전한 전용 라이브러리 사용
피해야 할 방향
- 사용자 입력을 붙여 쉘 명령 문자열 구성
sh -c,cmd /c같은 쉘 경유 실행- 디버그 편의상 관리 도구를 웹에서 직접 노출
정말 외부 프로세스를 호출해야 한다면 원칙은 다음과 같다.
- 쉘을 거치지 않는 API 사용
- 인자를 배열 단위로 분리
- 실행 가능한 프로그램과 인자 집합을 Allow-list로 제한
- 타임아웃과 자원 제한 적용
3. SSRF는 "서버가 대신 요청한다"는 점이 문제다
SSRF(Server-Side Request Forgery)는 서버가 사용자 대신 다른 주소로 요청을 보내는 기능에서 자주 생긴다.
예를 들어 이런 기능이 위험하다.
- URL 미리보기
- 이미지 프록시
- 웹훅 테스트
- 외부 파일 가져오기
- PDF 렌더링용 원격 자원 로드
왜 위험할까?
- 외부 사용자는 접근할 수 없는 내부망에 서버는 접근할 수 있다
- 클라우드 메타데이터 엔드포인트 같은 민감 자원에 닿을 수 있다
- 서버가 인증된 네트워크 위치에서 요청하기 때문에 신뢰를 악용할 수 있다
4. SSRF 방어 원칙
4.1 목적지 Allow-list
호출 가능한 도메인이나 서비스 목록을 고정하는 편이 가장 강력하다.
4.2 URL 파싱과 DNS 재검증
- 문자열로 startsWith 비교하지 않는다
- 표준 URL 파서로 스킴, 호스트, 포트를 분리한다
- 리다이렉트 이후 목적지도 다시 검증한다
- DNS 재바인딩 같은 우회를 고려해 최종 IP도 확인한다
4.3 내부 주소 차단
사설 IP, 루프백, 링크 로컬, 메타데이터 주소 대역은 원칙적으로 차단한다.
- IPv4뿐 아니라 IPv6 루프백, 링크 로컬, ULA 대역도 함께 본다
- 클라우드 환경에서는 메타데이터 엔드포인트 차단 정책을 별도로 둔다
- AWS를 쓰면 IMDSv2 강제를 함께 검토한다
4.4 요청 제한
- GET만 허용할지
- 응답 크기를 얼마나 받을지
- 타임아웃을 얼마나 둘지
- 어떤 헤더를 제거할지
이 정책도 같이 필요하다.
5. XXE는 현대 파서 기본값을 이해하는 것이 중요하다
원문에는 XXE를 XML 외부 엔티티 취약점으로 설명한다. 핵심 개념은 맞다.
다만 현재는 언어와 파서 버전에 따라 기본값이 더 안전해졌다는 점을 같이 알아야 한다.
실무 원칙
- XML이 꼭 필요한지 먼저 확인
- 가능하면 JSON 같은 단순 포맷 사용
- XML이 필요하면 외부 엔티티와 DTD 처리를 비활성화
- 안전한 파서 옵션을 명시적으로 켠다
특히 오래된 자료에서 자주 보이는 libxml_disable_entity_loader(true) 같은 예시는 현재 기준에서 역사적 맥락이 강하다.
현대 스택에서는 현재 사용 중인 파서의 기본값과 권장 옵션을 확인하는 쪽이 더 중요하다.
6. XXE에서 확인할 것
| 확인 포인트 | 이유 |
|---|---|
| 외부 엔티티 허용 여부 | 파일/네트워크 참조 위험 |
| DTD 허용 여부 | 엔티티 선언과 확장 위험 |
| 파서 옵션 명시 여부 | 런타임 업그레이드 시 동작 차이 방지 |
| 업로드 XML 크기 제한 | 파서 자원 고갈 완화 |
XML 파서 보안은 "기본값이 안전하겠지"라고 넘기지 말고 현재 라이브러리 문서를 한 번 더 확인하는 습관이 필요하다.
7. 원문을 현재 기준으로 다시 해석하면
| 원문 초점 | 현재식 정리 |
|---|---|
| 명령 실행 실습 | 웹에서 쉘 호출을 제거하는 구조 설계가 우선 |
| XXE 실습용 외부 엔티티 예시 | 현대 파서 기본 안전 설정과 명시적 비활성화가 우선 |
| 내부망 2차 침투 강조 | 개발자 문서에서는 외부 URL, 메타데이터, 내부 API 접근 차단 원칙으로 정리 |
즉, 공격 절차를 자세히 따라가는 대신 어떤 기능이 위험한 해석을 일으키는가를 보는 편이 학습 가치가 높다.
8. PR 리뷰 체크리스트
- 쉘 명령 호출을 대체할 표준 라이브러리가 없는가
- 외부 프로세스를 호출해야 한다면 쉘을 거치지 않는가
- 서버가 호출할 수 있는 URL 대상이 Allow-list로 제한되는가
- 사설망, 루프백, 메타데이터 대역 차단이 있는가
- XML 파서 옵션이 현재 권장값으로 명시되어 있는가
- 외부 응답 크기, 타임아웃, 리다이렉트 정책이 제한되는가
핵심 정리
- Command Injection, SSRF, XXE는 모두 서버가 입력을 과하게 해석할 때 생긴다
- 가장 좋은 방어는 위험한 해석 구조 자체를 줄이는 것이다
- 서버가 대신 요청하거나 실행하거나 파싱하는 기능은 항상 Allow-list와 제한 정책이 필요하다
- 오래된 실습용 예제를 따라가기보다 현재 사용 중인 런타임과 라이브러리의 안전 기본값을 확인해야 한다