【如需转载,请详细表明来源,请勿设置原创】
嗨,大家好,我是闪石星曜CyberSecurity创始人Power7089。
欢迎大家扫描下方二维码关注 “闪石星曜CyberSecurity” 公众号,这里专注分享渗透测试,Java代码审计,PHP代码审计等内容,都是非常干的干货哦。
今天为大家带来PHP代码审计基础系列文章第二篇之任意文件上传篇。
这是【炼石计划@PHP代码审计】知识星球第二阶段的原创基础系列文章,拿出部分课程分享给零基础的朋友学习。本系列原创基础文章涵盖了PHP代码审计中常见的十余种WEB漏洞,是匹夫老师精心的创作,欢迎关注我的公众号跟着一起学习。
【炼石计划@PHP代码审计】是一个系统化从入门到提升学习PHP代码审计的成长型知识星球。这里不仅注重夯实基础,更加专注实战进阶。强烈推荐加入我们,一起来实战提升PHP代码审计。
PHP代码审计之文件上传
1.文件上传原理
将Web木马插入到服务器并且服务器端可以成功解析插入的Web木马
何为上传的Web木马被解析:最简单的例子就是目标服务器后端用PHP语言,那么针对上传的文件我们就要利用PHP木马进行上传,且后缀为.PHP
。
是否存在上传漏洞的前提条件是:①存在上传点 ②上传点的内容可控③上传的文件可被解析
1.1 文件上传业务流程
通过前端页面上传恶意文件到后端,服务器接收到文件后先将他存储为临时文件,将临时文件移动到信的位置,然后攻击者访问该文件,恶意文件被解析后返回该恶意文件内容。
2.2文件上传利用条件
①Web站点具有上传功能点
②上传的目标文件可被Web服务器解析
③已知上传的目标文件路径
以及文件名
④目标文件可被访问
在某种情况下服务器会对上传的文件进行访问控制,也就是说即使将目标文件上传到服务器也无法对其进行访问,无法进一步利用。
1.3 文件上传示例代码
index.html
form
标签中action
属性定义在哪个文件实现后端文件上传功能,method
属性定义上传方式,enctype
属性定义上传类型,如果不写浏览器将根据上传文件,自行判断上传文件类型
input
标签type
属性定义input标签将内容当做什么类型来处理,name
属性定义上传文件名
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| <!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
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| <?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()
函数将临时文件进行移动存储,如果不进行移动在上传代码运行完成之后临时文件将被删除,文件将不会被保存。
1.3.1 PHP超全局变量以及函数介绍
$_FILES
PHP中的超全局变量,用来接收上传文件的所有内容,$_FILES是一个二维数组,数组内容如下:
1 2 3 4 5
| $_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()
如果移动过程中文件名重复,则会覆盖以后文件。
2.文件上传检测类型
文件上传最重要的是对上传文件的类型进行检测,相关检测方式如下如:
2.1 代码示例
这里代码为前端JS检测代码,上述提到的检测类型代码以及绕过方式会在Upload-Labs
靶场中为大家一一讲解。
upload_index.html
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
| <!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() { 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>
|
2.2 绕过方式
上传.php文件,提示不允许上传
修改后缀名为.jpg
,并使用burp抓包修改将后缀修改回原来的.php绕过js检测
3.文件上传代码审计总结
1
| 本次只对文件上传原理以及上传代码如何进行实现进行简单介绍,目的是让大家了解文件上传中前后端代码是如何进行分工配合实现文件上传的。在文件上传代码审记中重点要关注的是上传检测部分的代码,通过审计该部分代码来绕过文件上传检测。后续在Upload-Labs靶场部分会对上述所提到的所有上传检测代码以及绕过方式进行一一介绍以及实战演示。
|