보안 공부/소스코드 보안약점 진단

소스코드 보안약점 진단 - XQuery 삽입

H.J.World 2021. 12. 15. 10:10
728x90
반응형

소스코드 보안약점 진단 // 소프트웨어 보안약점 진단 // SW 보안약점 진단과 같이 다양한 이름으로 불리는 진단 과업 중 하나이다.

SW개발보안은 해킹 등 사이버공격의 원인인 보안약점을 SW개발단계에서 사전에 제거하고 SW 개발 생명주기의 각 단계별로 수행하는 일련의 보안활동을 통하여 안전한 SW를 개발·운영하기 위한 목적으로 적용하는 개발체계이다.

해당 내용은 KISA에서 발간하는 취약점 진단 가이드 항목을 기준으로 작성한다.

 

7. XQuery 삽입

가. 개요

XQuery를 사용하여 XML 데이터에 대한 동적쿼리 생성시 사용되는 외부입력값에 대해 적절한 검증 절차가 존재하지 않으면 공격자가 쿼리문의 구조를 임의로 변경할 수 있게 된다. 이로 인해 허가되지 않은 데이터를 조회하거나 인증절차를 우회할 수 있다.

나. 보안대책

XQuery에 사용되는 외부 입력데이터에 대하여 특수문자 및 쿼리 예약어를 필터링하고, XQuery를 사용한 쿼리문은 문자열을 연결하는 형태로 구성하지 않고 파라미터(Parameter)화된 쿼리문을 사용 한다.

다. 코드예제

다음의 예제에서는 executeQuery를 통해 생성되는 쿼리의 파라미터의 일부로 외부입력값 (name)을 사용하고 있다. 만일 something’ or ‘1’=‘1 을 name의 값으로 전달하면 다음과 같은 쿼리문을 수행할 수 있으며, 이를 통해 파일 내의 모든 값을 출력할 수 있게 된다.

doc(‘users.xml’)/userlist/user[uname=‘something’ or ‘1’=‘1’]

- 안전하지 않은 코드의 예 JAVA -

1: // 외부 입력 값을 검증하지 않고 XQuery 표현식에 사용한다.
2: String name = props.getProperty("name");
3: .......
4: // 외부 입력 값에 의해 쿼리 구조가 변경 되어 안전하지 않다.
5: String es = "doc('users.xml')/userlist/user[uname='"+name+"']";
6: XQPreparedExpression expr = conn.prepareExpression(es);
7: XQResultSequence result = expr.executeQuery();

 

- 안전한 코드의 예 JAVA -

1: // blingString 함수로 쿼리 구조가 변경되는 것을 방지한다.
2: String name = props.getProperty("name");
3: .......
4: String es = "doc('users.xml')/userlist/user[uname='$xname']";
5: XQPreparedExpression expr = conn.prepareExpression(es);
6: expr.bindString(new QName("xname"), name, null);
7: XQResultSequence result = expr.executeQuery();

 

라. 진단방법

XQuery가 실행되는 부분을 확인하고(①), XQuery 쿼리스트링에 사용되는 변수가 외부 입력값 여부 를 확인한 후(②), 변수에 대한 필터링 모듈이 존재하는지 확인한다. 필터링 모듈이 존재하거나 관련 프레임워크에서 적절히 조치할 경우 안전한 것으로 판정한다.

1: …
2: // 외부로부터 입력을 받음
3: String name = props.getProperty(“name”);--------------------②
4: Hashtable env = new Hashtable();
5: env.put(Context.INITIAL_CONTEXT_FACTORY, “com.sun.jndi.ldap.LdapCtxFactory”);
6: env.put(Context.PROVIDER_URL, “ldap://localhost:389/o=rootDir”);
7: javax.naming.directory.DirContext ctx = new InitialDirContext(env);
8: javax.xml.xquery.XQDataSource xqds = (javax.xml.xquery.XQDataSource) 
ctx.lookup(“x- qj/personnel”);
9: javax.xml.xquery.XQConnection conn = xqds.getConnection();
10:
11: String es = “doc(‘users.xml’)/userlist/user[uname=’” + name + “’]”; ---②
12: // 입력값이 Xquery의 인자로 사용
13: XQPreparedExpression expr = conn.prepareExpression(es);
14: XQResultSequence result = expr.executeQuery();---------------------①
15: while (result.next()) {
16: String str = result.getAtomicValue();
17: if (str.indexOf(‘>’) < 0) {
18: System.out.println(str);
19: }
20: …

 

- 정탐코드의 예 -

다음의 코드에서는 외부의 입력(name)값을 executeQuery를 사용한 쿼리생성의 문자열 인자 생성 에 사용하고 있다. 만일 다음과 something’ or ‘=’1 을 name의 값으로 전달하면 다음과 같은 쿼리 문을 수행할 수 있으며, 이를 통해 파일 내의 모든 값을 출력할 수 있게 되어 취약하다.

(doc(‘users.xml’)/userlist/user[uname=’something’ or ‘=’)

1: …
2: // 외부로부터 입력을 받음
3: String name = props.getProperty(“name”);
4: Hashtable env = new Hashtable();
5: env.put(Context.INITIAL_CONTEXT_FACTORY, “com.sun.jndi.ldap.LdapCtxFactory”);
6: env.put(Context.PROVIDER_URL, “ldap://localhost:389/o=rootDir”);
7: javax.naming.directory.DirContext ctx = new InitialDirContext(env);
8: javax.xml.xquery.XQDataSource xqds = (javax.xml.xquery.XQDataSource) 
ctx.lookup(“x- qj/personnel”);
9: javax.xml.xquery.XQConnection conn = xqds.getConnection();
10:
11: String es = “doc(‘users.xml’)/userlist/user[uname=’” + name + “’]”;
12: // 입력 값이 Xquery의 인자로 사용
13: XQPreparedExpression expr = conn.prepareExpression(es);
14: XQResultSequence result = expr.executeQuery();
15: while (result.next()) {
16: String str = result.getAtomicValue();
17: if (str.indexOf(‘>’) < 0) {
18: System.out.println(str);
19: }
20: …
728x90
반응형