漏洞利用过程
第十关
$is_upload = false;
$msg = null;
if (isset($_POST['submit'])) {
if (file_exists(UPLOAD_PATH)) {
$deny_ext = array(".php",".php5",".php4",".php3",".php2",".html",".htm",".phtml",".pht",".pHp",".pHp5",".pHp4",".pHp3",".pHp2",".Html",".Htm",".pHtml",".jsp",".jspa",".jspx",".jsw",".jsv",".jspf",".jtml",".jSp",".jSpx",".jSpa",".jSw",".jSv",".jSpf",".jHtml",".asp",".aspx",".asa",".asax",".ascx",".ashx",".asmx",".cer",".aSp",".aSpx",".aSa",".aSax",".aScx",".aShx",".aSmx",".cEr",".sWf",".swf",".htaccess",".ini");
$file_name = trim($_FILES['upload_file']['name']);
$file_name = deldot($file_name);//删除文件名末尾的点
$file_ext = strrchr($file_name, '.');
$file_ext = strtolower($file_ext); //转换为小写
$file_ext = str_ireplace('::$DATA', '', $file_ext);//去除字符串::$DATA
$file_ext = trim($file_ext); //首尾去空
if (!in_array($file_ext, $deny_ext)) {
$temp_file = $_FILES['upload_file']['tmp_name'];
$img_path = UPLOAD_PATH.'/'.$file_name;
if (move_uploaded_file($temp_file, $img_path)) {
$is_upload = true;
} else {
$msg = '上传出错!';
}
} else {
$msg = '此文件类型不允许上传!';
}
} else {
$msg = UPLOAD_PATH . '文件夹不存在,请手工创建!';
}
}
deldot() 函数从后向前检测,当检测到末尾的第一个点时会继续它的检测,但是遇到空格会停下来。
漏洞利用的原理是利用 deldot()
函数的特性以及对文件后缀名的检查不严谨,绕过文件类型限制,从而上传恶意文件。
详细利用步骤如下:
- 攻击者将恶意文件命名为
shell.php. .
,其中包含两个点。 - 在检查文件后缀名时,
deldot()
函数会从后向前检查文件名中的点,并删除末尾的点。但是,由于文件名中含有两个点,deldot()
函数在遇到第一个点时会继续检查,直到遇到空格停止检查。 - 在经过
deldot()
函数处理后,文件名变为shell.php.
,绕过了后缀名的检查。 - 经过后续的处理,攻击者成功将恶意文件
shell.php
上传到了指定的目录。(点绕过)
第十一关
$is_upload = false;
$msg = null;
if (isset($_POST['submit'])) {
if (file_exists(UPLOAD_PATH)) {
$deny_ext = array("php","php5","php4","php3","php2","html","htm","phtml","pht","jsp","jspa","jspx","jsw","jsv","jspf","jtml","asp","aspx","asa","asax","ascx","ashx","asmx","cer","swf","htaccess","ini");
$file_name = trim($_FILES['upload_file']['name']);
$file_name = str_ireplace($deny_ext,"", $file_name);
$temp_file = $_FILES['upload_file']['tmp_name'];
$img_path = UPLOAD_PATH.'/'.$file_name;
if (move_uploaded_file($temp_file, $img_path)) {
$is_upload = true;
} else {
$msg = '上传出错!';
}
} else {
$msg = UPLOAD_PATH . '文件夹不存在,请手工创建!';
}
}
在这段代码中,服务器会从用户上传的文件中获取文件名,并对文件后缀名进行检查。如果文件后缀名在 deny_ext
数组中,就会将该后缀名从文件名中删除,以避免上传被禁止的文件类型。
漏洞利用的思路是利用双写后缀名绕过后缀名检查,从而上传一个恶意的 PHP 文件。
将文件名命名为 shell.pphphp
,str_ireplace 函数从左往右扫描,当扫描到 pphp
hp 时,就会把中间的 php
删除,这恰好使得剩下的为 php
。
这种绕过技巧利用了 str_ireplace()
函数的从左往右扫描特性,使得攻击者可以通过在文件名中添加额外的 php
来绕过后缀名检查,从而上传恶意代码并在服务器上执行。
注意 phpphp
这样双写的不可以的,因为从左往右扫描,这样会有两次匹配,会删除两次。
第十二关
$is_upload = false;
$msg = null;
if(isset($_POST['submit'])){
$ext_arr = array('jpg','png','gif');
$file_ext = substr($_FILES['upload_file']['name'],strrpos($_FILES['upload_file']['name'],".")+1);
if(in_array($file_ext,$ext_arr)){
$temp_file = $_FILES['upload_file']['tmp_name'];
$img_path = $_GET['save_path']."/".rand(10, 99).date("YmdHis").".".$file_ext;
if(move_uploaded_file($temp_file,$img_path)){
$is_upload = true;
} else {
$msg = '上传出错!';
}
} else{
$msg = "只允许上传.jpg|.png|.gif类型文件!";
}
}
该漏洞利用的原理涉及 PHP 版本小于 5.3 和 magic_quotes_gpc
关闭的情况。在这种环境下,当服务器处理数据时,如果遇到字符串中的 00
字节(NULL 字节),PHP 会将其视为字符串的结尾,即认为数据处理结束,后面的内容将被忽略。
在 PHP 版本小于 5.3 的情况下,默认的 magic_quotes_gpc
配置为关闭状态。magic_quotes_gpc
是 PHP 中的一个配置选项,用于自动对通过 GET、POST 和 COOKIE 方式传递到脚本中的数据进行转义。当 magic_quotes_gpc
关闭时,PHP 将不会对输入数据进行自动转义,这可能导致一些安全问题。
利用该漏洞,攻击者可以构造恶意数据,将 00
字节放在数据的中间位置,使得 PHP 在处理数据时将其视为字符串的结尾,从而导致后面的数据被忽略。
修复该漏洞的方法包括:
- 将 PHP 升级到 5.3 或更高版本,因为在 PHP 5.3 版本之后,
magic_quotes_gpc
配置项已经被弃用,字符串转义由其他配置项控制,不会受到00
字节的影响。 - 将
magic_quotes_gpc
配置为开启状态,虽然这不是推荐的做法,但在老版本的 PHP 中可以作为临时的解决方案。 - 对上传的数据进行严格的过滤和验证,确保不包含任何特殊字符,特别是
00
字节。可以使用正则表达式或其他方法对数据进行过滤。 - 最好的方式是使用最新版本的 PHP,并且在代码中严格验证和过滤用户输入,以防止任何类型的漏洞攻击。
在本题中,我们可以修改 save_path
为 /upload/lab12/php%00
,这样就会忽略 php
之后的所有字符。
第十三关
$is_upload = false;
$msg = null;
if(isset($_POST['submit'])){
$ext_arr = array('jpg','png','gif');
$file_ext = substr($_FILES['upload_file']['name'],strrpos($_FILES['upload_file']['name'],".")+1);
if(in_array($file_ext,$ext_arr)){
$temp_file = $_FILES['upload_file']['tmp_name'];
$img_path = $_POST['save_path']."/".rand(10, 99).date("YmdHis").".".$file_ext;
if(move_uploaded_file($temp_file,$img_path)){
$is_upload = true;
} else {
$msg = "上传失败";
}
} else {
$msg = "只允许上传.jpg|.png|.gif类型文件!";
}
}
与第十二关原理一致,也是 00 截断,只不过换成了 POST 请求。
将空格(20)改成(00)进行截断(不知道为什么 2021 版的 burp 没有 hex 编辑,使用 2020 版的)
第十四关~第十七关
这几关均考察图片码。
文件上传漏洞中的图片码利用是一种利用图片上传功能漏洞的攻击方法。在某些网站或应用程序中,用户可以上传图片文件作为头像、相册或其他用途。然而,由于不恰当的输入验证和过滤,攻击者可以通过构造恶意的图片码来绕过上传限制,从而上传包含恶意代码的图片文件。
图片码利用的一种常见方式是将图片文件的内容进行篡改,使其同时包含合法的图片数据和恶意的代码。攻击者可以在图片文件的结尾添加额外的 PHP 代码,这样在服务器解析图片时,恶意代码也会被执行。
以下是一个示例,假设网站允许用户上传头像图片,且存在文件上传漏洞:
- 攻击者准备一个恶意图片,图片内容结构如下:
[合法的图片数据][恶意的PHP代码]
2. 攻击者通过上传功能上传这个恶意图片。由于文件上传漏洞,网站可能没有正确验证文件的内容,只是简单地检查文件后缀名或文件类型。
-
网站将这个图片文件保存到服务器上的指定位置。
-
当其他用户访问攻击者上传的图片文件时,服务器会解析图片内容并显示。由于恶意图片的结构,在显示图片时,服务器也会执行恶意的 PHP 代码。
-
攻击者成功地在网站上执行了恶意代码,可能导致网站被入侵、敏感信息被窃取、用户数据泄露等严重后果。
要防止图片码利用,网站应该对上传的图片进行严格的验证和过滤。可以使用图像处理库来确保上传的文件确实是有效的图片文件,并对文件内容进行检查,以确保不包含任何恶意代码。同时,还应该限制上传文件的类型和大小,避免上传可执行的文件或其他危险文件。此外,最好将上传的图片文件保存在非 Web 可访问的目录中,以减少恶意文件的利用可能性。总体上,加强输入验证和文件处理是预防文件上传漏洞及图片码利用的关键措施。
在部分关卡中,服务端对图片进行了二次渲染,我们需要绕过二次渲染。
绕过图片码二次渲染是一种利用文件上传漏洞的高级攻击技术。在一些情况下,网站或应用程序可能会对上传的图片文件进行检查和处理,包括重新渲染(即重新生成图片)以确保图像的合法性和安全性。然而,如果处理不当,攻击者仍然可以绕过这种二次渲染的措施,将恶意代码成功地执行在服务器上。
绕过图片码二次渲染的一些常见技术有:
- 图片尺寸欺骗:攻击者可以构造一个看似合法的图片,但实际上图片文件中可能隐藏了大量的恶意代码。然而,攻击者可能在图片文件的头部添加一些虚假的信息,使其看起来像一个较小的、无害的图片。这样,当服务器进行二次渲染时,可能只会渲染部分内容,而没有检测到恶意代码。
- 色彩混淆:攻击者可以在恶意图片中使用特殊的色彩混淆技术,使恶意代码与图片的颜色融合在一起,使其难以被检测到。这样,即使服务器对图片进行重新渲染,也不容易察觉其中的恶意代码。
- 图片结构混淆:攻击者可能对恶意图片的结构进行混淆,使其看起来像一个普通的图片,但实际上隐藏了恶意代码。这样,在服务器进行图片处理时,恶意代码可能会被忽略或遗漏。
- 嵌套图片:攻击者可以将多个图片文件嵌套在一个文件中,使其看起来像一个正常的图片。但实际上,其中的一个图片可能是恶意的,而其他的图片是用来迷惑服务器进行二次渲染。
为了防止绕过图片码二次渲染,网站应该采取更加严格的文件上传处理措施。除了检查图片文件的类型和大小之外,还应该对图片的内容进行更深入的分析和验证,确保图片文件不包含任何恶意代码。此外,最好采用安全的图像处理库来重新渲染图片,以确保不会忽略恶意代码。总体上,提高文件上传处理的安全性和可靠性是防止绕过图片码二次渲染的重要步骤。
我们尝试上传图片码并访问,可以成功运行 phpinfo
。
实验总结
前端-JS类验证
前端验证是指在客户端(浏览器)上使用JavaScript等脚本语言对上传的文件进行验证。然而,前端验证是不可靠的,因为攻击者可以轻易地绕过前端验证,通过直接发送HTTP请求来上传恶意文件。
后端-黑名单绕过
黑名单绕过是指攻击者绕过服务器端的黑名单验证机制,以上传服务器不允许的文件类型。攻击者可以使用特殊的文件名、后缀或文件头信息,使文件看起来像是允许的类型,从而绕过黑名单检查。
.htaccess解析
攻击者可以上传包含特殊.htaccess
内容的文件,以绕过服务器配置限制。.htaccess
是用于针对目录改变配置的文件,攻击者可能使用它来绕过上传目录的限制或修改解析规则,使上传的文件被解释为可执行的PHP文件。
大小写绕过
在某些系统中,文件名大小写不敏感。攻击者可以利用这一特性,将上传的文件后缀名改为大写,从而绕过服务器的后缀名限制。
点绕过
某些操作系统会删除文件名中的点号(.
),但Web服务器可能忽略了这一规则。攻击者可以通过上传带有点号的文件名绕过后端的文件类型检查。
空格绕过
类似于点绕过,某些操作系统会忽略文件名中的空格,攻击者可以通过上传带有空格的文件名来绕过后端的文件类型检查。
::$$DATA绕过
在Windows系统中,攻击者可以利用NTFS文件流特性,通过上传文件名为filename::$DATA
来绕过后端的文件类型检查。
Apache HTTPD换行解析漏洞(CVE-2017-15715)
在某些版本的Apache HTTPD服务器中存在解析漏洞,攻击者可以利用换行符的特性,在文件名中添加%0a
或%0d
,使服务器解析为php后缀,绕过文件类型检查。
Nginx 解析漏洞
在某些情况下,由于Nginx服务器的配置问题,攻击者可以上传以.php
结尾的文件并通过在文件名后添加/xxx.php
(xxx为任意字符)来绕过后端对文件类型的检查,使其被解析为PHP文件。
后端-白名单绕过
白名单绕过是指攻击者绕过服务器端的白名单验证机制,以上传恶意文件。攻击者可以使用各种技术手段,如文件头欺骗、MIME类型欺骗等,使上传的文件看起来像是允许的类型,从而绕过白名单检查。
MIME绕过
攻击者可以伪造文件的MIME类型,使其看起来像是允许的类型,从而绕过服务器端的MIME类型验证。
00截断-1(GET|POST)
攻击者可以利用%00
(空字节)来进行截断,使得文件名中的%00
之后的内容被忽略,从而绕过后端的文件类型检查。
其他内容
文件头检测
当文件上传到服务器,白名单进行的文件头检测。 JPEG (jpg),文件头:FFD8FF PNG (png),文件头:89504E47 GIF (gif),文件头:47494638
二次渲染
上传文件后,网站会对图片进行二次处理(格式、尺寸要求等),处理后在放到网站对应的标签进行显示。
如何绕过呢
- 图片尺寸欺骗:攻击者可以构造一个看似合法的图片,但实际上图片文件中可能隐藏了大量的恶意代码。然而,攻击者可能在图片文件的头部添加一些虚假的信息,使其看起来像一个较小的、无害的图片。这样,当服务器进行二次渲染时,可能只会渲染部分内容,而没有检测到恶意代码。
- 色彩混淆:攻击者可以在恶意图片中使用特殊的色彩混淆技术,使恶意代码与图片的颜色融合在一起,使其难以被检测到。这样,即使服务器对图片进行重新渲染,也不容易察觉其中的恶意代码。
- 图片结构混淆:攻击者可能对恶意图片的结构进行混淆,使其看起来像一个普通的图片,但实际上隐藏了恶意代码。这样,在服务器进行图片处理时,恶意代码可能会被忽略或遗漏。
- 嵌套图片:攻击者可以将多个图片文件嵌套在一个文件中,使其看起来像一个正常的图片。但实际上,其中的一个图片可能是恶意的,而其他的图片是用来迷惑服务器进行二次渲染。
条件竞争漏洞
文件上传中的条件竞争漏洞是一种安全漏洞,通常出现在文件上传过程中,攻击者利用并发性(多个操作同时执行)的特性来绕过服务器的上传限制或进行未经授权的文件上传。这种漏洞可能导致恶意文件被上传到服务器上,从而引发各种安全问题,如远程代码执行、服务器拒绝服务等。
漏洞原理:
- 文件上传过程中,服务器通常会检查上传文件的类型、大小和扩展名等信息来确保文件的合法性和安全性。
- 攻击者利用并发性的特性,同时发送多个上传请求到服务器,以尝试绕过文件上传的限制。
- 在服务器处理上传请求的过程中,可能会发生竞争条件,即多个请求同时竞争访问和修改服务器的状态。
- 攻击者通过并发操作,可能会在服务器完成检查和验证之前,将恶意文件成功地上传到服务器上。
攻击示例: 假设服务器上传文件的处理过程如下:
- 攻击者发起一个文件上传请求,并上传一个合法的图片文件,服务器接收到请求并进行类型和扩展名检查。
- 在服务器检查上传文件的过程中,攻击者快速地发送另一个上传请求,但这次上传的文件名为恶意文件(如.php文件)。
- 服务器可能会在检查完第一个请求后,再处理第二个请求,此时第二个请求中的恶意文件可能会被成功上传到服务器上,因为此时服务器已经处于检查完成的状态。
对于以上漏洞,对应的一些防范方法:
前端-JS类验证
- 前端验证仅作为用户友好的提示,不能作为唯一的上传文件验证。后端必须对上传的文件进行进一步验证和处理。
后端-黑名单绕过
- 不要依赖黑名单机制,而是使用白名单机制来验证上传的文件类型。只允许明确需要的文件类型,拒绝其他所有类型。
.htaccess解析
- 禁止上传
.htaccess
文件或任何其他可以修改服务器配置的文件。 - 对上传的文件名进行过滤,阻止含有特殊字符或字符编码的文件名。
大小写绕过
- 在服务器上设置大小写敏感的文件系统,避免大小写绕过问题。
点绕过
- 对文件名进行过滤,阻止文件名中含有点号的情况,或在服务器配置中禁止解析上传文件中的点号。
空格绕过
- 对文件名进行过滤,阻止文件名中含有空格的情况,或在服务器配置中禁止解析上传文件中的空格。
::$$DATA绕过
- 在Windows系统上,禁止上传文件名中含有
::$DATA
的文件,或在服务器配置中禁用NTFS文件流。
Apache HTTPD换行解析漏洞(CVE-2017-15715)
- 升级Apache HTTPD服务器至不受此漏洞影响的最新版本。
Nginx 解析漏洞
- 升级Nginx服务器至不受此漏洞影响的最新版本。
后端-白名单绕过
- 使用严格的白名单验证机制,只允许特定的文件类型,拒绝其他所有类型。
- 对上传文件的MIME类型进行验证,确保其与文件扩展名一致。
MIME绕过
- 使用文件头检测来确定文件的真实类型,而不是仅依赖MIME类型。
00截断-1(GET|POST)
- 在处理上传文件时,移除文件名中的
%00
或其他空字节,确保文件名的完整性。
其他内容
文件头检测
- 在上传文件时,不仅仅依赖文件扩展名,还应该根据文件头检测来验证文件类型的真实性。
二次渲染
- 使用安全的图片处理库来渲染和处理图片,确保不会被恶意图片利用。
- 对上传的图片进行严格的尺寸、格式和质量检查,防止攻击者利用图片渲染过程中的漏洞。
条件竞争漏洞
- 在处理上传文件时,使用原子操作或加锁机制,避免竞争条件的发生。
- 对上传的文件进行唯一性检查,确保不会出现重复上传的情况。
综合以上防范方法,可以大幅提高文件上传功能的安全性。但值得注意的是,单一的防范措施可能不足以防止所有类型的文件上传漏洞。因此,组合多种方法并持续进行安全审计是维护文件上传功能的安全性的有效途径。此外,保持应用程序和服务器的所有组件处于最新的安全状态也是至关重要的。
在这个实验中,我对文件上传漏洞进行了深入的学习和探索,通过实际操作和理论学习,我深刻认识到这些漏洞对网站安全所带来的威胁和风险。在实验过程中,我亲身体验了不同类型的文件上传漏洞的利用原理和实现方式,从前端-JS类验证到后端黑名单绕过,再到.htaccess解析等,每一种漏洞都有其特定的利用方法。
我了解了前端验证的不足之处,即前端验证可以轻易地被绕过,因为攻击者可以直接发送HTTP请求来上传恶意文件,而绕过前端的验证。其次,我学习了后端黑名单绕过,即攻击者通过使用特殊的文件名、后缀或文件头信息,使文件看起来像是允许的类型,从而绕过服务器端的黑名单检查。然后,我了解到.htaccess解析漏洞,攻击者可以上传包含特殊.htaccess内容的文件,以绕过服务器配置限制。而大小写绕过、点绕过、空格绕过等也是利用文件名的特殊构造来绕过后端的文件类型检查,从而上传恶意文件。
除了这些利用文件名的方式,我还了解到了 ::$DATA
绕过,这是利用Windows系统的NTFS文件流特性,通过上传文件名为 filename::$DATA
来绕过后端的文件类型检查。同时,还学习了Apache HTTPD换行解析漏洞和Nginx解析漏洞,它们利用服务器配置问题来绕过文件上传的限制。
我了解到文件上传中的条件竞争漏洞,它是一种安全漏洞,通过并发性的特性来绕过服务器的上传限制或进行未经授权的文件上传。攻击者利用并发操作,可能会在服务器完成检查和验证之前,将恶意文件成功地上传到服务器上,从而引发各种安全问题。
通过这次实验,我深刻认识到文件上传漏洞对网站安全造成的严重威胁。网络安全是一个不断演化的领域,攻击者总是在寻找新的漏洞和攻击方式,而防范措施也需要不断更新和加强。作为网站开发者和管理员,我深感责任重大,必须时刻保持警惕,采取有效的防范措施,确保网站的安全性和稳定性。
在实验中,我不仅学习到了文件上传漏洞的原理和利用方式,还学会了如何防范这些漏洞。前端-JS类验证只是一个辅助手段,主要的防范措施应该在后端进行。建立白名单而非黑名单,限制文件上传的类型和大小,并且对上传的文件进行严格的处理和验证,以确保其合法性和安全性。此外,定期更新服务器和网站的软件和补丁,加强访问控制和权限管理,都是提高网站安全性的有效方法。
通过这个实验,我不仅学到了具体的技术知识,还深刻认识到了网络安全的重要性。我将继续努力学习和提升自己的网络安全知识,为构建更安全的网络环境做出贡献。同时,我也希望能够通过自己的努力,为网站安全和网络安全事业做出更大的贡献。网络安全是一项永恒的课题,我将持续关注并不断学习,为网络安全事业贡献一份力量。