mysql-dump-hashes.nse compatibility patch (v5.7)

Robbe Van der Gucht <[email protected]> Sun, 19 Aug 2018 22:10:04 +0200
Newsgroups gmane.comp.security.nmap.devel
Message-ID <CAOF+3gatnnPqs-GT+sZCCMUDTtvPseeSzZWfUZAweBW2FheN-w@mail.gmail.com>
Hi all,

From MySQL version 5.7 on the hashes are stored in
authentication_string and the password field is no longer present.
Because of this the mysql-dump-hashes.nse script doesn't work any more
against recent MySQL server installations. Attached you'll find my
proposed fix.

The patch is a simple fall back. If the first query referring to the
the 'password' field fails it will attempt to use the
'authentication_string' field.

I tested this fix against MySQL version 5.6.41 and version 8.0.11 to
confirm that both the old and new table format return the expected
results. I performed these tests with Nmap 7.70 from a W10 and Kali
box.

--
Robbe Van der Gucht

_______________________________________________
Sent through the dev mailing list
https://nmap.org/mailman/listinfo/dev
Archived at http://seclists.org/nmap-dev/
mysql-dump-hashes-4.7ver.patch (application/octet-stream, 1.2 KB)
--- mysql-dump-hashes.nse	2015-11-05 15:41:05.000000000 -0500
+++ mysql-dump-hashes-fixed.nse	2018-08-19 14:47:49.877692000 -0400
@@ -84,12 +84,24 @@
 
     local status, response = mysqlLogin(socket, username, password)
     if ( status ) then
-      local query = "SELECT DISTINCT CONCAT(user, ':', password) FROM mysql.user WHERE password <> ''"
+      local query = "SELECT DISTINCT CONCAT(user, ':', password) "..
+                    "FROM mysql.user WHERE password <> ''"
       local status, rows = mysql.sqlQuery( socket, query )
-      socket:close()
       if ( status ) then
         result = mysql.formatResultset(rows, { noheaders = true })
+        socket:close()
         break
+      else
+        -- From MySQL version 5.7 on the authentication_string column is used
+        local query = "SELECT DISTINCT CONCAT(user, ':', authentication_string) "..
+            "FROM mysql.user "..
+            "WHERE authentication_string <> '*THISISNOTAVALIDPASSWORDTHATCANBEUSEDHERE'"
+        local status, rows = mysql.sqlQuery( socket, query )
+        socket:close()
+        if ( status ) then
+          result = mysql.formatResultset(rows, { noheaders = true })
+          break
+        end
       end
     else
       socket:close()