Post

Java XPath 삽입 코딩 기법

Java XPath 삽입 코딩 기법

1. 정의

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

xpath-injection

2. 안전한 코딩 기법

  • XPath 쿼리에 사용되는 외부 입력 데이터에 대하여 특수문자(", [, ], /, =, @ 등 ) 및 쿼리 예약어 필터링을 수행하고 인자화된 쿼리문을 지원하는 XQuery를 사용한다.

3. 예제

다음의 예제에서 name의 값으로 user1, passwd의 값으로 'or ''='을 전달하면 다음과 같은 질의문이 생성되어 인증과정을 거치지 않고 로그인할 수 있다.

1
//users/user[login/text()=‘user1' or ''='' and password/text() = “ or ”=“]/home_dir/text()
  • 안전하지 않은 코드의 예
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// 외부로 부터 입력을 받음
String name = props.getProperty("name");
String passwd = props.getProperty("password");

XPathFactory factory = XPathFactory.newInstance();
XPath xpath = factory.newXPath();

// 외부 입력이 XPath의 인자로 사용
XPathExpression expr = xpath.compile("//users/user[login/text()='" + name + "' and password/text() = '" + passwd + "']/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);
    }
}

다음의 예제와 같이 인자화된 질의문을 지원하는 XQuery를 사용하여 미리 질의 골격을 생성하고 이에 인자값을 설정함으로써 외부의 입력으로 인하여 질의 구조가 바뀌는 것을 막을 수 있다.

  • 안전한 코드의 예
1
2
3
4
// dologin.xp 파일
declare variable $loginID as xs:string external;
declare variable $password as xs:string external;
//users/user[@loginID=$loginID and @password=$password]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
// XQuery를 이용한 XPath Injection 방지
// 외부로 부터 입력을 받음
String name = props.getProperty("name");
String passwd = props.getProperty("password");
Document doc = new Builder().build("users.xml");
// 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());
}

[출처 및 참고]

This post is licensed under CC BY 4.0 by the author.