하지만 실제 악성 콘텐츠를 업로드하거나 악성콘텐츠를 활용하여 공격을 하는 경우 서버나 사용자에게 막대한 피해를 줄 수 있기 때문에 실제 공격하는 방식이 아닌 위험하지 않은 코드를 사용하여 테스트하는 경우가 많으며 SQL Injection, XSS, 파일 업로드 등의 취약점을 조치해놓은 경우 방어할 수 있는 가능성이 높아집니다.
하지만 조치하지 않은 경우 게시판과 자료실로 감염가능성도 있지만 메일과 메신저 등으로 악성 콘텐츠에 감염되는 경우도 존재하므로 사용자가 인식하고 조심하는 것이 매우 중요합니다.
물론 조치한 경우에도 공격자는 우회로를 찾아 공격하는 경우가 존재하므로 인식하고 사전에 조심하는 것이 가장 중요합니다.
마우스 우클릭을 하면 위와 같이 나다나는 것을 확인할 수 있는데 '페이지 소스 보기'를 누르거나 F12를 눌러 소스를 확인하면 위와 같이 PW가 노출되거나 서버 내 파일 업/다운로드 경로 혹은 관리자 페이지 경로 등 서버나 사용자의 중요정보를 노출하는 경우에 정보 노출 취약점으로 확인합니다.
2. 에러 페이지를 통한 정보 노출
위와 같이 에러페이지 내 서버의 절대 경로를 노출하거나 서버 버전 정보 노출 등으로 2차 공격에 사용될 수 있습니다.
3. 패킷 내 정보 노출
위 그림과 같이 파라미터 값을 잡았을 경우 패킷 내 서버 정보를 노출하는 경우 취약점으로 확인합니다.
XML Path Language를 의미하며 XML 문서의 특정 요소나 속성에 접근하기 위한 경로를 지정하는 언어입니다.
또한, XPath는 W3C 표준 권고안으로, XSLT와 XPointer에 주로 사용되며 XML DOM에서 노드를 검색할 때에도 사용이 가능합니다.
XPath는 XML 문서를 노드 트리로 모델링하여 경로 표현식(Path Expression)을 통해 XML 문서의 노드 또는 노드 집합을 선택합니다.
XPath 노드들은 아래와 같이 총 7개로 구성되어 있으며, XPath의 다양한 함수를 활용하여 접근 가능합니다.
XPath nodes
root nodes
element nodes
text nodes
attribute nodes
namespace nodes
processing instruction nodes
nomment nodes
XPath injection
입력값에 대한 필터링이나 보안 사항이 없을 때, 공격자가 XPath 쿼리문 생성을 위한 문자열을 삽입하면 개발자가 의도하지 않은 문자열을 서버에 전달하여 쿼리문의 의미를 왜곡시키거나 그 구조를 변경하고 임의의 쿼리를 실행하여 인가되지 않은 데이터를 열람할 수 있는 공격입니다.
XPath 명령어
명령어
설명
/
최상위 노드
//
현재 노드로부터 모든 노드 조회
*
모든 노드 조회
.
현재 노드
..
상위 노드 접근
parent
현재 노드의 부모 노드
child
현재 노드의 자식 노드
[ ]
조건문
node( )
현재 노드로부터 모든 노드 조회
공격 방법
(XPath injection의 공격 방법은 rootme를 활용하여 설명해보도록 하겠습니다.)
처음 들어가면 볼 수 있는 페이지입니다.
위에서 확인할 수 있는 Members와 Login페이지를 들어가 보도록 하겠습니다.
로그인 페이지는 위의 사진처럼 구성되어 있습니다.
이제 Members를 통해 사용자 목록을 확인하도록 하겠습니다.
Members를 확인해본 결과 John이 관리자 ID인 것으로 확인됩니다.
그럼 로그인을 injection 해보도록 하겠습니다.
위처럼 ' or '1'='1을 삽입하여 접근하면 Steve에 로그인이 되는 것을 확인할 수 있는데 이를 통해 Steve가 1번 ID인 것을 유추할 수 있습니다. 이를 통해 John이 2번 ID일 가능성도 알 수 있습니다.
Steve를 알아내기 위해 Blind injection을 활용하여 공격해보도록 하겠습니다.
우선 Blind injection을 하기 위해 참, 거짓을 알 수 있는 부분을 찾아보도록 하겠습니다.
위의 사진처럼 로그인 실패 시에 Wrong credentials라는 문구가 생성되는 것을 확인할 수 있습니다.
원활한 진행을 위해 Burp suite의 Repeater를 활용하여 진행해보겠습니다.
위의 사진은 예제가 참일 경우 Response 되는 내용입니다.
위의 사진은 예제가 거짓인 경우 Response되는 내용입니다.
먼저 AND와 OR구문에 대해 알아야 하는데 AND구문은 두 가지의 명제가 참일 경우만 참이지만 OR구문은 두가지의 명제 중 하나만 참이더라도 명제가 참이 됩니다.
(SQL 인젝션과 공격 방법은 매우 유사합니다.)
우선 과정 중 알게 된 ID를 활용하여 현재 노드의 노드 수가 몇 개가 존재하는지 알아보겠습니다.
'or count(../child::*)=3 or'
앞에서 확인한 것과 마찬가지로 '거짓 or count(../child::*) or 거짓'인 형태로 명제를 주입했습니다.
위의 명제에서 삽입한 명제가 거짓이라면 Wrong credentials가 나올 것이고 참이라면 정상적인 로그인이 될 것입니다.
주입한 명제는 '현재 노드에서 상위 노드에서의 자식 노드가 몇 개인가?'를 묻는 명제입니다.
3을 주입했고 참이 나왔으니 현재 노드에서 노드수는 세 개인 것으로 확인된 것입니다.
이후 부모 노드의 이름을 알아보도록 하겠습니다.
' or string-length(name(parent::*))=8 or '
위의 명제는 string-length는 길이를 알아보기 위한 문구입니다.
name은 이름, parent는 부모 노드로 즉, 부모 노드 이름의 길이를 알아보기 위한 구문입니다.
부모 노드 이름의 길이는 8로 확인되었습니다.(Boolean Based SQL injection과 매우 흡사한 공격 방식입니다.)
이제 이름을 찾아볼 차례입니다.
부모 노드의 첫 번째 글자
부모 노드의 두 번째 글자
부모 노드의 세 번째 글자
부모 노드의 네 번째 글자
부모 노드의 다섯 번째 글자
부모 노드의 여섯 번째 글자
부모 노드의 일곱 번째 글자
부모 노드의 여덟 번째 글자
부모 노드의 이름 확인
' or substring(name(parent::*),[알고 싶은 문자의 순서],1)='[대조하려는 문자]' or '
substring은 문자열을 반환하는 구문입니다. 전와 같은 문자열을 대조하여 알아내는 구문입니다.
' or string(name(parent::*))='[확인하려는 이름]' or '
이후 이름을 확인하는 구문입니다.
위의 과정으로 알 수 있는 부모 노드의 이름은 'database'입니다.
위의 과정을 다 올려둔 이유는 순서에 따라 입력하는 구문을 말씀드리기 위해서 올려봤습니다.
이제는 현재 노드의 이름을 알아보겠습니다.
' or substring(name(../child::*),[알고싶은 문자 순서],1)='[대조하려는 문자]' or '
위와 같은 구문으로 문자를 알아볼 수 있습니다. 확인된 현재 노드의 이름은 'user'입니다.
하지만, 여기에서 중요한 것은 '현재의 노드가 과연 첫 번째 노드인가?'입니다.
여기에서 정확이 확인해볼 수 있는 구문은 'position'을 써서 확인해주는 것입니다.
그럼 구문은
' or substring(name(../child::*[position()=[확인하려는 노드의 순서]]),[알고싶은 문자 순서],1)='[대조하려는 문자]' or '
위와 같이 확인해보면 노드 순서를 지정하여 확인할 수 있습니다.
그럼 현재 노드에서 자식 노드의 수와 이름을 알아보도록 하겠습니다.
자식 노드의 수
첫 번째 자식 노드의 이름
두 번째 자식 노드의 이름
세 번째 자식 노드의 이름
' or name(child::*[position()=[확인하려는 노드의 순서]])='대조하려는 문자' or '
위에서 확인 가능한 것은 현재 노드에서의 자식 노드는 userid, user, password가 확인되었으며 Members에서 확인한 내용을 토대로 나머지 두 가지는 email과 account type이라는 것을 유추할 수 있습니다.
그럼 현재 노드의 username과 현재 노드가 1번이 맞는지 확인해보겠습니다.
현재 노드의 username
첫 번째 user노드의 username
' or string(./username)='Steve' or '
' or string(/database/user[1]/username)='Steve' or '
현재의 노드에서 첫 번째는 Steve였다는 것을 확인할 수 있습니다.
그럼 현재 노드의 노드 수가 3이라는 것을 확인했으니 다른 노드를 알아보겠습니다.
현재 노드에서 다른 세 개의 노드들의 이름도 'user'라는 것을 확인했습니다.
그럼 유추할 수 있는 것은 첫 번째 username는 'Steve', 두 번째는 'John', 세번째는 'Eric'이라는 것을 유추할 수 있습니다.
그럼 관리자 ID인 John을 알아보겠습니다.
username 확인
password 길이 확인
위의 과정을 통해 두번째 user는 'John'이라는 것을 알 수 있으며 password의 길이는 24라는 것을 알 수 있습니다.
이제 bruteforce공격을 이용하여 알 수 있습니다.
위와 같은 방식으로도 시도해 볼 수 있으며 substring을 활용해서 한 글자씩 알아내는 방법도 있습니다.
하지만 24자나 되는 password를 알아내는 것을 많은 시간이 걸리는 것이 사실입니다.