본문 바로가기

보안지식/주통기반

[주통기반] 공격 시나리오 정리(XPath 인젝션)

안녕하세요 이번에는 주통기반 7번인 XPath 인젝션에 대해 공부해보겠습니다.

 

XPath 인젝션은 SQLi 와 매우 유사 합니다. 예를 들어 로그인을 할 때 ' and '1'='1 을 입력해서

비밀번호가 틀려도 들어가지는 경우가 SQLi라 하지만 XPath 공격 기법 중 하나입니다.

 

 

-XPath(XML Path Language) ?

 

우선적으로 저희는 XML에 대해 알 필요가 있습니다.

 

XML은 모바일 프로그래밍 하시다보면 자주 접하게 됩니다.

 

XML은 사용자가 자신만의 태그를 정의해서 데이터를 구조화할 수 있고 뎅터를 계층적으로 표현할 수 있는 형식입니다.

주로 데이터의 구조와 의미를 설명하는 데 사용되며, 웹에서 데이터를 교환하는 데에도 자주 사용된다고 합니다.

 

예시를 들어 볼게요

 

<bookstore>
  <book>
    <title>Introduction to XML</title>
    <author>John Doe</author>
    <price>29.99</price>
  </book>
  <book>
    <title>Web Development Basics</title>
    <author>Jane Smith</author>
    <price>19.95</price>
  </book>
</bookstore>

 

만약 이렇게 XML 코딩을 하면 <bookstore>는 최상위 요소이고 <book>은 <bookstore>의 하위 요소 입니다.

그리고 안에 <title>, <author>, <price>은 <book>의 하위 요소 이겠죠.

 

XPath은 XML 문서의 특정 요소를 선택하고 탐색하기 위한 언어입니다.

이걸 이용해 XML 문서의 경로를 지정해서 원하는 요소를 검색하고 데이터를 추출할 수 있습니다.

 

기본 문법은

'/' : 최상위 요소를 선택합니다.

'//' : 모든 하위 요소를 선택합니다.

'element' : 해당 요소를 선택합니다.

'element[@attribute]' : 특정 속성을 가지는 요소를 선택합니다.

'element/text()' : 요소의 텍스트 값을 선택합니다.

 

예를 들어 저희가 방금 짠 XML에 Introduction to XML의 가격을 선택하고 싶다면

 

/bookstore/book[title='Introduction to XML']/price/text() 입니다.

 

bookstore 밑에 book에 있는 제목 Introduction to XML을 찾은 다음 price을 선택하고 text() 값으로 반환하는 겁니다.

결과는 29.99 이겠죠!

-XPath 기본 명령어

명령어 설명
/ 최상위 노드
// 현재 노드로부터 모든 노드 조회
* 모든 노드 조회
. 현재 노드
.. 상위 노드 접근
parent 현재 노드의 부모 노드
child 현재 노드의 자식 노드
[ ] 조건문
node( ) 현재 노드로부터 모든 노드 조회

이 뿐만 아니라 count(../child::*)=[숫자] 이용해 노드 수를 조회 가능하고

string-length() 통해 문자열의 길이 알 수 있으며 name() 이용해 이름을 알 수 있습니다.

 

count(../child::*) 은 count(../*) 이랑 같습니다.

 

 

그럼 현재 부모 요소의 길이를 알고 싶다면 string-length(name(parent::*))=[숫자] 이렇게 하면 알 수 있습니다.

parent::* 은 .. 이랑 같다고 보시면 됩니다!

 

 

 

이걸 이용해 한 번 인젝션 공격을 해보겠습니다.

저희가 Blind SQL injection과 매우 흡사하니 쉽게 이해하기 쉬우실겁니다.

 

실습은 root me 에서 하겠습니다.

 

가장 쉬운겁니다.

 

들어가서 멤버에 누가 있나 봐보니

 

아하

 

john이 administrator 이라고 나오네요. 그럼 일단 로그인에 ' or '1'='1을 넣어봐서

XPath가 통할지 확인을 해봅니다.

 

 

로그인을 하니?

 

아하.. 바로 되긴하는 데 steve로 되어있네요.

 

아마 or 구문으로 그냥 강제 참으로 만들어서 데이터 맨위 에 있는 걸 꺼냈더니 steve 나온 걸 겁니다.

 

쉬운 방법이 있긴 합니다.

 

ID에 John을 참으로 만들고

 

비밀번호에 아무 값이나 넣어서 보내보는 겁니다.

 

 

이러면

 

그럼 John은 참이여서 ID는 John이 들어가지게 되고 비밀번호도 or 구문 때문에 그냥 들어가지게 되면서

 

 

 

쉽게 탈환이 가능합니다.

 

____________________________________________________________________________________________

만약 위 처럼 쉬운 방법이 안되면 일일이 비교 하면서 찾는 방법이 있습니다!

프록시 툴 통해 Blind injection을 하겠습니다.

 

먼저 참 과 거짓의 응답 메시지 차이점을 보겠습니다.

 

참인 경우

 

거짓인 경우

 

거짓인 경우 Not connected라고 알려주네요!

 

그럼 이제 공격 구문을 만들어 보겠습니다.

 

substring을 이용해 한 글자씩 알아 볼 수 있습니다. 그럼 부모 요소 이름 부터 알아야 되겠죠?

 

' or substring(name(parent::*),1,1)='a' or ' 이러면 부모 요소의 1번째 글자가 a인 경우 참이니 되야 되겠죠?

 

거짓이네요!

 

' or substring(name(parent::*),1,1)>50 or ' 처럼 등호로 크고 작고 기법 이용해 2진 탐색 알고리즘을 이용하겠습니다.

 

https://mynameisarke.tistory.com/33

 

[노말틱 모의 해킹 취업반 5주차 해킹과제] Blind SQLi

안녕하세요! 오늘은 SQL 인젝션 공격 중 하나인 Blind SQLi을 공부해 보겠습니다. 일단 이 Blind SQLi는 어디서 공격을 할까요? -공격 위치? DB결과가 화면에 안 나오는 곳. Error based 나오는 곳 ALL , 사실 S

mynameisarke.tistory.com

여기서 이진 탐색 기법으로 비슷한 인젝션 공격한게 있습니다 참고하시면 좋아요!

 

너무.. 노가다입니다 파이썬을 이용해 코드을 작성해 자동화 기법으로 보내면 훨씬 편합니다.

 

 

어쨋든 제가 알아보니

 

' or substring(name(parent::*),1,1)='d' or ' (첫 번째 글자는 d)

' or substring(name(parent::*),2,1)='a' or ' (두 번째 글자는 a)

.

.

.

.

부모의 노드은 database을 알아 냈습니다.

 

좋아요!

그리고 현재 노드을 알아 보겠습니다.

parent을 child로 바꾸기만 하면 됩니다.

 

' or substring(name(../child::*),1,1)='d' 

 

쭉쭉 찾아보니 user이 나왔습니다.

 

 

그다음에 자식 노드도 알아야 되겠죠?

 

그런데 자식의 노드의 수가 여러개 인 경우가 대부분 입니다.

그래서 저희는 우선 자식의 요소가 몇 개 있는지 알아 보겠습니다.

 

 

count(child::*)=5 하니 참이 나왔습니다!

그럼 자식 노드 수는 5개라는 뜻이죠.

 

자식 수는 5개

 

그럼 이제 첫 번째 자식 부터 보겠습니다.

 

[postion()=[숫자]] 이걸 이용해 몇 번째 자식을 선택할 수 있습니다.

 

' or substring(name(child::*[postion()=[몇 번째 자식]]),[숫자],1)>[문자 아스키 코드(십진법)] or ' 구문은 이러하겠네요!

 

일일히 대입해서 찾아보시면

 

 

 

 

첫 번째 자식 : userid

 

 

 

두 번째 username

 

 

 

세 번째 password

 

 

 

 

이제 John의 패스워드를 찾으면 되겠네요!

 

일단 John이 user에 1번째에 있는지 2번째에 있는지 확인 해보겠습니다.

 

2번째가 John이네요!

 

그럼 이제 password을 알아 내면 되겠네요.

 

' or substring(string(/database/user[2]/password),1,1)='6' or ' (첫글자는 6 인걸 알 수 있습니다.)

.

.

.

.

쭉 하시다보면... 총 비밀번호가 24글자 이에요.

꼭 함수나 파이썬 코드로 하시는 걸 추천 드려요.

 

저는 예전에 만든 파이썬 코드을 변형해서 했습니다.

 

https://mynameisarke.tistory.com/41

 

[노말틱 모의 해킹 취업반 6주차 해킹과제] Blind SQL Injection Python(POST방식)

안녕하세요! 오늘은 Blind SQL Injection을 했을 때 저희가 일일이 문자 하나하나 넣어서 확인했었잖아요? 이제 그걸 자동화하기 위해 파이썬으로 코드를 짜서 만들어보겠습니다. 일단은 import requests

mynameisarke.tistory.com

여기에 있는 함수에 변형을 했습니다.

 

6FkC67ui8njEepIK5Gr2Kwe

답은 이겁니다.

 

답은 맞는데 로그인은 안되네요!

 

 

_________________________________________________________________________________________

 

더 쉬운 방법이 있긴 합니다.

 

ID에 John을 참으로 만들고

 

비밀번호에 아무 값이나 넣어서 보내보는 겁니다.

 

 

이러면

 

그럼 John은 참이여서 ID는 John이 들어가지게 되고 비밀번호도 or 구문 때문에 그냥 들어가지게 되면서

 

 

 

쉽게 탈환이 가능합니다.