存储型XSS,顾名思义,就是会传入数据库,长久的使用,常见为留言板,用户信息资料。

LOW

审计源码

<?php
// 是否提交 btnSign
if( isset( $_POST[ 'btnSign' ] ) ) {
// 获取输入的mtxMessage和txtName
// trim() 首位去空
$message = trim( $_POST[ 'mtxMessage' ] );
$name = trim( $_POST[ 'txtName' ] ); // stripslashes() 将特殊字符前加入 \ 转义
// mysqli_real_escape_string() 转义特殊字符 NUL (ASCII 0),\n,\r,\,',"
// 对 message 特殊字符转义
$message = stripslashes( $message );
$message = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"], $message ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : "")); // 对 name的特殊字符进行转义
$name = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"], $name ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : "")); // 将message 和 name 写入到 guestbook 表中 comment 和 name 字中
$query = "INSERT INTO guestbook ( comment, name ) VALUES ( '$message', '$name' );";
$result = mysqli_query($GLOBALS["___mysqli_ston"], $query ) or die( '<pre>' . ((is_object($GLOBALS["___mysqli_ston"])) ? mysqli_error($GLOBALS["___mysqli_ston"]) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '</pre>' ); //mysql_close();
} ?>

对传入的messagename进行了转义,防止了SQL注入,对于XSS来说,这些转义没什么用

message内容中输入<script>alert(document.cookie)</script>

Nmae随便输入一个



点击提交



可以看到弹窗成功,这样每次刷新都会进行弹窗,为了方便我们测试,弹窗之后点击Clear Gueskbook

清楚之前的弹窗



进行清空数据

这是这是测试,反弹cookie可见另一篇博客:DVWA-XSS (DOM) DOM型跨站脚本攻击

Medium

审计源码

<?php
// 查看是否提交 btnSing
if( isset( $_POST[ 'btnSign' ] ) ) {
// 获取传入的 mtxMessage 和 txtName
// trim() 首位区控
$message = trim( $_POST[ 'mtxMessage' ] );
$name = trim( $_POST[ 'txtName' ] ); // 过滤传入 message
// addslashes() 使用反斜线引用字符串
// strip_tags() 去除HTML标签
$message = strip_tags( addslashes( $message ) );
$message = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"], $message ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : ""));
// 对 message 中的 HTML 标签进行实例化操作
$message = htmlspecialchars( $message ); // 对 name 进行过滤
// str_replace() 替换 <script> 为空
$name = str_replace( '<script>', '', $name );
$name = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"], $name ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : "")); // 跟新数据库
$query = "INSERT INTO guestbook ( comment, name ) VALUES ( '$message', '$name' );";
$result = mysqli_query($GLOBALS["___mysqli_ston"], $query ) or die( '<pre>' . ((is_object($GLOBALS["___mysqli_ston"])) ? mysqli_error($GLOBALS["___mysqli_ston"]) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '</pre>' ); //mysql_close();
} ?>

这里对message进行了严格的过滤,首选去除了其中的HTMl标签,让后又使用htmlspecialchars函数message进行了实例化操作

这里转到name传参,过滤了<script>标签,根据str_replace函数特性,只会过滤一次,所以这里可以进行双写绕过

测试

<scr<script>ipt>alert(document.cookie)</script>



发现只能输入10个字符,在前段做了限制,检查找到name输入框



maxlength="10"改为100



再次测试<scr<script>ipt>alert(document.cookie)</script>



可以输入,提交查看



成功弹出cookie

High

审计源码

<?php
// 判断传入的 btnSign
if( isset( $_POST[ 'btnSign' ] ) ) {
// 获取传入的 mtxMessage、txtName
$message = trim( $_POST[ 'mtxMessage' ] );
$name = trim( $_POST[ 'txtName' ] ); // 跟上次一样的过滤,message已经被封死了
$message = strip_tags( addslashes( $message ) );
$message = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"], $message ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : ""));
$message = htmlspecialchars( $message ); // 使用 preg_replace 正则匹配 <script> 标签
$name = preg_replace( '/<(.*)s(.*)c(.*)r(.*)i(.*)p(.*)t/i', '', $name );
$name = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"], $name ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : "")); // 更新数据库
$query = "INSERT INTO guestbook ( comment, name ) VALUES ( '$message', '$name' );";
$result = mysqli_query($GLOBALS["___mysqli_ston"], $query ) or die( '<pre>' . ((is_object($GLOBALS["___mysqli_ston"])) ? mysqli_error($GLOBALS["___mysqli_ston"]) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '</pre>' ); //mysql_close();
} ?>

代码只有对name过滤的规则发生了变化,使用preg_replace<script>进行了严格的过滤

.*除了换行匹配所有,/i为不区分大小写,所以这次双写绕过也无法使用

使用<img />标签src属性自动请求特性,进行弹窗

首先修改name输入的长度



name输入<img src=1 onerror=alert(document.cookie) />



提交查看



成功弹窗

Impossible

审计源码

<?php
// 是否传入 btnSign
if( isset( $_POST[ 'btnSign' ] ) ) {
// 检查 user_token
checkToken( $_REQUEST[ 'user_token' ], $_SESSION[ 'session_token' ], 'index.php' ); // 获取传入的 mtxMessage、txtName
$message = trim( $_POST[ 'mtxMessage' ] );
$name = trim( $_POST[ 'txtName' ] ); // 对message中的标签进行实例化
$message = stripslashes( $message );
$message = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"], $message ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : ""));
$message = htmlspecialchars( $message ); // 对name中的标签进行实例化
$name = stripslashes( $name );
$name = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"], $name ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : ""));
$name = htmlspecialchars( $name ); // 使用PDO方法更新数据库
$data = $db->prepare( 'INSERT INTO guestbook ( comment, name ) VALUES ( :message, :name );' );
$data->bindParam( ':message', $message, PDO::PARAM_STR );
$data->bindParam( ':name', $name, PDO::PARAM_STR );
$data->execute();
} // 生成user_token
generateSessionToken();

message和name进行了HTML实例化,检查了了user_token,使用PDO方法进行数据库查询,经典的防御

DVWA-XSS (Stored) 存储型XSS的更多相关文章

  1. 富文本存储型XSS的模糊测试之道

    富文本存储型XSS的模糊测试之道 凭借黑吧安全网漏洞报告平台的公开案例数据,我们足以管中窥豹,跨站脚本漏洞(Cross-site Script)仍是不少企业在业务安全风险排查和修复过程中需要对抗的“大 ...

  2. 风炫安全WEB安全学习第二十一节课 存储型XSS讲解

    风炫安全WEB安全学习第二十一节课 存储型XSS讲解 存储型XSS演示 存储型XSS,持久化,代码是存储在服务器中的,如在个人信息或发表文章等地方,加入代码,如果没有过滤或过滤不严,那么这些代码将储存 ...

  3. DVWA 黑客攻防演练(十一) 存储型 XSS 攻击 Stored Cross Site Scripting

    上一篇文章会介绍了反射型 XSS 攻击.本文主要是通过 dvwa 介绍存储型 XSS 攻击.存储型 XSS 攻击影响范围极大.比如是微博.贴吧之类的,若有注入漏洞,再假如攻击者能用上一篇文章类似的代码 ...

  4. DVWA之Stored XSS(存储型XSS)

    目录 Low Medium High Impossible Low 源代码: <?php if( isset( $_POST[ 'btnSign' ] ) ) { // Get input $m ...

  5. DVWA(七):XSS(stored)存储型XSS攻击

    存储型XSS : 存储XSS,会把攻击者的数据存储在服务器端,攻击行为将伴随着攻击数据一直存在.提交JS攻击代码存储到数据库然后再输出. low: 观察源码: <?php if( isset( ...

  6. 存储型XSS

    DVWA系列(二)存储型XSS https://www.imooc.com/article/284686 网络安全:存储型XSS https://blog.csdn.net/qq_41500251/a ...

  7. 利用mysql对特殊字符和超长字符会进行截断的特性 进行存储型XSS攻击——WordPress <4.1.2 & <=4.2 存储型xss

    转自:Baidu Security LabXteam http://xteam.baidu.com/?p=177 漏洞概述 本次漏洞出现两个使用不同方式截断来实现的存储型xss,一种为特殊字符截断,一 ...

  8. Coremail邮件系统存储型XSS两个

    (1):Coremail邮件系统存储型XSS之一 给受害者发送主题如下的邮件: <svg onload='img=new Image();img.src="//x55.me/geo.p ...

  9. 小白日记49:kali渗透测试之Web渗透-XSS(三)-存储型XSS、DOM型XSS、神器BEFF

    存储型XSS与DOM型XSS [XSS原理] 存储型XSS 1.可长期存储于服务器端 2.每次用户访问都会被执行js脚本,攻击者只需侦听指定端口 #攻击利用方法大体等于反射型xss利用 ##多出现在留 ...

  10. Java Web开发 - 持久型/存储型XSS漏洞

    Java Web开发 - 持久型/存储型XSS漏洞 1.什么是XSS漏洞攻击? XSS是跨站脚本攻击(Cross Site Scripting)的简称,之所以叫XSS而不是CSS相比大家都能明白了吧, ...

随机推荐

  1. evalJS代替mui.fire

    之前一直用mui.fire调用自定义事件以达到监听目标窗口的目的. 页面为双webview,页面跳转时 mui.openWindow({ url: '../choose/food-choose-con ...

  2. Linux-centos7 下开放某个端口

    方式一 1.开启防火墙 systemctl start firewalld  2.开放指定端口 firewall-cmd --zone=public --add-port=1935/tcp --per ...

  3. springsecurity 配置swagger

    最近在学习springsecurity 安全框架,具体是什么概念在这里不一一赘述了.下面呢,咱们一起搭建一下简单的springsecurity swagger 项目感受一下. 首先初始化spring ...

  4. CCF 202006-2 稀疏向量

    #include <iostream> #include <bits/stdc++.h> #include <string> using namespace std ...

  5. java 项目中Error linstenerStart 报错解决方法

    项目中经常会遇到如下报错: 严重:Error linstenerStart 这种报错,我们看不出来到底是出现了什么问题.下面我们就一步一步来解决: (1)首先进入项目的classes目录下: (2)进 ...

  6. Luogu P3368 【模板】树状数组 2 [区间修改-单点查询]

    P3368 [模板]树状数组 2 题目描述 如题,已知一个数列,你需要进行下面两种操作: 1.将某区间每一个数数加上x 2.求出某一个数的和 输入输出格式 输入格式: 第一行包含两个整数N.M,分别表 ...

  7. python+scrcpy实现将安卓设备录屏并保存到pc本地

    一)scrcpy下载及安装 参考链接:https://zhuanlan.zhihu.com/p/80264357 二)python+scrcpy实现将安卓设备录屏并保存到pc本地 示例代码: impo ...

  8. mysql重新设置列的自增初始值

    alter table xxx auto_increment = 100; 因为设置了列的自增之后,若删除过一些行,下次再新增时还会从已删除的id算起自增,为了让数据看起来连续,可以重新设置自增起始值 ...

  9. Element-ui框架Tree树形控件切换高亮显示选中效果

              废话不多说,直接上代码 1 <template> 2 <div class="warpper"> 3 <el-tree ref=& ...

  10. Educational Codeforces Round 2 个人总结A-E

    Educational Codeforces Round 2 A. Extract Numbers 简单的模拟 bool check(string op) { if(op.size()==1& ...