본문 바로가기

Web Security/Secure Coding

시큐어 코딩 (XPath Injection)

XPath Injection 이란? 

 외부 입력 값을 적절한 검사과정 없이 XPath 쿼리문 생성을 위한 문자열로 사용하면, 공격자는 프로그래머가 의도하지 않았던 문자열을 전달하여 쿼리문의 의미를 왜곡시키거나 그 구조를 변경하고 임의의 쿼리를 실행하여 인가되지 않은 데이터를 열람할 수 있게 만드는 공격

 

XPath 란?

 XPath는 XML 문서의 일부에 주소를 지정하기 위한 언어로, XSLT와 XPointer에서 모두 사용된다. 

 

XPath 역할 

 XPath는 XML 문서를 노드 트리로 모델링하여 경로 표현식(Path Expression)을 통해 XML 문서의 노드 또는 노드 집합을 선택한다. 이 때, 경로 표현식은 기존 컴퓨터 파일 시스템으로 작업할 때 볼 수 있는 표현식과 매우 유사하다. 이러한 XPath expression은 다양한 언어에서도 많이 사용되고 있다. XPath 노드들은 아래와 같이 총 7개로 구성되어있으며, 이러한 노드에 접근하기 편리하도록 XPath는 다양한 함수들을 제공한다. 

 

XPath Nodes 

  • root nodes
  • element nodes
  • text nodes
  • attribute nodes
  • namespace nodes
  • processing instruction nodes
  • comment nodes

아래 코드는 W3School 에 예시로 나와있는 코드의 일부이다.  

<?xml version="1.0" encoding="UTF-8"?>
<bookstore>
   <book category="cooking">
       <title lang="en">Everyday Italian</title>
       <author>Giada De Laurentiis</author>
       <year>2005</year>
       <price>30.00</price>
   </book>
   <book category="children">
       <title lang="en">Harry Potter</title>
       <author>J K. Rowling</author>
       <year>2005</year>
       <price>29.99</price>
   </book>
   <book category="web">
       <title lang="en">XQuery Kick Start</title>
       <author>James McGovern</author>
       <author>Per Bothner</author>
       <author>Kurt Cagle</author>
       <author>James Linn</author>
       <author>Vaidyanathan Nagarajan</author>
       <year>2003</year>
       <price>49.99</price>
   </book>
</bookstore>

예시를 통해 XPath가 어떻게 사용되는지 알아보자. 

 

우선 위 코드에서 노드들은 아래와 같이 나타낼 수 있다.

bookstore (root node), book(element node), lang="en"(attribute node), 2005(text node) 

 

이제 XPath 를 통해 값에 접근해보자. 

/bookstore/book[1]/title : Everyday Italian

/bookstore/book[price>35]/title : XQuery Kick Start

/bookstore/book/price[text()] : 30.00 29.99 49.99

/bookstore/book[@category='web']/title : XQuery Kick Start

//book/price : 30.00 29.99 49.99

/bookstore/book/price[text()='39.95' or '1'='1'] : 30.00 29.99 49.99

 

이와 같이, XML 문서에서 XPath를 통해 text에 접근할 수 있다. 

그럼, XPath에 대한 기본적인 이해를 모두 마쳤으니 이젠 XPath Injection이 어떻게 발생하는지 알아보자. 

 

XPath Injection 공격 원리 

1. 공격자가 'or '1'='1과 같이 특수 문자를 사용하여 XPath를 조작하여 웹 서버에 Request 요청 

2. 웹 서버는 XPath를 WAS(Web Application Server)에 전달

3. WAS는 조작된 XPath 실행

 

예제 코드를 통해 어떤 부분에서 취약점이 발생하는지 알아보자. 

```
   // 외부 입력 값 받음 
   String name = props.getProperty("name");
   String passwd = props.getProperty("password");
   
   ```
   XPathFactory factory = XPathFactory.newInstance(); 
   XPath xpath = factory.newXPath(); 
   ```
   
   // 외부 입력이 xpath의 인자로 사용 (취약 코드)
   XPathExpression expr = xpath.compile("//user/user[login/text()='" + name + "' and password/text() ='" + password + "']/home_dir/text()");
   Object result = expr.evaluate(doc, XPathConstants.NODESET); 
   
   NodeList nodes = (NodeList) result; 
   
   for(int i = 0 ; i < nodes.getLength(); i++) {
       String value = nodes.item(i).getNodeValue();
       if(value.indexOf(">") < 0) { 
           System.out.println(value); 
       }
   }
```

위 코드를 보면, XPath에 들어가는 name과 passwd가 필터링 없이 XPath에 포함되는 것을 알 수 있다. 이러한 경우, name부분에USER_ID' or '1'='1 를 입력하고, passwd 부분에 1'='1 를 입력하게 되면, XPath Injection을 시도할 수 있게 된다. 

 

[XPath Injection 보안 방법] 

이러한 XPath Injection을 막기 위해선, 특수 문자를 필터링해야하며 XQuery를 사용하여 미리 골격을 생성하여 인자 값을 전달하는 방식을 사용해야한다. 여기서 XQuery를 사용하는 이유는 외부의 입력으로부터 구조가 바뀌는 것을 막기 위함이다. 

 

우선 XQuery를 사용한 보안 코드를 알아보자. 

[dologin.xp]

declare variable $loginID as xs:string external; 
declare variable $password as xs:string external; 
//user/user[@loginID=$loginID and @password=$password]

[안전한 코드] 

   // 외부 입력
   String name = props.getProperty("name"); 
   String passwd = props.getProperty("password"); 
   Document doc = new Builder().build("users.xml"); 

   // Secure Coding (XQuery를 위한 정보 로딩) 
   XQuery xquery = new XQueryFactory().createXQuery(new File("dologin.xq")); 
   Map vars = new HashMap(); 
   vars.put("loginID", name); 
   vars.put("password", passwd); 
   
   Nodes results = xquery.execute(doc, null, vars).toNodes(); 
   
   for(int i = 0 ; i < results.size(); i++) { 
      System.out.println(results.get(i).toXML());
   }

위 코드와 같이, 형식을 만들어 놓고 인자를 전달하는 방식은 보안 수준을 더욱 높여준다. 추가적으로, 특수문자 필터링을 하기 위해선 외부 입력 값에 대한 화이트 리스트를 만들어 정규 표현식을 사용하여 해당 문자들을 필터링 해주는 작업을 해주면 된다. 

 

 

참고 문헌

[1] 시큐어 코딩 보안 가이드 https://www.kisa.or.kr/public/laws/laws3_View.jsp?mode=view

[2] W3C Recommendation XPath https://www.w3.org/TR/1999/REC-xpath-19991116/

[3] W3School XPath https://www.w3schools.com/xml/xml_xpath.asp