目录
一.XSS概述
跨站脚本攻击(Cross-Site Scripting,XSS)是一种常见的网络安全漏洞,攻击者通过在网页上注入恶意脚本代码,从而在用户的浏览器上执行恶意操作。这些脚本可以是 JavaScript、HTML 或其他网页脚本语言。一旦用户在受感染的网页上进行交互,如点击链接或填写表单,恶意脚本就会在用户浏览器上执行,从而导致多种安全问题,包括但不限于:
- 窃取用户信息:攻击者可以利用 XSS 漏洞窃取用户的敏感信息,如用户会话 cookie、登录凭证等。
- 会话劫持:通过获取用户的会话信息,攻击者可以冒充合法用户,执行未授权的操作。
- 网页篡改:攻击者可以修改网页内容,显示虚假信息,诱导用户点击恶意链接或下载恶意文件。
- 钓鱼攻击:攻击者可以伪装成合法网站或服务,诱骗用户输入敏感信息,如用户名、密码、信用卡信息等。
XSS 漏洞通常出现在没有充分验证用户输入的地方,比如网站的搜索框、评论区、表单提交等。预防 XSS 攻击的方法包括对用户输入进行严格过滤和转义,使用安全的开发框架和编程语言,以及定期对网站进行安全审计和漏洞扫描。
二.XSS漏洞分类
XSS攻击主要分为三种类型:
- 存储型XSS:恶意脚本被存储在服务器上(如数据库),当用户请求该数据时,脚本被执行。
- 反射型XSS:恶意脚本作为请求的一部分被立即反射回用户的浏览器,通常通过URL参数或表单提交。
- DOM型XSS:攻击者通过修改网页的DOM结构来执行恶意脚本,通常依赖于客户端的JavaScript。
1.反射型XSS漏洞
定义:反射型XSS是非持久性、参数型跨站脚本。反射型XSS的JS代码在web应用的参数(变量)中,如搜索框的反射型XSS。
特点:这种攻击方式往往具有一次性。
攻击方式:攻击者通过电子邮件等方式将包含xss代码的恶意链接发送给目标用户。当目标用户访问该链接时,服务器接收该目标用户的请求并进行处理,然后服务器把带有xss代码的数据发送给目标用户的浏览器,浏览器解析这段带有xss代码的恶意脚本后,就会触发xss漏洞。
举个栗子:
<?php
ini_set("display_errors", 0);
$str = $_GET["name"];
echo "<h2 align=center>欢迎用户".$str."</h2>";
?>
<center><img src=level1.png></center>
<?php
echo "<h3 align=center>payload的长度:".strlen($str)."</h3>";
?>
我们将URL中的参数修改为?name=<script>alert(/xss/)</script>
,测试是否触发弹窗。回车可以看到弹出窗口,说明网站后台未对输入参数进行过滤,存在xss漏洞。
以上为一个简单的反射型漏洞
2.DOM型XSS漏洞
定义:DOM型XSS比较特殊。owasp关于DOM型XSS的定义是基于DOM的XSS是一种XSS攻击,其中攻击的payload由于修改受害者浏览器页面的DOM树而执行的。其特殊的地方就是payload在浏览器本地修改DOM树而执行,并不会传到服务器上,这也就使得DOM型XSS比较难以检测。
网页的生成及修改:
在网站页面中有许多元素,当页面到达浏览器时,浏览器会为页面创建一个顶级的Document
object文档对象,接着生成各个子文档对象,每个页面元素对应一个文档对象,每个文档对象包含属性、方法和事件 。
可以通过JS脚本对文档对象进行编辑,从而修改页面的元素 。 也就是说,客户端的脚本程序可以通过DOM动态修改页面内容,从客户端获取DOM中的数据并在本地执行。由于DOM是在客户端修改节点的,所以基于DOM型的xss漏洞不需要与服务器端交互,它只发生在客户端处理数据的阶段。
攻击方式:用户请求一个经过专门设计的URL,它由攻击者提交,而且其中包含XSS代码。服务器的响应不会以任何形式包含攻击者的脚本。 当用户的浏览器处理这个响应时, DOM对象就会处理XSS代码,导致存在XSS漏洞 。
举个栗子:
<!-- Challenge -->
<form id="ricardo" method="GET">
<input name="milos" type="text" class="form-control" placeholder="True" value="True">
</form>
<script>
ricardo.action = (new URL(location).searchParams.get('ricardo') || '#')
setTimeout(_ => {
ricardo.submit()
}, 2000)
</script>
orm表单的action属性接受传参,2s后自动提交。而对于action属性,我们应该第一时间想到javascript伪协议
对于javascript伪协议,还有a标签的herf属性,,button标签的formaction属性,ifram标签的src属性,windows.location下
ricardo=javascript:alert(1)
3.存储型XSS漏洞
定义:存储型XSS是持久性跨站脚本,持久性体现在xss代码不是在某个参数(变量)中,而是写进数据库或文件等可以永久保存数据的介质中。存储型XSS通常发生在留言板等地方。我们在留言板位置留言,将恶意代码写进数据库中。
特点:攻击脚本将被永久地存放在目标服务器的数据库或文件中,具有很高的隐蔽性。
攻击方式:这种攻击多见于论坛、博客和留言板,攻击者在发帖的过程中,将恶意脚本连同正常信息一起注入帖子的内容中。随着帖子被服务器存储下来,恶意脚本也永久地被存放在服务器的后端存储器中 。 当其他用户浏览这个被注入了恶意脚本的帖子时,恶意脚本会在他们的浏览器中得到执行 。所以需要浏览器从服务器载入恶意的xss代码,才能真正触发xss。
这里以原型链污染为例
JavaScript原型链继承
JavaScript 规定,每个函数都有一个prototype
属性,指向一个对象,所有类对象在实例化的时候将会拥有prototype
中的属性和方法,这个特性被用来实现JavaScript中的继承机制。
function Father() {
this.first_name = 'Donald'
this.last_name = 'Trump'
}
function Son() {
this.first_name = 'Melania'
}
Son.prototype = new Father()
let son = new Son()
console.log(`Name: ${son.first_name} ${son.last_name}`)
Son类继承了Father类的
last_name
属性,最后输出的是Name: Melania Trump
。总结一下,对于对象son,在调用
son.last_name
的时候,实际上JavaScript引擎会进行如下操作:
在对象son中寻找last_name
如果找不到,则在
son.__proto__
中寻找last_name如果仍然找不到,则继续在
son.__proto__.__proto__
中寻找last_name依次寻找,直到找到
null
结束。比如,Object.prototype
的__proto__
就是null
在javascript中,每个对象的都有一个指向他的原型(prototype)的内部链接,这个原型对象又有它自己的原型,直到null为止
test--->prototype---->原型对象(test的父类)----->Function------>Object------>null
原型链污染定义:如果攻击者控制并修改了一个对象的原型,那将可以影响所有和这个对象来自同一个类、父类的对象,这种攻击方式就是原型链污染
举个栗子:
let o1 = {};
let o2 = JSON.parse('{"a":1,"__proto__":{"b":2}}');
merge(o1,o2);
console.log(o1.a,o2.b);
o3 = {};
console.log(o3.b);
解析:
JSON解析的情况下,__proto__会被认为是一个真正的“键名”,不代表原型,所以在遍历o2的时候存在这个键,新建的o3对象,也存在b属性,说明object已被污染