记一次出ctf中出xss题目

Author Avatar
ssssdl 9月 25, 2018

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
    3
    yum info epel-release
    yum install nodejs
    node -v
  • 安装phantomjs,命令如下

    1
    2
    npm install phantomjs -g
    phantomjs --version
  • 具体过程中可能要关闭selinux,操作如下

    1
    2
    setenforce 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
    29
    var 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
    2
    exec('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的可以再优化一下