Wargame/Webhacking.kr

[Webhacking.kr] Old 18

핏디 2021. 7. 28. 00:55
SMALL

[문제]

 


[풀이]

<?php
  include "../../config.php";
  if($_GET['view_source']) view_source();
?><html>
<head>
<title>Challenge 18</title>
<style type="text/css">
body { background:black; color:white; font-size:10pt; }
input { background:silver; }
a { color:lightgreen; }
</style>
</head>
<body>
<br><br>
<center><h1>SQL INJECTION</h1>
<form method=get action=index.php>
<table border=0 align=center cellpadding=10 cellspacing=0>
<tr><td><input type=text name=no></td><td><input type=submit></td></tr>
</table>
</form>
<a style=background:gray;color:black;width:100;font-size:9pt;><b>RESULT</b><br>
<?php
if($_GET['no']){
  $db = dbconnect();
  if(preg_match("/ |\/|\(|\)|\||&|select|from|0x/i",$_GET['no'])) exit("no hack");
  $result = mysqli_fetch_array(mysqli_query($db,"select id from chall18 where id='guest' and no=$_GET[no]")); // admin's no = 2

  if($result['id']=="guest") echo "hi guest";
  if($result['id']=="admin"){
    solve(18);
    echo "hi admin!";
  }
}
?>
</a>
<br><br><a href=?view_source=1>view-source</a>
</center>
</body>
</html>

 

문제에서 제공하는 코드 중 가장 핵심은 php 코드에 있다.

코드를 분석해보면,

<?php
if($_GET['no']){
  $db = dbconnect();
  if(preg_match("/ |\/|\(|\)|\||&|select|from|0x/i",$_GET['no'])) exit("no hack");

-> no에 / 와 /, (), ||, &, select, from, 0x/ 를 삽입할 경우 필터링 되어 no hack이 출력된다.

  $result = mysqli_fetch_array(mysqli_query($db,"select id from chall18 where id='guest' and no=$_GET[no]")); // admin's no = 2
-> 입력 결과는 chall18 DB에서 id가 guest이고 no가 입력 값에 의해 정해진 값을 출력한다.
  if($result['id']=="guest") echo "hi guest";

-> id 가 guest면 hi guest를 출력한다.
  if($result['id']=="admin"){
    solve(18);
    echo "hi admin!";
  }

-> id가 admin이면 문제가 풀리면서 hi admin을 출력한다.
}
?>

더보기

preg_match('/대조할 문자/', '입력한 문자', $matches);

의 형태로 사용하면서 필터링 한다!

- 특수문자를 필터링 하고 싶다면 특수문자 앞에 \를 붙이면 됨!

- '/admin/'i 와 같이 i가 붙어 있는 것은 대소문자를 구분하지 않겠다는 뜻!

- match 자리에는 사용자가 설정한 값과 입력 값이 일치하는 경우 그 값을 $match에 배열 형태로 저장함

(문자열이 1개라도 검거되면 1반환, 아니면 0 반환)

 

+ 필터링 함수

str_replace -> 다른 문자로 바꿔줌

preg_replace -> 다른 문자로 바꿔줌

 

preg_match전에 

eregi() -> 비슷한 원리로 문자열 필터링(근데 NULL BYTE 취약점 존재해서 없어짐)

 

 

https://overcode.tistory.com/entry/HTML-Encoding-ReferenceURL-%EC%9D%B8%EC%BD%94%EB%94%A9%EC%9D%84-%EC%95%84%EC%8A%A4%ED%82%A4-%EB%AC%B8%EC%9E%90%EB%A1%9C-%EB%B3%80%ED%99%98

문제에서 admin의 no가 2라고 알려줬기 때문에 2를 입력하면 될 것 같지만 id는 guest로 고정되어 있기 때문에 SQL Injection 공격이 필요하다.

 

우선, no에 1을 입력하면 hi guest가 출력된다. (guest의 no은 1)

https://webhacking.kr/challenge/web-32/index.php?no=1 

 

공백과 ()를 모두 필터링하고 있어서 입력 창에 입력하니 모두 no hack이 출력되었다. 이에 GET 방식으로 파라미터를 보내면 flag를 획득할 수 있다.

 

그렇다면 단순히 2를 입력할 수 없으므로 guest로도 로그인 되지 않는 1과 2를 제외한 숫자 중 하나를 골라 입력 값으로 넣어주고 or 과 함께 2를 작성해주면 될 것이다!

 

?no=4 or 2 

와 같은 형태로 작성해주면 되는데, url에 입력할 때에는 공백을 url 인코딩하여 사용해야 한다.

 

공백은 %20으로 치환할 수 있지만 이를 url에 ?no=4%20or%20no=2의 형태로 작성하면 필터링 되어 no hack이 뜬다.

 

따라서 tab을 나타내는 %09나 linefeed를 나타내는 %0a, %0b, %0c 중에 선택하여 시도하면 문제를 해결할 수 있다.

 

%09로 작성해보면,

https://webhacking.kr/challenge/web-32/index.php?no=4%09or%09no=2 

 

 


[핵심]

preg_match('/대조할 문자/', '입력한 문자', $matches);

의 형태로 사용하면서 필터링 한다!

- 특수문자를 필터링 하고 싶다면 특수문자 앞에 \를 붙이면 됨!

- '/admin/'i 와 같이 i가 붙어 있는 것은 대소문자를 구분하지 않겠다는 뜻!

- match 자리에는 사용자가 설정한 값과 입력 값이 일치하는 경우 그 값을 $match에 배열 형태로 저장함

(문자열이 1개라도 검거되면 1반환, 아니면 0 반환)

 

+ 필터링 함수

str_replace -> 다른 문자로 바꿔줌

preg_replace -> 다른 문자로 바꿔줌

 

preg_match전에 

eregi() -> 비슷한 원리로 문자열 필터링(근데 NULL BYTE 취약점 존재해서 없어짐)

 

 

https://overcode.tistory.com/entry/HTML-Encoding-ReferenceURL-%EC%9D%B8%EC%BD%94%EB%94%A9%EC%9D%84-%EC%95%84%EC%8A%A4%ED%82%A4-%EB%AC%B8%EC%9E%90%EB%A1%9C-%EB%B3%80%ED%99%98

LIST

'Wargame > Webhacking.kr' 카테고리의 다른 글

[Webhacking.kr] Old-39  (0) 2021.08.11
[Webhacking.kr] Old 26  (0) 2021.08.04
[Webhacking.kr] Old 17  (0) 2021.07.28
[Webhacking.kr] Old 16  (0) 2021.07.27
[Webhacking.kr] old-15  (0) 2021.07.22