- XSS基本概念和原理说明
XSS的基本概念
XSS又叫CSS (Cross Site Script) ,跨站脚本攻击。它指的是恶意攻击者往Web页面里插入恶意html代码,当用户浏览该页之时,嵌入其中Web里面的html代码会被执行,从而达到恶意的特殊目的。XSS属于被动式的攻击,因为其被动且不好利用,所以许多人常呼略其危害性。xss是一种发生在web前端的漏洞,所以其危害的对象也主要是前端用户
在WEB2.0时代,强调的是互动,使得用户输入信息的机会大增,在这个情况下,我们作为开发者,在开发的时候,要提高警惕。
xss漏洞可以用来进行钓鱼攻击,前端js挖矿,用户cookie获取。甚至可以结合浏览器自身的漏洞对用户主机进行远程控制
XSS原理说明
XSS攻击方法只是利用HTML的属性,作各种的尝试,找出注入的方法。现在对三种主要方式进行分析。
1.第一种:对普通的用户输入,页面原样输出,用户通过对JSCODE的伪装,经过一些操作就会跳出一个木马界面,取得登录用户的Cookie.
2.第二种:在代码区里有用户输入的内容
原则就是,代码区中,绝对不应含有用户输入的东西。
3.第三种:允许用户输入HTML标签的页面。
用户可以提交一些自定义的HTML代码,这种情况是最危险的。因为,IE浏览器默认采用的是UNICODE编码,HTML编码可以用&#ASCII方式来写,又可以使用”/”连接16进制字符串来写,使得过滤变得异常复杂
- 反射型、储存型、DOM型实战
反射型XSS(get型不持久型XSS)
交互的数据一般不会被存在在数据库里面,只是简单的把用户输入的数据反射给浏览器,一次性,所见即所得。
<?php
$name = $_GET['name'];
echo "Welcome $name<br>";
?>
中危漏洞
储存型XSS 或持久型 XSS
交互的数据会被存在在数据库里面,永久性存储,具有很强的稳定性。
除非管理员删除
高危漏洞
DOM XSS
不与后台服务器产生数据交互,通过前端的dom节点形成的XSS漏洞,跟服务器无关。一般无法产生危害链接,很难被利用(低微漏洞)
什么是DOM:DOM全称是Document Object
Model,也就是文档对象模型。我们可以将DOM理解为,一个与系统平台和编程语言无关的接口,程序和脚本可以通过这个接口动态地访问和修改文档内容、结构和样式。
当创建好一个页面并加载到浏览器时,DOM就悄然而生,它会把网页文档转换为一个文档对象,主要功能是处理网页内容。故可以使用Javascript 语言来操作DOM以达到网页的目的。
- XSS钓鱼
xss钓鱼测试
这里我们进入存储型xss实验
我们发现方框,进行注入js代码,输入
进行代码审计可知
我们发现代码出现了发送认证框,并将信息传送到后台
提交后出现登录框,输入默认密码
进行登录后,就那个入后台查看钓鱼结果
- XSS平台搭建及Cookie获取
开启PHPstudy
在浏览器上输入127.0.0.1/XXS 进入蓝莲花注册页面
只需要修改登录密码进行提交。
然后进入登录页面。
下次进入蓝莲花应该是:http:IP/XXS/login.php
dvaw也同样放在PHPstudy的WWW目录下
然后修改文件配置
WWW\DVWA\config
将文件类型修改为php
然后输入127.0.0.1/dvwa 进行登录
初始账号密码都是admin password
进行简单的cookie值提取使用
1.进入DVWA页面,选择XSS(stored)界面。
2.使用蓝莲花
先阅读好公用模板,看看自己想使用的模板
点击我的js
然后进行添加
复制payload然后在DVWA进行XSS
修改一下字符长度限制
提交
XSS平台面板就会收到消息
复制cookie
进入DVWA的登录页面
也可以F12更换cookie值
然后直接访问index.php页面
登陆成功
- 反射型XSS(POST)获取用户密码
反射型XSS(post)获取用户密码
跟反射型(get)的不同之处
post是无法在URL中插入payload的
是需要插入内容到数据包的
那么如何将数据包这种类型的攻击发送给用户呢
通过html页面方式提交,构造一个自己的post
丢到自己的网站上
get型xss是直接更改URL就可以了,可以直接在参数后加payload
pikachu\pkxss\xcookie目录解读
post .html解读
使用了from表单方式模拟了post提交数据包+页面URL地址,之后获取用户的cookie上传到攻击者数据库
对这段代码进行 windows.onload,点击自动点击提交按钮
post攻击利用页面 D:\phpStudy\WWW\pikachu\pkxss\xcookie\post.html
http://192.168.0.103:8080/post.html
前提条件:用户要登录
- XSS获取键盘记录
我们来到pikachu,进入xss的存储型
我们首先来看一下后台,在pikachu xss的后台有键盘记录这么一个目录
我们需要去嵌入一个能够调用我们的远程js的方法
把这段代码放进去,点提交后,这个js就被嵌入到这个页面中了
我们打开控制台,在页面上随便输入一个键盘,他会显示页面请求失败
这就是同源策略的好处,做了一道安全措施,但是1.15这个网站是攻击者自己建立的,所以他可以允许任何人来访问它
然后我们重新打开xss的存储页面
我们随便输入几个数字,会发现我们的js能把我们的输入全都抓下来
这边在网页上就能记录下来了
- XSS盲打
XSS盲打:它不是一种XSS漏洞的类型,它其实是一种XSS一种的攻击场景。
以下来实施XSS的一种盲打
1.打开pikachu里的XSS的盲打
- 输入一个字符来测一下看它有什么样的作用,点击提交后显示如图这句话:
仿佛在说我们输入的内容并不会在前端输出,看起来好像是被提交到了后台,它的管理员有可能会被看,只有他的管理员能看到我输入的内容,前端的用户是看不到的
3.我们来设想一种场景比如说它这边有个管理员在后台见面,我们输入的内容,跨占脚本的内容 ,这个内容也不会在前端输出,根据刚刚的思路管理员登录后台之后后台的内容会把我们输入的内容输出的话,就意味着后台的管理员会被查到,如果真的会被查到这种场景,那这种场景存在的XSS,我们会称这种场景XSS的盲打
- 点击右上角的“点一下提示”里的后台登录地址,复制这个地址在uil登陆一下,这个时候我们就会切换成管理员,然后他要查一下用户给他的发的一些看法,然后登录
登录之后就会看到如下图所示,就会被查
因为它的这个管理页面会执行前端输入的内容,它换的脚本会在下一个页面执行,它查的就是管理员。
对于攻击者来说他并不知道后台有没有输出,或是说它输出时有没有做过滤,它只是尝试性的注入一段恶意的跨段脚本,运气好它后端没有做处理,那后端输出的时候他把管理员给查到了,攻击者就成功了。
这种XSS漏洞的本质还是我们之前说的XSS的存储型,你前端的内容输出,你前端的内容输入,被后台存下来了又在后台的页面上输出了,这时危害的攻击就比较大的,因为攻击者可以直接通过在前段注入一段cookie的脚本,然后管理员登录后台之后,他就直接就把管理员的cookie获取到,照管理员登录后台。
- XSS防御绕过
绕过
XSS 绕过方法很多,涉及到的面也非常广泛,我们这里只记录常见的一些绕过方式。
1,最基本的就是利用 <> 来写入 html 和 js 代码,例如以下示例。
<script>alert(1);</script>
所以对于防 xss 首先就需要过滤和转义 <、>、<script>等字符。
2,利用 html 标签属性值来执行 xss,很多 html 标签的属性都支持 javascript:[code] 伪协议的形式,其声明了用 js 来执行 code 代码,例如以下示例。
<table background="javascript:alert(1)"></table>
<img src="javascript:alert(1);">
当然并不是所有的浏览器都会这样执行,有些浏览器并不支持 js 伪协议,所以这种方式有其局限性,我们示例就使用这种伪协议了,当然 script、on 等关键字都同样适用,同时我们也可以看见,防御 xss 一定要过滤 js 的关键字。
3,空格回车 Tab 方式,如果程序把敏感字符和关键字进行了过滤,那么我们可以利用空格、回车、Tab 等来尝试绕过,例如以下示例。
<img src="javas cript:alert(1)">
<img src="javas__ cript:__ alert(1)">
以上第一个在 javascript 中插入了 tab 键,第二个使用了回车,除了 tab 我们也可以使用回车空格等,在 script 和各种 on 事件中也可以使用,js 解析时会以分号来判断一个语句是否结束,所以添加空格、回车、tab 等并不会影响语句的正常执行。
4,对标签属性值进行转码,在 html 的属性中是支持 ASCII 码的,因为计算机只能接受数字信息,所以 ASCII 码会将字符作为数字来表示,例如以下示例。
<img src="javascript:alert(1);">
<img src="javascript:alert(1);">
t 的 ascii 码为 116,:的 ascii 码为 58,以上是转码后的效果,同理,以下代码同样会生效。
<img src=""javascript:alert(1);"/">
<img src=""javascript:alert(1);"/">
上面第二个例子每个字符加了四个 0,ascii 码中加入随意个 0 其效果是不变的,同时也可以结合换行、回车、Tab 等,tab 为 ,换行为 ,回车为 ,它们可以插入到代码的任意地方。所以我们除了过滤关键字外,最好也过滤 &、# 等特殊字符。
5,事件跨站,当属性值不能进行利用时,可以利用 js 的一些事件进行跨站,例如 click、mouseover、load 等,例如以下示例。
<input type="button" value="button" οnclick="alert(1)"/>
<img src="0" οnerrοr="alert(1)">
6,利用 css 进行跨站,xss 的另一个载体是 css,优点在于灵活隐蔽,缺点在于可能浏览器不会通用。示例如下。
<div style="background-image:url(javascript:alert(1))">
<style>body{background-image:url("javascript:alert(1)");}</style>
在 ie5 以后 css 支持使用 expression,expression 会执行放入的 js 代码,例如以下示例。
<div style="width:expression(alert(1));">
<style>body{background-image:expression(alert(1));}</style>
除了嵌入到 html 代码中外,也可以通过其他服务器进行 css 文件的引入,例如 link 标签的使用,假设 xxx.com/xxx.css 文件内容如下。
p{background-image:expression(alert(1));}
这时在目标程序中使用的 payload 则为:
<link rel="stylesheet" href="xxx.com/xxx.css">
除上面的 link 可以引入外部的 css 文件外,还有一种方式就是 @import,其使用示例如下。
<style type='text/css'>@import url(http://www.xxx.com/xxx.css);</style>
@import 除了可以引入 css 文件外,还有一个特性就是可以直接执行 js 代码,其使用示例如下。
<style>@import 'javascript:alert(1)';</style>
通过上面记录可知,我们除了过滤 script 关键字、&、#、<、> 等特殊字符外,也应该把 expression、javascript、import 等关键字也进行过滤。
7,扰乱过滤规则,扰乱规则也有很多种,常见的就是大小写转换,示例如下。
<IMG SRC="javaScripT:alErt(1);"
不使用双引号,使用单引号,示例如下。
<img src="javascript:alert(1);">
不使用引号的,示例如下。
<img src="javascript:alert(1);">
空格使用 / 来代替,示例如下。
<img src="javascript:alert(1);">
当使用 expression 执行跨站代码时,可以使用全角字符来绕过。
<div style="{left:expression(alert(1))}">
在样式表中,/**/ 会被浏览器忽略,所以可以用 /**/ 注释字符来进行绕过,示例如下。
<div style="wid/****/th:expre/*xss*/ssion(alert(1));">
对于跨站,基本很多系统都会使用黑名单的方式,白名单在这里可能不太使用,那么也可以通过双写来绕过,示例如下。
<scrScrIPtipt>alAlerTert(1)</sscriptcript>
在样式表中,和 0 也会被浏览器忽略,示例如下。
@\im\port '\0java\0script:alert(1)';
@\0000i\0000m\0000p\0000o\0000r\0000t 'url';
- 利用字符编码,字符编码我们可以在线 xssor.io 辅助一下,下面使用一下十六进制和十进制的编码,在 html 中,很多属性都支持 &#ascii 编码的方式,xssor 见下图。
示例如下。
<img src="javascript:alert(1);"> //原型
<img src="javascript:alert(1);"> //十六进制
<img src="javascript:alert(1);"> //十进制
使用选项截图分别如下。
&# 后的 0 可以随意输入,xssor 最后提供了 replace 替换功能,可以使用此功能进行 0 的添加删除和修改。
js 中有一个 eval 函数,它可以执行 js 代码,并支持十六进制和十进制,我们可以使用 / 连接十六进制字符,十进制需要 string.fromCharCode 函数结合,string.fromCharCode 作用是通过 ascii 码来获取字符内容,示例如下。
<script>eval("\61\6c\65\72\74\28\31\29");</script>
<img src="javascript:eval(String.fromCharCode(97,108,101,114,116,40,49,41))">
- jsfuck 绕过,jsfuck 是一种 js 编程风格,它会把 js 代码用六个字符来表示,[]()+! 其网站是 jsfuck.com,如果程序过滤了各种关键字,而没有过滤这六种符号的话,则可以进行尝试,只不过生成的字符会比较多,可能超出字符范围限制,利用时也可以外部引入等,示例图如下。
把编码后的代码放到网页会被直接解析执行,效果图如下。
以上就是常用的 xss 绕过方式,xss 绕过根据浏览器的不同环境不同可能会存在差异
防御
对于防御一般有两种方式,即 input filtering 和 output filtering 两种,即输入过滤和输出过滤。对于输入过滤,可以进行输入验证和数据消毒。输入验证即用来检测用户的输入是否合法,例如前端的手机号规则验证,邮箱验证等,是否超过最大限制,在前端 js 验证后,后端也应该进行验证,避免前端被绕过的可能。数据消毒即过滤特殊字符和关键字,例如 <>&#'" 等,关键字 script、javascript、expression、on 事件等。对于输出过滤我们可以进行输出编码 htmlencode,例如 < 的实体名字 & lt;实体编号 <;对这种类似的符号做编码和转义可以有效的防止跨站攻击。现在基本常见的后端程序也都有提供类似的编码,例如 asp 的 server.htmlencode,php 的 htmlspecialchars 等。
同时在进行输出编码时,需要根据上下文的环境进行不同的编码,例如内容是输出到网页内容中,则需要用 html 实体代替,例如:
< 转换为 & lt;
> 转换为 & gt;
& 转换为 & amp;
" 转换为 & quot;
''
如果内容是输出到标签中,例如一些标签的属性值,这个和输入到网页中的处理一样,对敏感字符进行转义实体代替。
< 转换为 & lt;
> 转换为 & gt;
& 转换为 & amp;
" 转换为 & quot;
''
如果内容是输出到 script 标签中的,则需要对敏感字符进行编码过滤,示例如下。
'单引号转为 /'
"双引号转为 /"
反斜杠转为 \\
/ 正斜杠转为 \/
/n 换行转为 / n
/r 回车转为 / r
总体来说就是未受信任的数据嵌入到页面前都应该按照上下文进行对应的编码。
而对于 DOMXSS 来说,并没有对后端产生交互,所以后端过滤规则对 DOMXSS 不会生效,防御 DOMXSS 需要注意的一个是避免客户端文档重写,重定向或其他敏感操作,同时避免使用客户端数据,这些操作尽量在服务端使用动态页面来实现。再一个是分析和强化客户端的 js 代码,尤其是受到用户影响的 dom 对象,例如 document.url,document.location,document.referrer 等。
以上是进行输入和输出编码的处理方式,除此之外建议对用户登录的 cookie 做 httponly 属性,在跨站的攻击中,基本都会使用 document.cookie 来盗取用户的 cookie 信息,所以建议设置 httponly。
- XSS绕过之htmlspecialchars()函数
htmlspecialchars函数绕过
进行该实验,代码审计可知
由原理可知,该函数过滤掉了大部分符号,但没定义quotestyle类型,默认知识过滤了双引号
可以利用zhian’ οnclick=‘alert(111)’;
进行注入实验,或者试试我刚刚补充的代码
(10)XSS安全防御
XSS的防御是复杂的。流行的浏览器都内置了一些对抗XSS的措施,比如Firefox的CSP,Noscript扩展,IE8内置的XSS Filter等。而对于网站来说,也应该寻找优秀的解决方案,保护用户不被XSS攻击。
1)HttpOnly
HttpOnly最早是由微软提出,并在IE 6中实现的,至今已成为一个标准。浏览器将禁止页面的JavaScript访问带有HttpOnly属性的Cookie。严格来说,HttpOnly并非为了对抗XSS--HttpOnly解决的是XSS后的Cookie劫持。
之前的文章中提到过”如何使用XSS窃取用户的Cookie,然后登录进该用户的账户“。但如果该Cookie设置了HttpOnly,则这种攻击会失败,因为JavaScript读取不到Cookie的值。
一个Cookie的使用过程如下:
Step1:浏览器向服务器发起请求,这时没有Cookie。
Step2:服务器返回时发送Set-Cookie头,向客户端浏览器写入Cookie。
Step3:在该Cookie到期前,浏览器访问该域下的所有页面,都将发送该Cookie。
HTTPOnly是在Set-Cookie时被标记的。服务器可能会设置多个Cookie(多个key-value对),而HttpOnly可以有选择性地加在任何一个Cookie值上。在某些时候,应用可能需要JavaScript访问某几项Cookie,这种Cookie可以不设置HttpOnly标记;而仅把HttpOnly标记给用于认证的关键Cookie。
HttpOnly的使用非常灵活,如下是一个使用HttpOnly的过程。
<?php
header("Set-Cookie: cookie1=test1;");
header("Set-Cookie: cookie2=test2;httponly", false);
?>
<script>
alert(document.cookie);
</script>
在这段代码中,cookie1没有HttpOnly,cookie2被标记为HttpOnly。但是只有cookie1倍JavaScript读取到:
HttpOnly起到了应有的作用。