road23 2022. 8. 15. 12:59

bwapp XML/XPath injection


XML/XPath Injection (Login Form)

Low

 

시험 삼아 해보기 위해 login에 test를 password에 pass를 입력하고 로그인 버튼을 누른다.

그러면 아래의 사진과 같은 메세지가 뜨는 것을 확인할 수 있다.

XPath 명령어를 살펴보면, 로그인 페이지는 아이디와 비밀번호를 모두 AND 연산으로 호출하는 것을 알 수 있다.

그렇기 때문에 login에 ' or 1=1 or '와 같은 코드가 들어가야 한다.

login에 ' or 1=1 or '을 입력하고 로그인 버튼을 누르면 위와 같이 Welcome Neo라는 메세지가 뜨는 것을 확인할 수 있다.

 

노드의 개수를 알아내기 위해 count() 함수를 사용한다.

로그인 폼에 neo' and count(../child::*)=1 or 'a'='b 를 입력해서 현재 노드가 속한 부모노드의 자식노드가 1개가 맞는지 확인한다.

위의 명령어를 입력하고 로그인 버튼을 누르면 아래와 같이 invalid credientials! 라는 메세지가 뜨면서 자식노드가 1개가 아니라는 것을 확인할 수 있다.

수를 늘려가면서 입력하다 보면, (neo' and count(../child::*)=6 or 'a'='b 를 입력했을 때 아래와 같이 메세지가 뜨는 것을 통해 현재 노드가 속한 부모 노드의 자식 노드가 6개인 것을 알아낼 수 있다.

 

이제  부모 노드의 이름을 확인하기 위해 로그인 폼에 neo' and string-length(name(parent::*))=1 or 'a'='b 를 입력하면 부모 노드의 이름의 길이가 몇 글자인지 알 수 있다.

neo' and string-length(name(parent::*))=1 or 'a'='b 를 입력하고 로그인 버튼을 누르면 아래와 같은 메세지가 뜨는 것을 통해 부모 노드의 이름 길이가 1글자가 아닌 것을 알 수 있다.

위에서 했던 것처럼 수를 늘려가면서 입력하다 보면, neo' and string-length(name(parent::*))=6 or 'a'='b 을 입력했을 때 아래와 같은 메세지가 뜨는 것을 통해 부모 노드의 이름이 6글자인 것을 확인할 수 있다.

 

이제 부모 노드의 이름을 확인해가 위해 로그인 폼에 neo' and substring(name(parent::*),1,1)='a' or 'a'='b 을 입력한다.

1,1)='a'는 첫번째 글자가 a인지를 묻는 것이다. (1,1은 첫번째 글자부터 첫번째 글자까지를 묻는 것이므로 결국 첫번째 글자에 대해 묻고 있음을 알 수 있다.)

neo' and substring(name(parent::*),1,1)='a' or 'a'='b 를 입력했을 때 위와 같은 메세지가 뜨는 것을 통해 첫번째 글자가 a가 아니라는 것을 알 수 있다.

neo' and substring(name(parent::*),1,1)='b' or 'a'='b

neo' and substring(name(parent::*),1,1)='c' or 'a'='b

...

neo' and substring(name(parent::*),1,1)='h' or 'a'='b 까지 입력하다 보면 h를 입력했을 때 아래와 같은 화면이 뜨는 것을 통해 부모 노드의 첫번째 글자가 h라는 것을 알 수 있다.

이렇게 계속 입력하다 보면 부모 노드의 모든 자리의 글자를 알 수 있게 된다.

확인을 위해 neo' and substring(name(parent::*),1,6)='heroes' or 'a'='b 를 입력해서 부모 노드의 첫번째부터 여섯번째까지의 글자가 heroes인지 확인할 수 있는데, 결과가 아래와 같은 메세지가 뜨는 것을 통해 heroes가 맞음을 알 수 있다.

 

위의 명령어들을 이용해서 첫번째 자식 노드 이름을 찾아내고, 확인을 위해 neo' and substring(name(../child::*[position()=1]),1,4)='hero' or 'a'='b 를 입력해서 첫번째 자식 노드 이름이 hero가 맞는지 확인한다.

그러면 위와 같은 메세지가 뜨는데 이것을 통해서 첫번째 자식 노드의 이름이 hero인 것을 알 수 있다.

다른 자식 노드들도 확인해보면 모든 자식 노드들이 hero인 것을 알 수 있다.

 

이제 현재 노드의 자식 노드의 개수를 알아내기 위해서 neo' and count(/heroes/hero[1]/child::*)=1 or 'a'='b 를 입력하면 hero의 첫번째 자식 노드의 개수가 1인지를 알 수 있다. 위에서처럼 수를 늘려가며 입력하다 보면 hero의 자식 노드의 개수가 6개인 것을 확인할 수 있다.

 

자식 노드의 자식 노드 이름의 글자수를 구해기 위해 neo' and string-length(name(/heroes/hero[1]/child::*[position()=1]))=1 or 'a'='b 명령어를 입력한다. 위에서처럼 수를 늘려가다 보면 hero[1]의 첫번째 자식 노드의 길이가 2인 것을 확인할 수 있다.

 

 

이렇게 계속 입력하다 보면 hero[1] 안에 있는 자식 노드가 id, login, password, secer, movie, genre 인 것을 확인할 수 있다.


Medium, High

여기서는 공격이 먹히지 않는 것을 알 수 있다. xmli.php 파일을 확인해보면 xmli_check_1 함수가 적용되어 있는데, functions_external.php을 열어 이 함수를 확인해보면 입력값이 " "으로 대체되기 때문에 공격이 통하지 않는 것을 알 수 있다.


XML/XPath Injection (Search)

 

Action에서 Search를 누르면 xmli_2.php 페이지가 영화 제목을 리스트 형태로 출력하는 것을 확인할 수 있다.

SQL Injection 취약점을 찾아보기 위해 genre 변수에 작은따옴표를 넣어 입력한다.

그러면 위와 같이 XML과 관련된 경고 내용을 확인할 수 있다.

 

http://localhost/bWAPP/xmli_2.php?genre=%27%29]|//*|evil[%28%27&action=search 를 입력하면 아래와 같이 heroes 테이블에 존재하는 모든 사용자의 정보를 테이블 형태로 출력하는 것을 확인할 수 있다.