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. A*算法 javascript模拟
  2. ASP.NET Core WebApi 返回统一格式参数
  3. [导入]OpenSceneGraph编译指导
  4. 关于SQL Server安装文件挂起错误解决办法
  5. 关于孵化器类型的创业公司-面试注意事项
  6. icoding复习7, 8
  7. 05 MapReduce应用案例02
  8. Spring—注解开发
  9. 《软件需求分析(第二版)》第 17 章——需求管理工具 重点部分总结
  10. php delegate,jQuery中delegate()方法的用法详解
  11. python二维向量运算_python中二维数组的Elementwise与or或运算
  12. element表格点击行即选中该行复选框
  13. 安装Python3.8.8
  14. python个人简历爬取_python爬取简历模板
  15. JAVA毕业设计高校教学资源共享平台计算机源码+lw文档+系统+调试部署+数据库
  16. Python如何查询版本号
  17. “我应为王”,比尔盖茨名言--author :邵京国
  18. 找到读取文本文件的方法
  19. 以前不懂事现在只想搞钱,从0-1搭建一个树莓派小车
  20. matlab dim是什么意思,哪位大神给我解释下这两句程序是什么意思

热门文章

  1. golang中的variable和data types
  2. gitlab定期备份_如何在一分钟内让GitLab为您做定期工作
  3. return本质探究以及try-finaly下的return探究
  4. lamp php7.0,LAMP(Ubuntu16+PHP7.0)安装Wordpress
  5. java调用sqlserver存储过程_Java中调用SQLServer存储过程示例
  6. python 3d游戏记录路径_基于osg的python三维程序开发(五)------沿路径运动
  7. try、catch和finally中都有return语句的情况
  8. Python 3.8.3 发布
  9. textbox有个AutoCompleteType的属性
  10. 2.9 穆尔彭罗斯伪逆