记一次出ctf中出xss题目
0x00 问题分析
xss一般的出题思路是考一些绕过,或者一些常见函数,利用这些使用户浏览器弹窗,但是最终的弹窗结果是显示在用户浏览器端的,单纯的借助php是没办法在浏览器验证是否造成了弹窗的(也可能是有办法我没发现),以前做过一些CTF关于xss的题目,有的考编码绕过,当用户提交含有绕过编码的字段,就直接给出flag(bugku xss),还有一些是通过浏览器端js判断,但是只要用户读懂js就可以不通过弹窗直接可以get flag(hackinglab xss),等等吧,感觉都不怎么理想。
0x01解决
解决思路来源于这位大佬的博客,但是这位大佬是用js写的,我的js比较水,就用php完成的这个题目
思路:
- phantomjs是一个没有图形界面的浏览器,可以直接使用少量js+phantomjs本身提供的函数和接口(好像也提供了php的接口)直接操作。
- 利用php中的exec或者system之类的函数执行系统命令,调用js打开操作phantomjs验证弹窗等,并输出返回值,判断是否给出flag
实际操作
环境部署
- 搭建lamp,我是再centos7上弄的,具体的搭建过程就不详细描述了
安装nodejs,大概这样三条命令
1
2
3yum info epel-release
yum install nodejs
node -v安装phantomjs,命令如下
1
2npm install phantomjs -g
phantomjs --version具体过程中可能要关闭selinux,操作如下
1
2setenforce 0(暂时)
修改/etc/selinux/config文件中的SELINUX="" 为 disabled ,然后重启。(永久)
这样环境就基本搭建完了,可以在命令行中试一下phantomjs,其实还是挺有意思
代码实现
js调用phantomjs验证
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29var webPage = require('webpage');
var page = webPage.create();
var postBody = 'id=1';
var url = 'http://127.0.0.1/verification.php'
//接收命令行参数 第一个要验证是否能弹窗的js的base64(也可以不用加密) 第二个验证的是网页地址base64
var system = require('system');
if (system.args.length === 1) {
//console.log('Try to pass some args when invoking this script!');
phantom.exit();
} else {
system.args.forEach(function (arg, i) {
if(i === 1){
postBody = 'id='+ atob(arg);
}
if(i ===2 ){
url = atob(arg);
}
});
}
page.open(url,'POST',postBody,function(status) {//打开网页
//console.log('Status: ' + status);//获取加载消息
//console.log(page.content);//获取页面内容
//page.render('aa.png');//获取屏幕截图
phantom.exit();
});
page.onAlert = function(msg) {//获取alert弹窗消息 比如如果执行了alert('key')就会输出key 没弹框的话就什么都不输出
console.log(msg);
};php调用js ,这个没什么说的,就是一个系统命令执行,注意防一下命令执行,还有就是直接用nodejs就不会有这个问题
1
2exec('phantomjs --output-encoding=utf8 verification.js '.base64_encode(iconv('utf-8','gbk',$_key)).' '.base64_encode(iconv('utf-8','gbk',$_url)),$output_main);
//其实就是 exec('命令',$返回值) 注意编码,还有就是返回值是数组形式的可以用count()之类的函数判断是否为空需要注意的地方:
js代码一定要写对,效率要高,js一旦出问题会卡好久,应该会占用一部分资源
php中要做好防止命令执行
还有一个就是一定要想好逻辑,避免出现死循环,比如:你用ctfer访问的页面去验证是否弹窗,那是不是当phantomjs的验证弹窗操作也会被服务器理解为成ctfer的提交操作,然后再调用phantomjs去验证。。。。然后服务器就崩溃了,这里一定要注意,我想出的解决方法就是在代码中把phantomjs和ctfer分开,传个key值什么的,也可以写一个简单的验证页面(echo $_POST(‘id’);这种的),就可以解决这个问题0x02 附:关于csrf
这次出题我还出了一个关于csrf,大致就是利用xss平台或者自己搭建网站获取管理员cookie,然后冒充管理员登录getflag,其实本来没什么说的,但是中间遇到了一个phantomjs模拟登录后进如登录后的界面的问题,以前我写登录一般都是直接用js跳转的,但是这个phantomjs没办法得到js跳转后的页面,这样模拟管理员登录查看留言时,管理员就看不到留言,后来使用php的header()函数解决
0x03 再附:一些参考文件
- phantomjs官网,可以查询一些函数接口 什么的
- 大佬博客讲怎么用js出xss题目的
- 附上我的题目代码这个代码还有一个bug,熟悉js的可以再优化一下