0x00 背景

最近遇到一个双重编码绕过过滤的xss漏洞,成功在大佬的指点下弹出成功之后记录一下学习。

0x01 URL编码

一个URL的形式如下:

foo://example.com:8042/over/there?name=ferret#nose

协议 域名 端口 路径 search参数 hash参数

通常来说,如果某种文本需要编码,说明他并不适合传输。原因多种多样,或压缩尺寸,或隐藏隐私数据……

对于URL来说,之所以要进行编码,一方面是因为URL中有些字符会引起歧义。例如,URL参数字符串中使用key=value键值对这样的形式来传参,键值对之间以&符号分隔,如/s?name=chen&city=beijing。但是这个时候如果value字符串包含了=或者&,那么服务器解析肯定会出错,因此必须将引起歧义的&和=符号进行编码。

另一方面,因此URL编码采用的是ASCII码,这也就是说你不能在Url中包含任何非ASCII字符,例如中文。否则如果客户端浏览器和服务端浏览器支持的字符集不同的情况下,中文可能会造成问题。

Javascript中对于URL编码主要有以下几个函数:

escape(string):该方法不会对 ASCII 字母和数字进行编码,也不会对下面这些 ASCII 标点符号进行编码: * @ - _ + . / 。其他所有的字符都会被转义序列替换。

escape("http://www.xxx.com/My first/a?name=chen&city=beijing")======>>>>>> http%3A//www.xxx.com/My%20first/a%3Fname%3Dchen%26city%3Dbeijing

encodeURI(string):该方法不会对 ASCII 字母和数字进行编码,也不会对这些 ASCII 标点符号进行编码: - _ . ! ~ * ' ( ) 。该方法的目的是对 URI 进行完整的编码,因此对以下在 URI 中具有特殊含义的 ASCII 标点符号,encodeURI() 函数是不会进行转义的:;/?:@&=+$,#

encodeURI("http://www.xxx.com/My first/a?name=chen&city=beijing")========>>>>>> http://www.xxx.com/My%20first/a?name=chen&city=beijing

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

encodeURIComponent("http://www.xxx.com/My first/a?name=chen&city=beijing")=======>>>>>> http%3A%2F%2Fwww.xxx.com%2FMy%20first%2Fa%3Fname%3Dchen%26city%3Dbeijin

0x02 URL双重编码

那么为什么需要双重编码呢?因为以上未讨论value为中文的情况。

当value的值为中文字符时,提交到后台经过一次encodeURI()对中文URL参数进行编码时,“测试”二字会被转换为“%E6%B5%8B%E8%AF%95”。 但是编码后的字符串信息,浏览器机制会认为“%”是一个转义字符,它并未将“%”认为是个普通字符。因此需要使用encodeURI进行二次编码

操作: encodeURI(encodeURI("测试"));

经过以上操作处理后的"测试"变为”%25E6%25B5%258B%25E8%25AF%2595“,通过再次编码原有被浏览起解析为转义字符的”%“被再次编码,转换成了普通字符转”%25“。

代码逻辑如下:

首先,在前端页面准备参数的时候,需要对中文参数进行encode处理:

var url = '/?page_name='+encodeURI(encodeURI("测试"));

window.open(url);

后端处理:String starName = java.net.URLDecoder.decode(request.getParameter("page_name"),"UTF-8");

前端在进行encode编码为什么用了两次encodeURI,而服务器后端在解码时只解了一次?这是因为容器会默认帮你解一次码。

既然容器会默认解一次码,那么为什么不只编码一次然后让容器自动解析一次就好呢?即直接在前端只进行一次encode,服务端程序直接request.getParameter(“page_name”) ?

这是因为容器默认解码时采用的是容器的默认编码,可能是UTF-8,GBK,也可能是其他编码方式。这与你当前的应用的编码方式未必一致。所以你直接获取的话可能会出现乱码。

当然也可以通过修改容器的默认编码,从而实现“前端一次encode——后端直接获取”的途径获取中文参数。例如:在Tomcat下默认编码修改方式:修改%TOMCAT_HOME%/conf/server.xml,找到这行代码:

在后面可以追加URIEncoding属性,即:

如果不方便改容器默认编码方式,或者应用程序本身就有多种编码方式的话,还是采取“前端两次encode——后端一次decode”的途径获取中文参数吧。

0x03 URL编码与XSS

XSS原理这里就不讲了。这里直接使用自己遇到的一个反射性xss的例子,问题参数出在url的search参数上。

首先是是在搜索框中插入尖括号,可以看到这是在黑名单之中的:

然后输入正常的查询字段发现会被编码并使用get方式进行提交,所以就在对应的参数后面进行提交,还是首先测试尖括号的url编码是否被过滤,经过测试发现经过一次URL编码的%3c依旧会被过滤,但是经过二次URL编码的%253c就能够在搜索框与页面正常显示:

这里就通过查看源代码和查看元素发现都被正常解析了,这也意味着可以出发XSS了,一个触发点时搜索框中,一个触发点时搜索[

这里继续尝试在搜索的中括号进行XSS,将payload  进行2次URL编码如下:%253Cimg%2520src%253D1%2520onerror%253Dalert%25281%2529%253E

可以看到标签被正确解析了,但是onerror 的alert却没有被触发,所以后台对于alert应该是有防护的,这里尝试双写绕过即可触发:

还有一个触发点就是在输入框利用引号闭合,增加onclick或者onmouseover等事件进行触发。

0x04 绕过原理

首先就是浏览器在前端与后端都有过滤措施。

首先前端在输入框对于输入的参数校验是很严格的,对于未经编码与经过编码的特殊符号都能够做到完整过滤,但是却使用了get进行提交,导致攻击者可以任意修改url参数进行绕过前端验证。

其次后端的验证对于非法字符的检测与过滤机制就太不严格了,当我们传输只经过一次URL编码的payload时,后台可以经过解码可以检测出敏感输入,但是在经过2次URL编码的时候就无法检测出恶意的符号内容。

参考链接:

xss 全编码两次_URL编码与XSS相关推荐

  1. XSS注入(1)-两个简单测试理解反射型xss注入和存储型xss注入

    XSS注入(1)-两个例子理解反射型xss注入和存储型xss注入 XSS全称 Cross Site Script,为使与css语言重名,所以我们将其称为xss跨站脚本攻击.它指的是恶意攻击者往Web页 ...

  2. xss 全编码两次_XSS进阶

    原标题:XSS进阶 1.XSS常用语句及编码绕过 XSS常用的测试语句有: ●<>alert(1)> ● ● ● 常见的XSS的绕过编码有JS编码.HTML实体编码和URL编码. ( ...

  3. xss 全编码两次_XSS平台简单使用

    XSS常用语句及编码绕过 XSS常用的测试语句有: 常见的XSS的绕过编码有JS编码.HTML实体编码和URL编码 JS编码 JS提供了四种字符编码的策略,如下所示. 三个八进制数字,如果个数不够,在 ...

  4. 基于内码映射方案的简繁体、全半角、gbk/utf8编码轻量级转换方案,无需三方库

    基于内码映射方案的简繁体.全半角.gbk/utf8编码轻量级转换方案,无需三方库 基于内码映射方案的简繁体.全半角.gbk/utf8编码互相转换 1. Unicode和UTF8/16/32之间的关系 ...

  5. 两种不同编码规则的查询

    两种不同编码规则("Chinese_PRC_BIN"和"Chinese_PRC_CI_AS")的表之间的数据查询,如何来处理-MS-SQLServer/基础类 ...

  6. 【javaScript】encodeURI来解决URL传递时为什么需要进行两次encodeURI编码

    encodeURI来解决URL传递时为什么需要进行两次encodeURI编码 文章来源于https://blog.csdn.net/u012027337/article/details/5212647 ...

  7. python全栈开发-再谈编码 python_day_6

    一. 回顾上周所有内容 一. python基础 Python是一门解释型. 弱类型语言 print("内容", "内容", end="\n" ...

  8. iconv 判断字符编码_GBK 和 UTF8编码

    相关学习内容: https://study.163.com/course/courseMain.htm?courseId=1210747815&share=2&shareId=4800 ...

  9. 【拓展】谈谈字符编码:Unicode编码与emoji表情编码

    " 开发过程中,字符编码是我们一定要掌握的知识.本文回顾ASCII标准,并介绍了Unicode和UTF-8.UTF-16方案间的关系,各自是如何存储的,最后介绍了Unicode中emoji表 ...

最新文章

  1. Android Studio 打开提示Invalid Gradle JDK configuration found错误
  2. Java学习之for语句
  3. 学习笔记之-php编码技巧
  4. 计算机c语言模拟考试,国家计算机二级c语言考试模拟题
  5. android audio arch
  6. 从零开始,我用了两年半逆袭秋招!
  7. 命令端口C++检测本地网络端口占用
  8. vue视频文本编辑器html,Vue 轻量级富文本编辑器 Vue-Quill-Editor
  9. 全国省市县乡镇四级sql数据
  10. 阿里云在安全方面有哪些防护措施
  11. 电力通信网与运营商5G网络融合方案
  12. ios 保存图片到相册 崩溃_iOS保存图片到相册
  13. 用html和css制作九宫格,我就是要用CSS实现九宫格图
  14. 2022非常全的接口测试面试题及参考答案-软件测试工程师没有碰到算我输~
  15. 计算机网络-自顶向下方法 第三章课后习题答案(第七版)
  16. dB单位与放大倍数关系
  17. Maple学习笔记——数学计算与数据处理
  18. Ubuntu 下同局域网主机访问Tomcat 服务器
  19. pandas_数据处理分析基本
  20. 小游戏贪吃蛇的c++源代码

热门文章

  1. JavaScript中有关数据结构和算法的最佳书籍
  2. SAS在金融中的应用六
  3. springMVC发送邮件
  4. 数组扩容 java_java 数组扩容的方法
  5. 源码分析参考:Pipelines
  6. Ubuntu美化方案
  7. 使用母版頁是內容如何使用CSS和javascript
  8. okhttp builder_从 OkHttp 到 Retrofit 到 OkHttps
  9. leetcode - 617. 合并二叉树
  10. 网络爬虫之java基础篇QueryRunner(Ⅲ)