嗨,朋友你好,我是闪石星曜CyberSecurity创始人Power7089。
今天为大家带来PHP代码审计基础系列文章第二篇之任意文件上传篇。
这是【炼石计划@PHP代码审计】知识星球第二阶段的原创基础系列文章,拿出部分课程分享给零基础的朋友学习。本系列原创基础文章涵盖了PHP代码审计中常见的十余种WEB漏洞,是匹夫老师精心的创作,欢迎关注我的公众号跟着一起学习。
【炼石计划@PHP代码审计】是一个系统化从入门到提升学习PHP代码审计的成长型知识星球。这里不仅注重夯实基础,更加专注实战进阶。强烈推荐加入我们,一起来实战提升PHP代码审计。
进入正文
将Web木马插入到服务器并且服务器端可以成功解析插入的Web木马
何为上传的Web木马被解析:最简单的例子就是目标服务器后端用PHP语言,那么针对上传的文件我们就要利用PHP木马进行上传,且后缀为.PHP
。
是否存在上传漏洞的前提条件是:①存在上传点 ②上传点的内容可控③上传的文件可被解析
通过前端页面上传恶意文件到后端,服务器接收到文件后先将他存储为临时文件,将临时文件移动到信的位置,然后攻击者访问该文件,恶意文件被解析后返回该恶意文件内容。
①Web站点具有上传功能点
②上传的目标文件可被Web服务器解析
③已知上传的目标文件路径
以及文件名
④目标文件可被访问
在某种情况下服务器会对上传的文件进行访问控制,也就是说即使将目标文件上传到服务器也无法对其进行访问,无法进一步利用。
index.html
form
标签中action
属性定义在哪个文件实现后端文件上传功能,method
属性定义上传方式,enctype
属性定义上传类型,如果不写浏览器将根据上传文件,自行判断上传文件类型
input
标签type
属性定义input标签将内容当做什么类型来处理,name
属性定义上传文件名
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>文件上传小demo</title>
</head>
<body>
<form action="demo.php" method="post" enctype="multipart/form-data">
<p>请选择上传的文件:</p>
<input class="upload_file" type="file" name="uploadFile"/>
<input class="button" type="submit" name="submit" value="上传" />
</form>
</body>
</html>
demo.php
<?php
if(is_uploaded_file($_FILES["uploadFile"]["tmp_name"]))
{
$upFile = $_FILES["uploadFile"];
$name = $upFile["name"];
$type = $upFile["type"];
$size = $upFile["size"];
$tmpName = $upFile["tmp_name"];
var_dump($upFile);
$path = "./".$name;
move_uploaded_file($tmpName,$path);
echo "文件上传成功";
}else
{
echo "文件上传失败";
}
?>
上传dog.jpg作为演示文件
uploadFile
就是index.html
中input
标签中name
属性值,上传成功后会通过var_dump()
函数以键值对的形式打印出$_FILES
中保存的所有值。
值得注意的是文件被上传后,默认地会被存储为临时文件(phpBD6C.tmp),需使用move_uploaded_file()
函数将临时文件进行移动存储,如果不进行移动在上传代码运行完成之后临时文件将被删除,文件将不会被保存。
$_FILES
PHP中的超全局变量,用来接收上传文件的所有内容,$_FILES是一个二维数组,数组内容如下:
$_FILES['uploadFile']['name'] 客户端文件的原名称。
$_FILES['uploadFile']['type'] 文件的 MIME 类型,例如"image/gif"。
$_FILES['uploadFile']['size'] 已上传文件的大小,单位为字节。
$_FILES['uploadFile']['tmp_name'] 文件被上传后在服务端储存的临时文件名,一般是系统默认。可以在php.ini的upload_tmp_dir指定。
$_FILES['uploadFile']['error'] 该文件上传相关的错误代码。
var_dump()
is_uploaded_file()
move_uploaded_file()
如果移动过程中文件名重复,则会覆盖以后文件。
文件上传最重要的是对上传文件的类型进行检测,相关检测方式如下如:
这里代码为前端JS检测代码,上述提到的检测类型代码以及绕过方式会在Upload-Labs
靶场中为大家一一讲解。
upload_index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>文件上传JS检测demo</title>
</head>
<body>
<form action="demo.php" method="post" enctype="multipart/form-data" onsubmit="return checkFile()">
<p>请选择上传的文件:</p>
<input class="upload_file" type="file" name="uploadFile"/>
<input class="button" type="submit" name="submit" value="上传" />
</form>
</body>
</html>
<script type="text/javascript">
function checkFile() {
//获取数组下标为0的值,也就是上传的文件名
var file = document.getElementsByName('uploadFile')[0].value;
if (file == null || file == "") {
alert("请选择要上传的文件!");
return false;
}
//定义允许上传的文件类型
var allow_ext = ".jpg|.png|.gif";
//提取上传文件的类型
var ext_name = file.substring(file.lastIndexOf("."));
//判断上传文件类型是否允许上传
if (allow_ext.indexOf(ext_name) == -1) {
var errMsg = "该文件不允许上传,请上传" + allow_ext + "类型的文件,当前文件类型为:" + ext_name;
alert(errMsg);
return false;
}
}
</script>
上传.php文件,提示不允许上传
修改后缀名为.jpg
,并使用burp抓包修改将后缀修改回原来的.php绕过js检测
本次只对文件上传原理以及上传代码如何进行实现进行简单介绍,目的是让大家了解文件上传中前后端代码是如何进行分工配合实现文件上传的。在文件上传代码审记中重点要关注的是上传检测部分的代码,通过审计该部分代码来绕过文件上传检测。后续在Upload-Labs靶场部分会对上述所提到的所有上传检测代码以及绕过方式进行一一介绍以及实战演示。
往期回顾
【第一篇】PHP代码审计系列基础文章(一)之SQL注入漏洞篇
注意
后台回复以下关键字即可获取对应学习资料!
【navicat15】SQL注入篇用到的Navicat 15 即破解教程
【PHP代审录屏】往期PHP代码审计直播课
【0531】往期PHP代码审计直播课
【文件上传演示代码】获取文件上传篇涉及的案例代码