文件上传漏洞是web安全中常常利用到的一种漏洞形式。一些web应用程序中容许上传图片,文本或者其余资源到指定的位置,文件上传漏洞就是利用这些能够上传的地方将恶意代码植入到服务器中,再经过url去访问以执行代码。但在一些安全性较高的web应用中,每每会有各类上传限制和过滤,致使咱们没法上传特定的文件。本文将就此展开讨论,经过本文的学习你将了解到Web应用中文件上传的处理和验证发送流程,以及咱们该如何绕过这些验证。javascript
客户端验证是一种发生在输入被实际发送至服务器以前进行的验证。这类验证大都都是经过JavaScript,VBScript或HTML5来完成的。虽然,这对于用户来讲响应速度更快体验也更好。但对于恶意×××者来讲,这些验证彷佛就显得略为低级。php
这种类型的绕过也很是简单,咱们能够关闭浏览器上的JavaScript或是在浏览器发出请求以后,在被发送至服务器以前来篡改该HTTP请求便可。html
示例:java
1. <script type="text/javascript">web
2. var _validFileExtensions = [".jpg", ".jpeg", ".bmp", ".gif", ".png"];shell
3. function Validate(oForm) {浏览器
4. var arrInputs = oForm.getElementsByTagName("input");安全
5. for (var i = 0; i < arrInputs.length; i++) {服务器
6. var oInput = arrInputs[i];网络
7. if (oInput.type == "file") {
8. var sFileName = oInput.value;
9. if (sFileName.length > 0) {
10. var blnValid = false;
11. for (var j = 0; j < _validFileExtensions.length; j++) {
12. var sCurExtension = _validFileExtensions[j];
13. if (sFileName.substr(sFileName.length - sCurExtension.length, sCurExtension.length).to LowerCase() == sCurExtension.toLowerCase()) {
14. blnValid = true;
15. break;
16. }
17. }
18.
19. if (!blnValid) {
20. alert("Sorry, " + sFileName + " is invalid, allowed extensions are: " + _validFileExtension s.join(", "));
21. return false;
22. }
23. }
24. }
25. }
26.
27. return true;
28. }
29. </script>
正如你所看到的,此JavaScript仅在请求被实际发送至服务器以前处理你的请求,以及检查你上传的文件扩展名是否为(jpg,jpeg,bmp,gif,png)。这样的话,咱们就能够拦截该请求并篡改文件内容(恶意代码),而后将图片扩展名更改成可执行文件的扩展名(如php,asp)。
如上图所示,咱们试图上传一个直接的PHP文件,JavaScript阻止了咱们的文件上传请求。
咱们能够经过浏览器来上传一个正常的图片格式来绕过该验证,而后拦截该请求再将其改回为php格式并将文件内容替换为咱们的恶意代码,这样咱们就可以成功上传咱们的恶意php脚本了。
顾名思义,就是在文件被上传到服务端的时候,对于文件名的扩展名进行检查,若是不合法,则拒绝此次上传。检查扩展名是否合法有两种经常使用策略,即黑名单和白名单策略。
黑名单策略,即文件扩展名在黑名单中的为不合法。白名单策略,即文件扩展名不在白名单中的均为不合法。相对于黑名单,白名单策略更加安全的。经过限制上传类型为只有咱们接受的类型,能够较好的保证安全,由于黑名单咱们可使用各类方法来进行注入和突破。
咱们能够经过上传一些平时不怎么用的容易被人忽视的文件扩展名,来绕过这种类型的验证。
黑名单绕过
经过上传不受欢迎的php扩展来绕过黑名单。例如:pht,phpt,phtml,php3,php4,php5,php6
白名单绕过
经过某种类型的技巧来绕过白名单,例如添加空字节注入(shell.php%00.gif),或使用双重扩展来上传文件(shell.jpg.php)。
此外,咱们还能够尝试扩展名大小写来绕过,例如:pHp,Php,phP。
示例:
1. if($imageFileType != "jpg" && $imageFileType != "png" && $imageFileType != "jpeg"2. && $imageFileType != "gif" ) { 3. echo "Sorry, only JPG, JPEG, PNG & GIF files are allowed.";
以上代码将会阻止除jpg,jpeg,gif,png扩展名之外的,全部其它文件类型上传。在本例中咱们将尝试绕过该检查,并在Web服务器上传一个php文件。
黑名单绕过
正如你所看到的,将php文件的后缀更改成.php5(Apache服务器会将其视为php文件执行)后,就能够成功绕过该上传验证。
白名单绕过
如上图所示,咱们使用了双重扩展名(shell.jpg.php)来绕过验证。
Content-Type(内容类型),通常是指网页中存在的Content-Type,用于定义网络文件的类型和网页的编码,决定文件接收方将以什么形式、什么编码读取这个文件。例如,一些图像文件上传经过检查文件的内容类型是否为图像类型来验证上传的图像。
该类型的绕过也很是简单,只需将“Content-Type”的参数类型更改成“image/ *”便可,例如“image/png”, “image/jpeg”, “image/gif”。
示例:
1. <?php 2. 3. $mimetype = mime_content_type($_FILES['file']['tmp_name']); 4. if(in_array($mimetype, array('image/jpeg', 'image/gif', 'image/png'))) { 5. move_uploaded_file($_FILES['file']['tmp_name'], '/uploads/' . $_FILES['file']['name']); 6. echo 'OK'; 7. 8. } else { 9. echo 'Upload a real image'; 10. }
以上代码会检查Content-Type header中的MIME类型,仅接受类型为image/jpeg, image/gif, image/png的文件上传。咱们只需只需将“Content-Type”的参数类型更改成其可接受的类型便可绕过。
Content-Length验证是指服务器会对上传的文件内容长度进行检查,超出限制大小的文件将不容许被上传。虽然这种类型的验证不是很受欢迎,但在一些应用的文件上传中也时常能碰到。
针对这种类型的验证,咱们能够经过上传一些很是短的恶意代码来绕过。上传文件的大小取决于,Web服务器上的最大长度限制。咱们可使用不一样大小的文件来fuzzing上传程序,从而计算出它的限制范围。
示例:
1. if ($_FILES["fileToUpload"]["size"] > 30) {
2. echo "Sorry, your file is too large.";
3. }
以上代码将限制大小超过30字节的文件上传。咱们能够经过上传一个30字节之内大小的恶意payload文件来绕过它。