본문 바로가기
Write Up/webhacking.kr_old

Webhacking.kr Challenge(old)_7번문제

by 비원(Be one) 2020. 5. 31.
반응형

여러분 안녕하세요. 세이버입니다.

 

이번 시간에는 Webhacking.kr Challenge old 7번 문제를 풀어보도록 하겠습니다.


1. 문제 파악하기

7번 문제를 클릭해봅시다.

옆에 데이터베이스 표시가 있는 걸로 보아 데이터베이스 관련 문제인거 같습니다. (SQL 인젝션 냄새가...)

 

7번 문제를 클릭하면 Admin page라는 문구와 버튼, 링크가 있습니다.

 

auth 버튼을 클릭하면 Access-Denied! 알림창이 뜹니다.

 

view-source 링크를 클릭해보면 html과 php 코드가 보입니다.

 

코드 중간에 sql코드가 있는걸로 보아 SQL 인젝션이 확실해졌습니다.

 

노가다의 시작?

SQL인젝션에 관한 설명을 아래 링크를 참고하시기 바랍니다.

SQL Injection 공격 : https://poci.tistory.com/49

 

SQL Injection 공격

SQL Injection 공격은 웹해킹에서 가장 많이 쓰이는 공격 기법 중 하나입니다. SQL와 Injection(주입하다)의 합성어로, SQL를 주입하는 공격이라는 의미입니다. SQL Injection 공격은 아이디, 비밀번호를 적��

poci.tistory.com

 

2. 코드 해석하기

php 코드를 해석해야 문제를 해결할 수 있을 거 같습니다.

 

<?php
$go=$_GET['val'];
if(!$go) { echo("<meta http-equiv=refresh content=0;url=index.php?val=1>"); }
echo("<html><head><title>admin page</title></head><body bgcolor='black'><font size=2 color=gray><b><h3>Admin page</h3></b><p>");
if(preg_match("/2|-|\+|from|_|=|\\s|\*|\//i",$go)) exit("Access Denied!");
$db = dbconnect();
$rand=rand(1,5);
if($rand==1){
  $result=mysqli_query($db,"select lv from chall7 where lv=($go)") or die("nice try!");
}
if($rand==2){
  $result=mysqli_query($db,"select lv from chall7 where lv=(($go))") or die("nice try!");
}
if($rand==3){
  $result=mysqli_query($db,"select lv from chall7 where lv=((($go)))") or die("nice try!");
}
if($rand==4){
  $result=mysqli_query($db,"select lv from chall7 where lv=(((($go))))") or die("nice try!");
}
if($rand==5){
  $result=mysqli_query($db,"select lv from chall7 where lv=((((($go)))))") or die("nice try!");
}
$data=mysqli_fetch_array($result);
if(!$data[0]) { echo("query error"); exit(); }
if($data[0]==1){
  echo("<input type=button style=border:0;bgcolor='gray' value='auth' onclick=\"alert('Access_Denied!')\"><p>");
}
elseif($data[0]==2){
  echo("<input type=button style=border:0;bgcolor='gray' value='auth' onclick=\"alert('Hello admin')\"><p>");
  solve(7);
}

$go=$_GET['val'];

이 부분에서 val값을 GET방식으로 받아서 go변수에 대입합니다.

 

url 뒤에 val값이 있습니다. 이 값을 가져와 go변수에 대입합니다.

 

if(preg_match("/2|-|\+|from|_|=|\\s|\*|\//i",$go)) exit("Access Denied!");

이 부분에서는 go변수의 값을 필터링합니다.

SQL인젝션에 필요한 부분들이 필터링 되므로 살짝 난이도가 있습니다.

 

$rand=rand(1,5);
if($rand==1){
  $result=mysqli_query($db,"select lv from chall7 where lv=($go)") or die("nice try!");
...
if($rand==5){
  $result=mysqli_query($db,"select lv from chall7 where lv=((((($go)))))") or die("nice try!");
}

1에서 5까지 랜덤한 값으로 sql쿼리를 생성합니다.

 

if(!$data[0]) { echo("query error"); exit(); }
if($data[0]==1){
  echo("<input type=button style=border:0;bgcolor='gray' value='auth' onclick=\"alert('Access_Denied!')\"><p>");
}
elseif($data[0]==2){
  echo("<input type=button style=border:0;bgcolor='gray' value='auth' onclick=\"alert('Hello admin')\"><p>");
  solve(7);
}

쿼리의 이 1이면 Access_Denied 알림을 띄우고, 값이 2면 문제가 해결됩니다.

 

즉, go변수의 값(val의 값)이 2가 되어야 문제가 해결됩니다.

하지만 2,와 +, -가 필터링되어 1+1, 5-3과 같이 사칙연산으로 2를 만들 수 없습니다.

대신 2는 아스키코드로 50이므로 char(50)을 이용하면 2를 만들 수 있습니다.

 

3. SQL인젝션

다행히 GET 방식이기 때문에 url값만 바꿔주면 되므로 BurpSuite는 굳이 쓰지 않아도 됩니다.

 

char(50)을 넣었지만 query error가 뜹니다.

char(50)을 넣으면 select lv from chall7 where lv=(char(50))이 되므로 괄호 처리를 안했기 때문입니다.

 

그래서 0)union(select(char(50))을 넣었습니다.

그러면 select lv from chall7 where lv=(0)union(select(char(50)))이 되므로 괄호를 처리할 수 있습니다.

 

그런데 nice try!가 뜹니다.

그 이유는  0)union(select(char(50))은 rand의 값이 1인 경우에만 해결되기 때문입니다.

 

그래서 rand의 값이 1이 될때까지 새로고침해주면 어느순간 해결됩니다.

 

새로고침 연타하느라 이미 푼걸로 뜨네요...

 


오늘도 수고하셨습니다.

 


정리

-php를 해석한 후 필터링을 피해 SQL 인젝션을 한다.


강의가 유익하셨거나 마음에 드셨으면 구독과 좋아요, 댓글 부탁드립니다.

궁금하신 점이나 질문은 댓글이나 메일을 남겨주세요.

 

poci5003@gmail.com

 

반응형