728x90
반응형

이번엔 350점인 8번 문제를 풀어보도록 하자.

첫 화면은 다음과 같고 view-source를 클릭해 소스코드를 확인해보도록 하자.

<?php
  include "../../config.php";
  if($_GET['view_source']) view_source();
?><html>
<head>
<title>Challenge 8</title>
<style type="text/css">
body { background:black; color:white; font-size:10pt; }
</style>
</head>
<body>
<br><br>
<center>
<?php
$agent=trim(getenv("HTTP_USER_AGENT")); #클라이언트의 웹브라우저 환경을 가져온다.
$ip=$_SERVER['REMOTE_ADDR']; # 사이트에 접속한 사용자 iP를 $ip에 넣는다.
if(preg_match("/from/i",$agent)){ # agent에 from 문자가 있으면 Access Denied! 출력
  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")); # $count_ck 변수에 쿼리 값을 저장
if($count_ck[0] >= 70){ mysqli_query($db,"delete from chall8"); } # 만약 $count_ck(id 컬럼 개수)가 70개 이상이면 "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){ # $ck 변수값이 존재하면
  echo "hi <b>".htmlentities($ck[0])."</b><p>";
  if($ck[0]=="admin"){ # $ck[0] 값이 admin이면
    mysqli_query($db,"delete from chall8"); # chall8 테이블의 모든 데이터 삭제
    solve(8); # 문제 해결
  }
}

if(!$ck){ # 만약 $ck 변수값이 존재하지 않으면
  $q=mysqli_query($db,"insert into chall8(agent,ip,id) values('{$agent}','{$ip}','guest')") or die("query error"); # insert 쿼리 실행
  echo("<br><br>done!  ({$count_ck[0]}/70)");
}
?>
<a href=./?view_source=1>view-source</a>
</body>
</html>

문제를 해결하기 위해서는 $ck[0]=="admin"이면 된다는 것을 확인할 수 있다.

 

처음에는 "select id from chall8 where agent='".addslashes($_SERVER['HTTP_USER_AGENT'])." 쿼리를 실행하지만

HTTP_USER_AGNET에 들어있는 변수값이 정상적인 쿼리가 아니므로 $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)");" 쿼리가 실행되게 됩니다.

 

그럼 여기에서 문제를 풀기 위해서는 INSERT 구문을 통해 id가 admin을 주입시킬 수 있다면 문제를 해결 할 수 있을 것입니다.

 

쿼리문 : as1234', '1', 'admin'), ('as123

 

다음과 같은 쿼리문을 헤더의 User-Agent에 주입시켜 보기로 하자.

우선, Burp Suite를 이용해서 Reqeust 헤더를 수정한다.

그 후 페이지 새로고침 후 똑같이 Burp Suite를 이용하여 User-Agent 부분에 insert했던 as1234 값을 넣어 전달하게 되면 문제가 풀리는 것을 확인할 수 있다.

 

 

※ 추가 학습 내용

trim() 함수 : 이 함수는 문자열 의 맨 앞과, 맨 뒤 의 여백을 제거한다.

preg_match() 함수 : PHP에서는 preg_match함수를 이용해서 정규식 표현을 작성한다.

첫번째 인자 : 정규표현식 작성 / 두번째 인자 : 검색 대상 문자열 / 세번째 인자 : 배열 변수 반환, 패턴 매치에서 매칭된 값을 배열로 저장

예시)

<?php
$text = 'My name is Tom';
$reg = preg_match('/\btom\b/i',$text,$matches);
var_dump($matches);
?>

결과)

array(1) { [0]=> string(3) "Tom" }

 

getenc() 함수 : 함수의 인자로 오는 변수에 따라, 해당되는 환경 변수값을 알려주는 역할

REMOTE_ADDR : 웹사이트를 접속한 컴퓨터의 IP Address
HTTP_USER_AGENT : 웹사이트를 접속한 컴퓨터의 웹브라우저 정보

예시)

<?PHP
$ip_address = getenv(REMOTE_ADDR);
$browser_info = getenv(HTTP_USER_AGENT);

echo("접속자 IP Address : $ip_address <br>");
echo("접속자 브라우저 정보 : $browser_info");
?>

접속자 IP Address : 127.0.0.1
접속자 브라우저 정보 : Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)

htmlspecialchars() 함수 : 문자열에서 특정한 특수문자를 HTML 엔티티로 변환한다. 이 함수를 사용하면 악성 사용자로부터 XSS 공격을 방지할 수 있다.

 

addslashes() 함수 : 어떤 문자열을 데이터베이스의 필드값으로 저장하기 전에 사용되는 함수로, 만약 그 문자열에 특수문자(' ," ,\ )문자가 포함되어 있다면 문자앞에 역슬래시(\)를 붙이는 역할을 한다. 그렇게 되면 특수 문자에 역슬래시가 붙어서 데이터베이스의 필드값으로 저장되면 특수 문자가 아닌 하나의 문자로 인식되어 저장된다. 만약 addslashes()함수를 사용하지 않으면 데이터베이스의 필드값에 저장되는 문자가 특수 문자로 인식되어 오류를 일으키거나 잘못된 결과를 나타낼 수 있다.

그와 반대로 사용하는 stripslashes()함수는 역슬래시를 떼어내는 작업이다.

 

 

728x90
반응형

'CTF & WarGame > webhacking.kr' 카테고리의 다른 글

[webhacking.kr] 10번 문제  (0) 2020.03.02
[webhacking.kr] 9번 문제  (0) 2020.03.01
[webhacking.kr] 7번 문제  (0) 2020.02.28
[webhacking.kr] 6번 문제  (0) 2020.02.27
[webhacking.kr] 5번 문제  (0) 2020.02.27

+ Recent posts