Getting XSS with DOM Clobbering and Prototype Pollution
获得带有 DOM Clobbering 和原型污染的 XSS
Summary 总结
This solution was an unintended solution to the 0124 Intigriti XSS Challenge. This article details how I used DOM Clobbering to inject into a POST form which led to Prototype Pollution. Then I used a gadget in JQuery to get an XSS.
该解决方案是 0124 Intigriti XSS 挑战赛的意外解决方案。本文详细介绍了我如何使用 DOM Clobbering 注入到 POST 表单中,这导致了原型污染。然后我使用 JQuery 中的一个小工具来获取 XSS。
Introduction 介绍
The challenge at first seemed like a reflected XSS. It starts with a reflection in the name parameter.
起初,挑战似乎是一个反映的 XSS。它从 name 参数中的反射开始。
However the reflection is sanitized by DOM Purify in the backend. There was another reflection via the search parameter, but this proved difficult to exploit.
但是,反射在后端由 DOM Purify 清理。通过搜索参数还有另一个反射,但事实证明很难利用。
DOM Clobbering
Since there was HTML Injection, DOM Clobbering was possible. There is JavaScript code that seems to execute when there is a “search” parameter in the URL bar. It then submits the form with an id of “search”.
由于有 HTML 注入,DOM Clobbering 是可能的。当 URL 栏中有“search”参数时,JavaScript 代码似乎会执行。然后,它提交 ID 为“search”的表单。
window.onload = () => {
const params = new URLSearchParams(location.search);
if (params.get("search")) search();
$("#search").submit((e) => {
e.preventDefault();
search();
});
};
So I could clobber the DOM, and insert another <form id=”search”> above the form that’s in the challenge page. However, this would only allow me to hijack the searches, and that wouldn’t get me an XSS.
因此,我可以删除 DOM,并在挑战页面中的表单上方插入另一个 <form>。但是,这只允许我劫持搜索,这不会让我获得 XSS。</form>
Looking at the search function, it looks to be using a specific library, axios.
查看搜索功能,它似乎正在使用特定的库 axios。
function search(name) {
$("img.loading").attr("hidden", false);
axios.post("/search", $("#search").get(0), {
"headers": { "Content-Type": "application/json" }
}).then((d) => {
$("img.loading").attr("hidden", true);
const repo = d.data;
if (!repo.owner) {
alert("Not found!");
return;
};
$("img.avatar").attr("src", repo.owner.avatar_url);
$("#description").text(repo.description);
if (repo.homepage && repo.homepage.startsWith("https://")) {
$("#homepage").attr({
"src": repo.homepage,
"hidden": false
});
};
});
};
The library has a recent vulnerability, prototype pollution
该库近期存在漏洞,原型污染
Exploiting Prototype Pollution
利用原型污染
When submitting a POST request via the Axios library, the resulting POST request data was a JSON formatted request, which is the specific function the vulnerability lies.
通过 Axios 库提交 POST 请求时,生成的 POST 请求数据是 JSON 格式的请求,这是漏洞所在的特定功能。
In order to exploit the vulnerability, I created a form, with an input tag, with the name of “__proto__[intigriti]” and value of anything.
为了利用这个漏洞,我创建了一个带有输入标签的表单,其名称为“__proto__[intigriti]”,值为任何值。
<form id=search>
<input name="__proto__[intigriti]" value="rodriguezjorgex">
Example url: 示例URL:
I verified it worked by checking the web developer console and typing “intigriti”.
我通过检查 Web 开发人员控制台并键入“intigriti”来验证它是否有效。
Finding a gadget 查找小工具
Blackfan List 黑粉名单
There are several ways I tried finding a gadget. First was using BlackFans prototype pollution gadgets on Github. There were several gadgets for JQuery, however none of these gadgets worked
我尝试了几种方法来寻找小工具。首先是在 Github 上使用 BlackFans 原型污染小工具。JQuery 有几个小工具,但这些小工具都不起作用
DOM Invader DOM 入侵者
I tried using DOM Invaders gadget scanner to find gadgets. However after doing a couple of searches just to be safe, no gadgets were found
我尝试使用 DOM Invaders 小工具扫描器来查找小工具。然而,为了安全起见,在进行了几次搜索后,没有找到任何小工具
Manual Hunting It Is 手动狩猎
Bypassing Checks 绕过检查
I noticed in the code there was a check for repo.owner, and after that, it would set the attributes of #homepage to the result of the repo.homepage variable. The only #homepage in the page was for an iframe tag, and the src would then be set to the homepage of the repository it found.
我注意到代码中有一个对 repo.owner 的检查,之后,它会将 #homepage 的属性设置为 repo.homepage 变量的结果。页面中唯一的 #homepage 是 iframe 标记,然后 src 将被设置为它找到的存储库的主页。
if (repo.homepage && repo.homepage.startsWith("https://")) {
$("#homepage").attr({
"src": repo.homepage,
"hidden": false
However, with the prototype pollution, I could inject my own homepage and possibly get an easy XSS that way. However, there is a check in the code to make sure the homepage starts with “https”, so I was not able to do something like “javascript:alert()”.
但是,有了原型污染,我可以注入自己的主页,并可能以这种方式获得一个简单的 XSS。但是,代码中有一个检查以确保主页以“https”开头,因此我无法执行“javascript:alert()”之类的操作。
Error in JQuery JQuery 中的错误
I set the prototype of “owner” to any value, and the prototype of “homepage” to “https://google.com” using the following link:
我使用以下链接将“owner”的原型设置为任何值,并将“homepage”的原型设置为“https://google.com”:
After setting prototype of “owner” to any value, and the prototype of “homepage” to “https://google.com“, the application sets the iframe src to google.com. I checked the console and there was an error:
将 “owner” 的 prototype 设置为任意值,并将 “homepage” 的 prototype 设置为 “https://google.com” 后,应用程序将 iframe src 设置为 google.com。我检查了控制台,出现错误:
jquery-3.7.1.min.js:2 Uncaught (in promise) TypeError: Cannot use 'in' operator to search for 'set' in https://google.com
I followed this error in the console, and set a breakpoint, and noticed the jQuery code that’s responsible for the error is this:
我在控制台中遵循了这个错误,并设置了一个断点,并注意到导致该错误的jQuery代码是这样的:
void 0 !== n ? null === n ? void ce.removeAttr(e, t) : i && "set"in i && void 0 !== (r = i.set(e, n, t)) ? r : (e.setAttribute(t, n + "")
The i variable is set to “https://google.com“, and this is causing the error. Normally, this variable is set to a function, or null, depending on what is passed to the function.
i 变量设置为“https://google.com”,这会导致错误。通常,此变量设置为函数或 null,具体取决于传递给函数的内容。
After researching the error, I found that if I set the i variable to an array, it will bypass the error, and the e.setAttribute() function will be called, setting an attribute in the <iframe> tag. So if I can add an srcdoc attribute, this will get passed to the iframe tag, and I can set the srcdoc to an XSS payload.
在研究了错误之后,我发现如果我将 i 变量设置为数组,它将绕过错误,并且会调用 e.setAttribute() 函数,在标签中设置一个属性<iframe>。因此,如果我可以添加 srcdoc 属性,它将被传递给 iframe 标签,并且我可以将 srcdoc 设置为 XSS 有效负载。</iframe>
Final Payload 最终有效载荷
After testing various ways to create an array, I found that by using __proto__[srcdoc][], I can make srcdoc into an array, and bypass the error, then execute the e.setAttribute function. Here’s the final payload:
在测试了各种创建数组的方法后,我发现通过使用 __proto__[srcdoc][],我可以将 srcdoc 变成一个数组,并绕过错误,然后执行 e.setAttribute 函数。以下是最终有效载荷:
After navigating to the page, I got the XSS alert!
导航到该页面后,我收到了 XSS 警报!
Conclusion 结论
This was my first Intigriti Challenge, and it was a fun one! Although I didn’t get the intended solution, finding the prototype pollution gadget and popping the alert was satisfaction enough!
这是我第一次参加Intigriti挑战,这很有趣!虽然我没有得到预期的解决方案,但找到原型污染小工具并弹出警报已经足够令人满意了!
Thanks Intigriti and Kevin Mizu for an excellent challenge!
感谢 Intigriti 和 Kevin Mizu 的出色挑战!
原文始发于Rodriguezjorgex:How I passed the Intigriti 0124 Challenge