rapid7 / metasploit-framework

Metasploit Framework
https://www.metasploit.com/
Other
33.87k stars 13.92k forks source link

Update `admin/mssql/mssql_sql` to handle required password changes when attempting login #18819

Open cgranleese-r7 opened 7 months ago

cgranleese-r7 commented 7 months ago

Summary

Currently when admin/mssql/mssql_sql attempts a login but the user requires a password change. It just returns a console output that doesn't help the user.

Basic example

Current output: image

Example output we should detect when attempting to interact via sqlcmd:

C:\Users\foo>sqlcmd -U foo -P test
mssql: login error: Login failed for user 'foo'.  Reason: The password of the account must be changed.
mssql: login error: Login failed for user 'foo'.  Reason: The password of the account must be changed.

Wireshark output:

Token - Error
    Token length: 122
    SQL Error Number: 18456
    State: 1
    Class (Severity): 14
    Error message length: 29 characters
    Error message: Login failed for user 'alan'.
    Server name length: 26 characters
    Server name: DESKTOP-DRQ7J9D\SQLEXPRESS
    Process name length: 0 characters
    Line number: 1

When taking a quick look into this it looks like we could possibly leverage fChangePassword see here. Updating the module to detect when a new password is required then make use of the flag to then submit a new password and login.

sqlcmd example of flag being used, -z being the new password to set:

C:\Users\foo>sqlcmd -U alan -P password123 -z password1234 -N disable
1>

Motivation

  1. Improve the handling off this scenario off having a success login but not being able to go any further with the module due to not being able to update the password.
  2. Updating this and some extra error handling would improve the module overall user experience as it fails very silently currently.
nrathaus commented 5 months ago

I believe the bug is in lib/rex/proto/mssql/client_mixin.rb function mssql_parse_reply

nrathaus commented 5 months ago

Docker based setup: https://github.com/microsoft/mssql-docker/tree/master/linux/preview/examples/mssql-customize

SQL setup: src/mssql-docker/linux/preview/examples/mssql-customize/setup.sql

CREATE DATABASE HelloWorld;
GO

CREATE LOGIN foo WITH PASSWORD = 'Password123!' MUST_CHANGE, CHECK_EXPIRATION = ON;
GO

CREATE USER foo FOR LOGIN 'foo';
GO

Run: cd mssql-docker/linux/preview/examples/mssql-customize docker build -t mssql-custom . docker run -e 'ACCEPT_EULA=Y' -e 'MSSQL_SA_PASSWORD=StrongPassw0rd' -p 1433:1433 --name sql1 -d mssql-custom

nrathaus commented 5 months ago

The error itself (returned by the server) doesn't show the Reason that sqlcmd shows

nrathaus commented 5 months ago

To use fChangePassword we would need to move to TDS 7.2

nrathaus commented 5 months ago

I tried changing the TDS Version inside client.rb to 0x72000001 without any other changes, the server doesn't respond to the login attempts (no packets are sent back)

In the logs I see:

2024-04-22 13:28:00.64 Logon       The Tabular Data Stream (TDS) version 0x72000001 of the client library used to open the connection is unsupported or unknown. The connection has been closed.  [CLIENT: 172.17.0.1]
nrathaus commented 5 months ago

I found a reference to: 0x72090002

Here: https://github.com/prisma/tiberius/blob/8f66a699dfa041e7b5f736c7e94f92c945453c9e/src/tds/codec/login.rs#L16

nrathaus commented 5 months ago

This value seems to be the correct one, but logs indicate the structure is invalid:

2024-04-22 13:37:14.54 Logon       The login packet used to open the connection is structurally invalid; the connection has been closed. Please contact the vendor of the client library. [CLIENT: 172.17.0.1]
nrathaus commented 5 months ago

@cgranleese-r7 can you provide a wireshark dump of a successful login (using sqlcmd)? maybe using the docker indicated above?

This will help debug why the login packet is regarded as invalid (I am on Linux, don't have access to sqlcmd)

nrathaus commented 5 months ago

I found that you can docker use sqlcmd: $ docker run -it --link sql1:sqlsrv fabiang/sqlcmd -S sqlsrv -U sa -P StrongPassw0rd -C

nrathaus commented 5 months ago

Problem with sqlcmd is that TLS encrypts the connection - without any (apparent) ability to control it

cgranleese-r7 commented 5 months ago

@cgranleese-r7 can you provide a wireshark dump of a successful login (using sqlcmd)? maybe using the docker indicated above?

This will help debug why the login packet is regarded as invalid (I am on Linux, don't have access to sqlcmd)

I did this targeting one of our Windows VMs. Should also work if you target a docker image. Here is a docker command we have used when testing MSSQL issues previously:

docker run -e "ACCEPT_EULA=Y" -e "MSSQL_SA_PASSWORD=MyMSSQLServerPassword__<>" -p 1433:1433 mcr.microsoft.com/mssql/server:2022-preview-ubuntu-22.04