본문 바로가기

보안/시큐어코딩

[시큐어코딩-8] 입력데이터 검증및 표현(8) XPath삽입


발생원인 


외부 입력값을 적절한 검사과정 없이 XPath 쿼리문 생성에 이용할 경우 발생


영향


데이터 변조, 조회, 인증 우회


코드예



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

……

// 외부로 부터 입력을 받음

String name = props.getProperty("name");

String passwdprops.getProperty("password");

……

XPathFactory factory = XPathFactory.newInstance();

XPath xpath = factory.newXPath();

……

// 외부 입력이 xpath의 인자로 사용

XPathExpression exprxpath.compile("//users/user[login/text()='" +name + "' and password/text() = '" + 

 passwd + "']/home_dir/text()");

Object result = xpr.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);

}

……


 Name과 passwd에 대한 입력값 검증을 수행하지 않음



 안전한 코드의 예 - JAVA

dologin.xp 파일

declare variable $loginID as xs:string external;

declare variable $password as xs:string external;

//users/user[@loginID=$loginID

//and @password=$password]

//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());

}

 쿼리 구조가 변경되는 것을 막는 형태로 구성



<참고> XPath 란?

XML문서의 part를 정의하기 위한 문법이다. XML내부를 검색하기 위한 path expression을 사용한다. XPath는 표준함수의 라이브러리를 갖고 있다.  W3C표준이다.

 

XPath 예제

이 항목에서는 XPath 참조 전체에 나타나는 구문 예제를 살펴봅니다. 모든 예제는 XPath 구문에 대한 샘플 XML 파일(inventory.xml)을 기반으로 합니다. 테스트 파일에서 XPath 식을 사용하는 예제는 이 항목 하단의 "통합( | ) 예제"를 참조하십시오.

 

참조 항목

./author

현재 컨텍스트 내에 있는 모든 <author> 요소. 이 식은 다음 행에 나온 식과 같습니다.

author

현재 컨텍스트 내에 있는 모든 <author> 요소

first.name

현재 컨텍스트 내에 있는 모든 <first.name> 요소

/bookstore

이 문서의 문서 요소(<bookstore>)

//author

문서에 있는 모든 <author> 요소

book[/bookstore/@specialty=@style]

style 특성 값이 문서의 루트에 있는 <bookstore> 요소의 specialty 특성 값과 같은 모든 <book> 요소

author/first-name

<author> 요소의 자식인 모든 <first-name> 요소

bookstore//title

<bookstore> 요소(임의의 하위 항목)에서 수준이 하나 이상인 모든 세부 <title> 요소. 이 식은 다음 행에 나온 식과 다릅니다.

bookstore/*/title

<bookstore> 요소의 최하위인 모든 <title> 요소

bookstore//book/excerpt//emph

<bookstore> 요소 내에 있는 <book> 요소의 <excerpt> 자식 내에 있는 모든 <emph> 요소

.//title

현재 컨텍스트에서 수준이 하나 이상인 모든 세부 <title> 요소. 이 상황은 유일하게 기간 노테이션이 필요한 경우입니다.

author/*

<author> 요소의 모든 자식 요소

book/*/last-name

<book> 요소의 최하위인 모든 <last-name> 요소

*/*

현재 컨텍스트의 모든 최하위 요소

*[@specialty]

specialty 특성이 있는 모든 요소

@style

현재 컨텍스트의 style 특성

price/@exchange

현재 컨텍스트 내에 있는 <price> 요소의 exchange 특성

price/@exchange/total

특성에 요소 자식이 포함되지 않았으므로 빈 노드 집합을 반환합니다. 이 식은 XPath(XML Path Language) 문법상 허용되지만 엄격히 말하면 유효하지 않습니다.

book[@style]

현재 컨텍스트의 style 특성이 있는 모든 <book> 요소

book/@style

현재 컨텍스트의 모든 <book> 요소에 대한 style 특성

@*

현재 요소 컨텍스트의 모든 특성

./first-name

현재 컨텍스트 노드에 있는 모든 <first-name> 요소. 이 식은 다음 행에 나온 식과 같습니다.

first-name

현재 컨텍스트 노드에 있는 모든 <first-name> 요소

author[1]

현재 컨텍스트 노드에서 첫 번째 <author> 요소

author[first-name][3]

<first-name> 자식 요소가 있는 세 번째 <author> 요소

my:book

my 네임스페이스의 <book> 요소

my:*

my 네임스페이스의 모든 요소

@my:*

my 네임스페이스의 모든 특성. 여기에는 my 네임스페이스의 요소에서 비정규화된 특성이 포함되지 않습니다.

 

인덱스는 부모에 상대적입니다. 다음 데이터를 살펴보십시오.

<x>
  <y/>
  <y/>
</x>
<x>
  <y/>
  <y/>
</x>

 

참조 항목

x/y[1]

<x>의 첫 번째 <y> 자식.이 식은 다음 행에 나온 식과 같습니다.

x/y[position() = 1]

<x>의 첫 번째 <y> 자식

(x/y)[1]

<x> 요소의 전체 <y> 자식 집합에서 첫 번째 <y>

x[1]/y[2]

첫 번째 <x>의 두 번째 <y> 자식

 

나머지 예제는 XPath에 대한 샘플 XML 파일을 참조합니다.

 

참조 항목

book[last()]

현재 컨텍스트 노드의 마지막 <book> 요소

book/author[last()]

현재 컨텍스트 노드에서 각 <book> 요소의 마지막 <author> 자식

(book/author)[last()]

현재 컨텍스트 노드에서 <book> 요소의 전체 <author> 자식 집합에서 마지막 <author> 요소

book[excerpt]

<excerpt> 요소 자식이 하나 이상 포함된 모든 <book> 요소

book[excerpt]/title

<excerpt> 요소 자식이 하나 이상 포함된 <book> 요소의 자식인 모든 <title> 요소

book[excerpt]/author[degree]

<degree> 요소 자식이 하나 이상 포함되어 있고, <excerpt> 요소가 하나 이상 포함된 <book> 요소의 자식인 모든 <author> 요소

book[author/degree]

<degree> 자식이 하나 이상 포함된 <author> 자식을 포함하는 모든 <book> 요소

author[degree][award]

<degree> 요소 자식과 <award> 요소 자식이 하나 이상 포함된 모든 <author> 요소

author[degree and award]

<degree> 요소 자식과 <award> 요소 자식이 하나 이상 포함된 모든 <author> 요소

author[(degree or award) and publication]

<degree> 또는 <award> 요소 하나 이상과 <publication> 요소가 자식으로 하나 이상 포함된 모든 <author> 요소

author[degree and not(publication)]

<degree> 요소 자식이 하나 이상 포함되어 있고 <publication> 요소 자식이 포함되지 않은 모든 <author> 요소

author[not(degree or award) and publication]

<publication> 요소 자식이 하나 이상 포함되어 있고 <degree><award> 요소 자식이 포함되지 않은 모든 <author> 요소

author[last-name = "Bob"]

값이 Bob<last-name> 요소 자식이 하나 이상 포함된 모든 <author> 요소

author[last-name[1] = "Bob"]

첫 번째 <last-name> 자식 요소의 값이 Bob인 모든 <author> 요소.이 식은 다음 행에 나온 식과 같습니다.

author[last-name [position()=1]= "Bob"]

첫 번째 <last-name> 자식 요소의 값이 Bob인 모든 <author> 요소

degree[@from != "Harvard"]

from 특성이 "Harvard"가 아닌 모든 <degree> 요소

author[.= "Matthew Bob"]

값이 Matthew Bob인 모든 <author> 요소

author[last-name = "Bob" and ../price &gt; 50]

값이 Bob<last-name> 자식 요소와 값이 50보다 큰 <price> 형제 요소가 포함된 모든 <author> 요소

book[position() &lt;= 3]

처음 세 책(1, 2, 3)입니다.

author[not(last-name = "Bob")]

값이 Bob<last-name> 자식 요소가 포함되지 않은 모든 <author> 요소

author[first-name = "Bob"]

값이 Bob<first-name> 자식이 하나 이상 포함된 모든 <author> 요소

author[* = "Bob"]

값이 Bob인 자식 요소가 포함된 모든 author 요소

author[last-name = "Bob" and first-name = "Joe"]

값이 Bob<last-name> 자식 요소와 값이 Joe<first-name> 자식 요소가 포함된 모든 <author> 요소

price[@intl = "Canada"]

컨텍스트 노드에서 intl 특성이 "Canada"인 모든 <price> 요소

degree[position() &lt; 3]

컨텍스트 노드의 자식인 처음 두 <degree> 요소

p/text()[2]

컨텍스트 노드의 각 <p> 요소에서 두 번째 텍스트 노드

ancestor::book[1]

컨텍스트 노드의 가장 가까운 <book> 상위 요소

ancestor::book[author][1]

컨텍스트 노드의 가장 가까운 <book> 상위 요소이며 이 <book> 요소에는 <author> 요소가 자식으로 포함되어 있습니다.

ancestor::author[parent::book][1]

현재 컨텍스트의 가장 가까운 <author> 상위 요소이며 이 <author> 요소는 <book> 요소의 자식입니다.

 

통합예제

다음 XPath 식을 사용하여 통합 연산에 대해 알 수 있습니다.

x | y/x

다음 XML 파일에서 값이 green 또는 blue인 <x> 요소를 모두 선택합니다.

 

XML 파일(data1.xml)

 

<?xml version='1.0'?>
<?xml-stylesheet type="text/xsl" href="union.xsl"?>
<root>
   <x>green</x>
   <y>
      <x>blue</x>
      <x>blue</x>
   </y>
   <z>
      <x>red</x>
      <x>red</x>
   </z>
   <x>green</x>
</root>


XSLT 파일(union.xsl)

 

<?xml version='1.0'?>
<xsl:stylesheet version="1.0"
      xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:template match="root">
   <xsl:for-each select="x | y/x">
      <xsl:value-of select="."/>,
      <xsl:if test="not(position()=last())">,</xsl:if>
   </xsl:for-each>
</xsl:template>

</xsl:stylesheet>


서식이 지정된 출력

green,blue,blue,green

프로세서 출력

<?xml version="1.0" encoding="UTF-16"?>green,blue,blue,green