最近刷推特看到了一个洞,PHP<=7.4.21时通过php -S
开起的WEB服务器存在源码泄露漏洞,可以将PHP文件作为静态文件直接输出源码,还蛮有意思的,这里大胆预测一波,最近在CTF里肯定会有人出这个点
查看原文详细分析:PHP Development Server <= 7.4.21 - Remote Source Disclosure
我不分析了,因为是PHP的C源码,我C语言PTSD
直接拉docker就完事了:
docker pull php:7.4.21 # 拉取镜像
docker run --rm -i -t -p 2333:80 php:7.4.21 /bin/bash # 进入内部shell,映射内部80到外部2333
进入容器内shell之后
echo "<?php phpinfo();?>" > phpinfo.php # 写一个php文件
php -S 0.0.0.0:80 # 开Development Server
复现方法如下,记得要关掉Burp自动修改Content-Length的功能
在原文中还提出了一个历史漏洞:在解析HTTP请求的过程中,当某些回调被多次调用时,$_SERVER['REQUEST_URI']
变量会被自身的一个子串覆盖。
这个漏洞没什么太大危害,但有时候可能导致XSS,这里我们来看作者给的一个例子
首先写入如下1.php
<a href="<?php echo htmlentities($_SERVER['REQUEST_URI']) ?>">Unexpected url</a>
因为文件是在/1.php
,所以最后输出的HTML一定是这样格式:
<a href="/1.php[...后续的参数...]">Unexpected url</a>
如果说能构造成<a href="javascript:alert(1)">Unexpected url</a>
用户一点击就能触发XSS了,问题的关键点就是在于怎么去除最前面的/1.php?
脏数据
接下来复现漏洞,因为只是说需要准备一个很长的字符串,也没说具体多长,复现起来就比较困难,这里主要分享一下我复现的方法(没有什么代码依据,就是自己瞎蒙出来的)。
首先随便准备一串字符串,内容无所谓,比如我准备的是
jBSZoRHIsU2chNGIzlGa0BibJBiLkVWby9mZsFWbgMXagQ3clVXclJHIlhGdgQXYoRHIz5WYl1GI0lGIsQWYlJHIzVGd5JGIm9GIyVmYtVnbgwWY09GdgUGa0Byb0BCbhVXclBCdv5GIzlGIyV2cyFGcgUGa0BSeiBCZl1Wdz52bjByclRXeiBiZvBiclJWb15GIlhGdgYWS4ycuJXd0VmcgQmbhBSnAKOdzVWdxVmcgAFVUhEIkV
之后就一遍一遍往上复制,正常情况下输出的$_SERVER['REQUEST_URI']
应该都是/1.php?
开头
同时记得保持URL的最后是javascript:alert(1)
这个XSSpayload
然后继续复制,发送请求,复制多了你就会发现a href
不再以/1.php?
开头了
此时的输出:
<a href="YtVnbgwWY09GdgUGa0Byb0BCbhVXclBCdv5GIzlGIyV2cyFGcgUGa0BSeiBCZl1Wdz52bjByclRXeiBiZvBiclJWb15GIlhGdgYWS4ycuJXd0VmcgQmbhBSnAKOdzVWdxVmcgAFVUhEIkVjBSZoRHIsU2chNGIzlGa0BibJBiLkVWby9mZsFWbgMXagQ3clVXclJHIlhGdgQXYoRHIz5WYl1GI0lGIsQWYlJHIzVGd5JGIm9GIyVmYtVnbgwWY09GdgUGa0Byb0BCbhVXclBCdv5GIzlGIyV2cyFGcgUGa0BSeiBCZl1Wdz52bjByclRXeiBiZvBiclJWb15GIlhGdgYWS4ycuJXd0VmcgQmbhBSnAKOdzVWdxVmcgAFVUhEIkVjBSZoRHIsU2chNGIzlGa0BibJBiLkVWby9mZsFWbgMXagQ3clVXclJHIlhGdgQXYoRHIz5WYl1GI0lGIsQWYlJHIzVGd5JGIm9GIyVmYtVnbgwWY09GdgUGa0Byb0BCbhVXclBCdv5GIzlGIyV2cyFGcgUGa0BSeiBCZl1Wdz52bjByclRXeiBiZvBiclJWb15GIlhGdgYWS4ycuJXd0VmcgQmbhBSnAKOdzVWdxVmcgAFVUhEIkVjavascript:alert(1)">Unexpected url</a>
记录下<a href="
和javascript:alert(1)">Unexpected url</a>
之间的部分,拿到Burp的请求包中搜索
删除搜索到的最后一块结果,多次重放(可能要发包七八次才成功一次),就可以了
没看懂没关系,这里我用Python生成的长度为500的随机字符串来演示一下
import random
import string
def get_random_string(length):
return ''.join(random.choice(string.ascii_letters) for _ in range(length))