继续学习文件上传骚操作 skrskr
pass-09
$is_upload = false;
$msg = null;
if (isset($_POST['submit'])) {
if (file_exists(UPLOAD_PATH)) {
$deny_ext = array (".php",".php5",".php4",".php3",".php2",".html",".htm",".phtml",".pHp",".pHp5",".pHp4",".pHp3",".pHp2",".Html",".Htm",".pHtml",".jsp",".jspa",".jspx",".jsw",".jsv",".jspf",".jtml",".jSp",".jSpx",".jSpa",".jSw",".jSv",".jSpf",".jHtml",".asp",".aspx",".asa",".asax",".ascx",".ashx",".asmx",".cer",".aSp",".aSpx",".aSa",".aSax",".aScx",".aShx",".aSmx",".cEr",".sWf",".swf",".htaccess");
$file_name = trim($_FILES['upload_file']['name']);
$file_name = deldot($file_name);//删除文件名末尾的点
$file_ext = strrchr($file_name, '.');
$file_ext = strtolower($file_ext); //转换为小写
$file_ext = str_ireplace('::$DATA', '', $file_ext);//去除字符串::$DATA
$file_ext = trim($file_ext); //首尾去空
if (!in_array($file_ext, $deny_ext)) {
if (move_uploaded_file($_FILES['upload_file']['tmp_name'], UPLOAD_PATH . '/' . $_FILES['upload_file']['name'])) {
$img_path = UPLOAD_PATH . '/' . $file_name;
$is_upload = true;
}
} else {
$msg = '此文件不允许上传';
}
} else {
$msg = UPLOAD_PATH . '文件夹不存在,请手工创建!';
}
}
源码发现黑名单机制将该过滤的都过滤了.可是过滤仅过滤了一次.
假如构造 test.php. . //点+空格+点
首先第一步删掉了文件末尾的点 test.php. //点+空格
然后第二步删掉了末尾的空格 test.php. //点
从而绕过了对文件名的处理.
前由此前八关也可以利用这种方式绕过构造.可这种利用方式如果没有拿到源码的情况下,构造这样的payload我想还是不太容易的,所以对这样的文件名处理还是有一定的防御能力
pass-10
$is_upload = false;
$msg = null;
if (isset($_POST['submit'])) {
if (file_exists(UPLOAD_PATH)) {
$deny_ext = array("php","php5","php4","php3","php2","html","htm","phtml","jsp","jspa","jspx","jsw","jsv","jspf","jtml","asp","aspx","asa","asax","ascx","ashx","asmx","cer","swf","htaccess");
$file_name = trim($_FILES['upload_file']['name']);
$file_name = str_ireplace($deny_ext,"", $file_name);
if (move_uploaded_file($_FILES['upload_file']['tmp_name'], UPLOAD_PATH . '/' . $file_name)) {
$img_path = UPLOAD_PATH . '/' .$file_name;
$is_upload = true;
}
} else {
$msg = UPLOAD_PATH . '文件夹不存在,请手工创建!';
}
}
同样是黑名单机制但是,这次不同的是当发现黑名单里的字符串时,它采取的是替换为空
构造test.pphphp
str_ireplace(find,replace,string,count)该函数对大小写不敏感。
同时对大小写敏感的是str_replace(find,replace,string,count)
作用是将string中的find替换成relpace,count计数替换了几次。
如果find和replace都是数组的话,replace若多于find,则多余部分无视,若少,则空串替换。
pass-11
$is_upload = false;
$msg = null;
if(isset($_POST['submit'])){
$ext_arr = array('jpg','png','gif');
$file_ext = substr($_FILES['upload_file']['name'],strrpos($_FILES['upload_file']['name'],".")+1);
if(in_array($file_ext,$ext_arr)){
$temp_file = $_FILES['upload_file']['tmp_name'];
$img_path = $_GET['save_path']."/".rand(10, 99).date("YmdHis").".".$file_ext;
if(move_uploaded_file($temp_file,$img_path)){
$is_upload = true;
}
else{
$msg = '上传失败!';
}
}
else{
$msg = "只允许上传.jpg|.png|.gif类型文件!";
}
}
不知道什么原因上传失败,查了别人的payload也还是失败.先留着
pass-12
$is_upload = false;
$msg = null;
if(isset($_POST['submit'])){
$ext_arr = array('jpg','png','gif');
$file_ext = substr($_FILES['upload_file']['name'],strrpos($_FILES['upload_file']['name'],".")+1);
if(in_array($file_ext,$ext_arr)){
$temp_file = $_FILES['upload_file']['tmp_name'];
$img_path = $_POST['save_path']."/".rand(10, 99).date("YmdHis").".".$file_ext;
if(move_uploaded_file($temp_file,$img_path)){
$is_upload = true;
}
else{
$msg = "上传失败";
}
}
else{
$msg = "只允许上传.jpg|.png|.gif类型文件!";
}
}
12和11其实是同类型 都是由于上传路径可控可以利用%00截断构造php结尾的文件.
11题是get型直接在url后面添加%00就可以达到效果,
12题是post型需要利用burp在发包的时候以16进制的方式修改
例如 test.php .jpg //中间有个空格
空格对应的16进制是20利用burp修改成00便可以达到目的
%00截断有这么2种利用状况
在url中加入%00,如http://xxxx/filename.php%00.jpg
在burpsuite的16进制编辑工具将”filename.php .jpg”[带空格的]中间的空格由20改成00
url中的%00[只要是这种%xx]的形式,Webserver会把它当作十六进制处理,然后把16进制的hex自动翻译成ascii码值“NULL”,实现了截断Burpsuite中16进制编辑器将空格20改成了00,跟上面一样的变成Asccii的null。
pass-13
从此关开始php文件不能直接执行,需要配合其他漏洞才能利用.在源码上的表现,就是文件后缀被写死,一定是gif,jpg,png
function getReailFileType($filename){
$file = fopen($filename, “rb”);
$bin = fread($file, 2); //只读2字节
fclose($file);
$strInfo = @unpack(“C2chars”, $bin);
$typeCode = intval($strInfo[‘chars1’].$strInfo[‘chars2’]);
$fileType = ‘’;
switch($typeCode){
case 255216:
$fileType = ‘jpg’;
break;
case 13780:
$fileType = ‘png’;
break;
case 7173:
$fileType = ‘gif’;
break;
default:
$fileType = ‘unknown’;
}
return $fileType;
}
$is_upload = false;
$msg = null;
if(isset($_POST['submit'])){
$temp_file = $_FILES['upload_file']['tmp_name'];
$file_type = getReailFileType($temp_file);
if($file_type == 'unknown'){
$msg = "文件未知,上传失败!";
}else{
$img_path = UPLOAD_PATH."/".rand(10, 99).date("YmdHis").".".$file_type;
if(move_uploaded_file($temp_file,$img_path)){
$is_upload = true;
}
else{
$msg = "上传失败";
}
}
}
pass-13只是读取文件头两个字节, 也就是文件头了, 于是可以用 copy 命令去生成一个图片马
copy test.jpg /b + test.php /a shell.jpg
pass-14
$image_type = exif_imagetype($filename);
pass-15
$info = getimagesize($filename);
$ext = image_type_to_extension($info[2]);
pass-16
16题进行层层检查,毫无可能上传一个php文件.即使是插入了php代码的图片马也会被二次渲染一定几率破坏掉.虽然有机会绕过,但是在没有类似文件包含这样的漏洞执行php代码,这个漏洞并不能被利用.
要实现上传正常的图片与二次渲染的图片进行对比,在相同数据部分插入php代码 //这种骚操作暂时还不会
总结
1.对文件名的处理是必要且有效的,进过滤一次特殊字符可能达不到预期的防御效果
2.上传路径和文件名可控会存在一定问题
3.写死文件后缀可以防止恶意文件的getshell.像菜刀链接的文件就得是php,asp这些动态文件
4.当文件名被写死时,需要寻找例如文件包含漏洞来触发图片马内的php代码达到getshell