XQuery Injection 공격이란?
XQuery를 사용하여 XML 데이터에 대한 동적 쿼리문을 생성할 때 사용하는 외부 입력 값에 대해 적절한 검증 절차가 존재하지 않을 경우, 공격자가 쿼리문의 구조를 임의로 변경하여 허가되지 않은 데이터를 조회하거나 인증 절차를 우회할 수 있게 되는 공격.
XQuery Injection 공격 원리
1. 공격자가 XQuery Injection을 시도
2. XML 데이터에 대한 조작된 동적 쿼리문 생성
3. 조작된 XQuery 문 실행
4. 서버는 실행된 결과(공격 결과)를 공격자에게 전달
예제 코드를 보며 XQuery Injection 이 일어나는 이유를 살펴보자.
[안전하지 않은 코드]
```
String name = props.getProperty("name");
// Connection
Hashtable env = new Hashtable();
env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LadpCtxFactory");
env.put(Context.PROVIDER_URL, "ladp://localhost:389/o=rootDir");
javax.naming.directory.DirContext ctx = new InitialDirContext(env);
java.xml.xquery.XQDataSource xqds = (javax.xml.xquery.XQDataSource) ctx.look-up("xqj/personnel");
javax.xml.xquery.XQConnection conn = xqds.getConnection();
// 취약한 코드
String es = "doc('user.xml')/userlist/user[uname='" + name + "']";
// 입력 값이 XQuery의 인자로 사용
XQPreparedExpression expr = conn.prepareExpression(es);
XQResultSequence result = expr.executeQuery();
while(result.next()) {
...
}
```
위 코드를 살펴 보면, 외부 입력 값을 받은 것을 XQuery 문에 바로 포함시켜 실행하는 것을 알 수 있다. 이러한 경우, XQuery상의 쿼리 구조 변경시키는 입력 값이 들어오게 되면 XQuery Injection 이 실행될 것이다.
이를 막기 위해선, 아래와 같이 preparedExpression 을 사용하여 bindString, bindInt 등으로 인자 형식으로 전달해줍니다. 이와 같이 인자 전달을 하게 되면, 외부에서 입력된 값은 단순히 문자열로 취급되어 XQuery 상의 쿼리 문법으로 인식되지 않아 쿼리 구조를 변경시킬 수 없게 됩니다.
[안전한 코드]
```
String name = props.getProperty("name");
// Connection
Hashtable env = new Hashtable();
env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LadpCtxFactory");
env.put(Context.PROVIDER_URL, "ladp://localhost:389/o=rootDir");
javax.naming.directory.DirContext ctx = new InitialDirContext(env);
java.xml.xquery.XQDataSource xqds = (javax.xml.xquery.XQDataSource) ctx.look-up("xqj/personnel");
javax.xml.xquery.XQConnection conn = xqds.getConnection();
// Secure Coding
String es = "doc('user.xml')/userlist/user[uname='$xpathname']";
// 입력 값이 XQuery의 인자로 사용
XQPreparedExpression expr = conn.prepareExpression(es);
// Secure Coding
expr.bindString(new QName("xpathname"), name, null);
XQResultSequence result = expr.executeQuery();
while(result.next()) {
...
}
```
쿼리 구조를 변경 시킬 수 없는 이유를 이해하기 위해서는 Expression 과 preparedExpression의 동작 원리를 이해하고 있으면 어떤 방식으로 인해 보안이 이루어지는지 알 수 있으며, bind[타입] 메소드를 사용하느냐 안하느냐에 따라 XQuery Injection 공격을 막느냐 못막느냐가 결정되기 때문에 이러한 부분을 이해하는 것이 중요한 것 같다.
Expression과 preparedExpression 방식 차이점에 대해 더 알아보고 싶다면, 아래 링크를 참고하시면 됩니다 :)
XQuery Java API : http://www09.sigmod.org/sigmod/record/issues/0912/p07.article.cappellen.pdf
참고 문헌
[1] 시큐어 코딩 보안 가이드 https://www.kisa.or.kr/public/laws/laws3_View.jsp?mode=view
'Web Security > Secure Coding' 카테고리의 다른 글
시큐어 코딩 (XPath Injection) (0) | 2021.08.01 |
---|---|
시큐어 코딩 (Open Redirect) (0) | 2021.07.30 |
시큐어 코딩 (File upload vulnerability) (0) | 2021.07.30 |
시큐어 코딩 (Command Injection) (0) | 2021.07.29 |
시큐어 코딩 (Cross-Site Scripting) (0) | 2021.07.29 |