时间:2021-05-25
漏洞描述
开发中文件上传功能很常见,作为开发者,在完成功能的基础上我们一般也要做好安全防护。
文件处理一般包含两项功能,用户上传和展示文件,如上传头像。
文件上传攻击示例
upload.php
<?php$uploaddir = 'uploads/'; $uploadfile = $uploaddir . basename($_FILES['userfile']['name']);if (move_uploaded_file($_FILES['userfile']['tmp_name'], $uploadfile)){ echo "File is valid, and was successfully uploaded.\n";} else { echo "File uploading failed.\n";}?>upload.html
<form name="upload" action="upload1.php" method="POST" ENCTYPE="multipart/formdata">Select the file to upload: <input type="file" name="userfile"><input type="submit" name="upload" value="upload"></form>上述代码未经过任何验证,恶意用户可以上传php文件,代码如下
<?php eval($_GET['command']);?>
恶意用户可以通过访问 如http://server/uploads/shell.php?command=phpinfo(); 来执行远程命令
Content-type验证
upload.php
<?phpif($_FILES['userfile']['type'] != "image/gif") {//获取Http请求头信息中ContentType echo "Sorry, we only allow uploading GIF images"; exit;}$uploaddir = 'uploads/';$uploadfile = $uploaddir.basename($_FILES['userfile']['name']);if (move_uploaded_file($_FILES['userfile']['tmp_name'], $uploadfile)){ echo "File is valid, and was successfully uploaded.\n";} else { echo "File uploading failed.\n";}?>该方式是通过Http请求头信息进行验证,可通过修改Content-type ==> image/jpg绕过验证,可以通过脚本或BurpSuite、fiddle修改
如下
Content-Disposition: form-data; name="userfile"; filename="shell.php"
Content-Type: image/gif
图片类型验证
该方法通过读取文件头中文件类型信息,获取文件类型
备注:如JPEG/JPG文件头标识为FFD8
upload.php
<?php$imageinfo = getimagesize($_FILES['userfile']['tmp_name']);if($imageinfo['mime'] != 'image/gif' && $imageinfo['mime'] != 'image/jpeg') { echo "Sorry, we only accept GIF and JPEG images\n"; exit;}$uploaddir = 'uploads/';$uploadfile = $uploaddir . basename($_FILES['userfile']['name']);if (move_uploaded_file($_FILES['userfile']['tmp_name'], $uploadfile)){ echo "File is valid, and was successfully uploaded.\n";} else { echo "File uploading failed.\n";}?>可以通过图片添加注释来绕过此验证。
如添加注释<?php phpinfo(); ?>,保存图片后将其扩展名改为php,则可成功上传。
上传成功后访问该文件则可看到如下显示
文件扩展名验证
通过黑名单或白名单对文件扩展名进行过滤,如下代码
upload.php
<?php$blacklist = array(".php", ".phtml", ".php3", ".php4");foreach ($blacklist as $item) {if(preg_match("/$item\$/i", $_FILES['userfile']['name'])) { echo "We do not allow uploading PHP files\n"; exit;}}$uploaddir = 'uploads/';$uploadfile = $uploaddir . basename($_FILES['userfile']['name']);if (move_uploaded_file($_FILES['userfile']['tmp_name'], $uploadfile)){ echo "File is valid, and was successfully uploaded.\n";} else { echo "File uploading failed.\n";}?>当黑名单不全,构造特殊文件名可以绕过扩展名验证
直接访问上传的文件
将上传文件保存在非web root下其他文件夹下,可以防止用户通过路径直接访问到文件。
upload.php
用户不可以直接通过http://localhost/uploads/ 来访问文件,必须通过view.php来访问
view.php
查看文件代码未验证文件名,用户可以通过例如http://localhost/view.php?name=..//php/upload.php,查看指定的文件
解决漏洞示例
upload.php
<?phprequire_once 'DB.php';$uploaddir = 'D:/uploads/'; $uploadfile = tempnam($uploaddir, "upload_");if (move_uploaded_file($_FILES['userfile']['tmp_name'], $uploadfile)) { $db =& DB::connect("mysql://username:password@localhost/database"); if(PEAR::isError($db)) { unlink($uploadfile); die "Error connecting to the database"; } $res = $db->query("INSERT INTO uploads SET name=?, original_name=?,mime_type=?", array(basename($uploadfile,basename($_FILES['userfile']['name']),$_FILES['userfile']['type'])); if(PEAR::isError($res)) { unlink($uploadfile); die "Error saving data to the database. The file was not uploaded"; } $id = $db->getOne('SELECT LAST_INSERT_ID() FROM uploads'); echo "File is valid, and was successfully uploaded. You can view it <a href=\"view.php?id=$id\">here</a>\n";} else { echo "File uploading failed.\n";}?>view.php
<?phprequire_once 'DB.php';$uploaddir = 'D:/uploads/';$id = $_GET['id'];if(!is_numeric($id)) { die("File id must be numeric");}$db =& DB::connect("mysql://root@localhost/db");if(PEAR::isError($db)) { die("Error connecting to the database");}$file = $db->getRow('SELECT name, mime_type FROM uploads WHERE id=?',array($id), DB_FETCHMODE_ASSOC);if(PEAR::isError($file)) { die("Error fetching data from the database");}if(is_null($file) || count($file)==0) { die("File not found");}header("Content-Type: " . $file['mime_type']);readfile($uploaddir.$file['name']);?>上述代码文件名随机更改,文件被存储在web root之外,用户通过id在数据库中查询文件名,读取文件,可以有效的阻止上述漏洞发生
总结
通过以上示例分析,可总结一下几点
1.文件名修改,不使用用户上传的文件名
2.用户不可以通过上传路径直接访问文件
3.文件查看采用数据库获取文件名,从而在相应文件服务器读取文件
4.文件上传限制文件大小,个人上传数量等
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
声明:本页内容来源网络,仅供用户参考;我单位不保证亦不表示资料全面及准确无误,也不保证亦不表示这些资料为最新信息,如因任何原因,本网内容或者用户因倚赖本网内容造成任何损失或损害,我单位将不会负任何法律责任。如涉及版权问题,请提交至online#300.cn邮箱联系删除。
会员上传文件漏洞,可以上传任意后缀user/swfupload.asp文件漏洞复制代码代码如下:IfUpFileObj.Form("NoReName")="1"
作为PHP程序员,特别是新手,对于互联网的险恶总是知道的太少,对于外部的入侵有很多时候是素手无策的,他们根本不知道黑客是如何入侵的、提交入侵、上传漏洞、sql注
在平时我们可能会碰到过php文件,可是很多用户不知道php文件是什么文件?也不知道怎么打开php文件?为了满足一些用户的好奇心,小编现在就给大家
项目结构:上传首页:上传效果:fileupload.php复制代码代码如下:上传文件:fileupload.php文件中:复制代码代码如下://判断是否为图片s
html文件代码php文件代码/***文件上传方法*/publicfunctionuploadfile(){//单文件上传$upload=new\Think\U