[WARGAME][webhacking.kr] old-7

jckim22·2022년 11월 15일
0

[WEBHACKING] STUDY (WARGAME)

목록 보기
71/114
post-thumbnail

아래는 서버 코드이다.

<?php
  include "../../config.php";
  if($_GET['view_source']) view_source();
?><html>
<head>
<title>Challenge 7</title>
</head>
<body>
<?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);
}
?>
<a href=./?view_source=1>view-source</a>
</body>
</html>

코드를 해석하자면 일단 GET으로 val의 값을 받는다.
그리고 눈에 띄는 것은 전에 수도 없이 봤던 정규식이다.
무엇 무엇을 필터링 하고 있는지 확인한다.
dbconnect를 보고 드디어 sql인젝션 문제임을 확신했다.

rand 함수로 5개 중 하나의 쿼리를 실행하는데 이게 무슨 의미이고 왜 있는지 이해가 안됐다.

그 후 $data에 row들을 담고 첫 row로 조건식을 판별한다.
만약 첫 row가 1,2가 아니면 query error를 출력하고
1이면 아무튼 실패다.
첫 row를 2로 만들어야한다.

이번에도 무수히 많은 뻘짓을 했다.

아래 사진들을 제외한 삽질이 훨씬 많다.

먼저 val에 4를 넣었더니 역시나 query error가 떴다.
1,2가 아니기 때문이다.

정규식에서 from을 필터링하고 있길래 아래서 해본 결과 역시 디나이 당했다.

혹시 1을 하고 닫는 괄호 후 뒤를 주석처리 하면 lv=(1)#이 되지 않을까 상상했다.
아래처럼 하고

rand이기때문에 여는 괄호가 하나여야 했다 그래서 새로고침을 열심히 했지만 아래와 같이 쿼리가 입력이 안된 nice try만 떴다.

아마도 주석에서 문제가 있었을 거라고 생각한다.


혹시나 하는 마음에 2를 해봤지만 2역시 정규식에서 필터링 되고 있다는걸 깜빡했다.


아래처럼 sql에서는 0x를 문자열로 인식하는걸 알고 필터링 되고 있는 from을 16진수로 변환했다.
허나 변환한 숫자에도 2가 있었다 ..

아래에서 대문자도 해봤지만 당연히 되지 않았다.



그러던 와중에 위처럼 그나마 할만했던 like를 써봤더니 1로 인식은 되었다.
근데 원래 쿼리와 뭐 다를게 없었다. 결국 2를 우회해야 했기 때문에..

아래처럼 char(50)으로 2를 우회했다.


근데 위처럼 쿼리에러가 떴다.
쿼리에러라는 건 row가 발견되지 않은거고 결과 값이 없다는 건데 말이 안되었다.
char(50)==2가 확실한데 뭐가 문제인지 몰라서 이후 계속된 삽질을 계속했다.

그러던 중 떠오른 것이 애초에 chall7 테이블에 lv중 2라는 것은 존재하지 않았던 것이 아닐까라는 생각이었다.

나는 테이블에서 계속 2를 가져오려고 했는데 내가 2가 있는 테이블을 만들면 되는 것이었다.

그래서 생각난 것이 이전에 계속적으로 썼던 union이다.
전자 쿼리의 row들에 아래에 있게 되는데 드림핵 문제에서 전자의 row를 0으로 아무것도 없게 하고 union을 사용해서 후자의 쿼리의 내용을 1번째 row로 만들었던 워게임이 생각났다.

그럼 내가 할 것은 전자를 검색결과가 없게 하고 후자에 select char(50)으로 2를 row에 가져오면 되는 것이었다.

그래서 짠 페이로드는 아래와 같다.

3)union(select(char(50))

3)으로 괄호를 닫아주고 union으로 char(50)을 row로 가져오는 것이었다.
다만 괄호가 하나일 때 기준이었기 때문에 rand가 1일 때를 이용해야해서 새로고침이 필요했다.
위에서 계속 했던 것처럼 공백은 괄호로 우회했다.

아래처럼 익스플로잇하게 되면

아래와 같이 flag를 얻을 수 있다.

profile
개발/보안

0개의 댓글