A technical description of the SSL PCT vulnerability (CVE-2003-0719)
There has been public discussions about the exploitation of
the SSL PCT vulnerability. Exploit code was made publicly available
(THCIISLame.c) and rumors of a potential worm that uses the
vulnerability as an attack vector are spreading the security news.
What follows is my analysis of the vulnerability and the method of
exploitation, it is based on the CORE IMPACT exploit module I wrote
that shipped to our customers on April 16th. The THCIISLame.c
exploit seems to be a direct port of the module's first version.
The vulnerable code is located in schannel.dll which is loaded by
LSASS.exe, a dissembly of the vulnerable code translates roughly
to the following C construct:
function(char *packet, unsigned int N)
char buf[32];
unsigned int register i;
if(N < 32)
{
memcpy(buf,packet,N);
for(i = 0; i < N; i++)
buf[i+N] = ~buf[i];
}
Compilation of the above code with optimizations and inline expansion
translates to the following ASM that can be found in LSASS.exe:
.text:781786C8 mov [ebp-60], eax
.text:781786CB mov eax, [esi+0Ch]
.text:781786CE mov ecx, eax
.text:781786D0 add esi, 30h
.text:781786D3 mov edx, ecx
.text:781786D5 lea edi, [ebp-24]
.text:781786D8 shr ecx, 2
.text:781786DB rep movsd
.text:781786DD mov ecx, edx
.text:781786DF and ecx, 3
.text:781786E2 rep movsb
.text:781786E4 xor esi, esi
.text:781786E6 test eax, eax
.text:781786E8 jbe short dontcopy
.text:781786EA
.text:781786EA loop:
.text:781786EA mov dl, [ebp+esi-24]
.text:781786EE lea ecx, [ebp+esi-24]
.text:781786F2 inc esi
.text:781786F3 not dl
.text:781786F5 cmp esi, eax
.text:781786F7 mov [ecx+eax], dl
.text:781786FA jb short loop
.text:781786FA dontcopy:
In the above C code N is a value obtained from the PCT packet.
A value higher than 0x10 is enough to trigger the overflow. A value
of 0x16 overwrites the return address. The boundary check (N<32) is done
before the call to memcpy() but the concatenation code that follows it
is logically wrong.
The vulnerability could be exploited to execute arbitrary code, for that
purpose the return address should be overwritten with an address
pointing to data controlled by the attacker, but the address of such
data is
not predictable.
The usual way to reach the attacker code in Windows exploits is jumping
to a portion of instructions at a known address that redirects the
program flow to the attackers code. Those instructions are part of the
vulnerable application code, or part of any module loaded by it, so the
address depends on the application and system version, sometimes the
address is the same in different version of the same modules and
applications. It is part of the exploit developer's work to find those
instructions to make the exploit reliable against different target
configurations.
This is the approach I took for the first version of the PCT exploit,
the THCISLame.c exploit uses the same technique although I have a
different address.
In this case, when the vulnerable function returns to the address chosen
by the attacker, there is no register pointing to the controllable data,
but there is a pointer to the PCT packet on the thread's stack at [esp+6c].
If we can find a set of instructions in the vulnerable application
memory equivalent to CALL [esp+6C] part of the job is done.
I used:
add esp,6c
ret
There are many occurrences of those instructions in the lsass.exe memory.
But there is still a problem to solve: The address at [esp+6c] points to
the PCT packet header, so the fields of that header are going to be used
as executable code. If the PCT packet doesn't fulfil some protocol
checks execution flow will not reach the vulnerable function so we need
to craft a packet with valid field values and valid opcodes.
In this context a "valid field value" is one that allows the execution
flow to reach the vulnerable function AND is also a valid opcode so as
to prevent the application from crashing when it is executed.
Note that for successful exploitation, its not necessary to craft a
packet that complies with the PCT RFC (See RFC referenced at the end of
this email)
The packet used on the first version of the exploit module was:
"\x80\x66\x01\x02\xbd\x00\x01\x00\x01\x00\x16\x8F\x86\x01\x00\x00\x00"
Here is a brief explanation of the values used:
Value Condition to fulfill
XX YY (RecordLength):
if(XX & 0x80)
RecordLength = ((XX & 0x7f) << 8) | YY
else
RecordLength = ((XX & 0x3f) << 8) | YY
I selected XX=0x80 and YY=0x66 which satisfies the above condition.
01 0x01 (j):= 0x01
02 BD 0x02bd (k):0x0002 <= k < 0x301 < 0x8001
Here two bytes that satisfy the above condition can be used, 0x02
and 0xbd are just arbitrarily chosen values, because I like them!
Note that 0xbd == mov ebp
00 01 0x0001 (l): > 0x0001, its better to keep it under 0x0003
00 01 0x0001 (m):<= 0x10
00 16 0x001A (N): (l+m+N+9 <= RecordLength) && (0 < N <= 0x20)
8F 0x008F (o): = 0x008F
86 01 0x8601 (p): >= 0x8001
Additionally, RecordLength must be less or equal to the packet size.
The crafted packet translates to the following ASM code:
80660102 and byte ptr [esi+0x1],0x2
bd00010001 mov ebp,0x1000100
0016 add [esi],dl
8f8601000000 pop [esi+0x1]
eb20 jmp 0016f40b
The ESI register points to writable data in both XP and 2000, the
register used by the first and fourth instructions can be changed but
the third (00 16) is the right size to overwrite the return address.
A jump opcode (eb xx) could be used in the first two bytes if the
packet's length is modified accordingly.
Looking at the conditions that must be met for each field we can see
that there are more than 25 millions different packets that will trigger
the vulnerability (combinations of the possible values for XX,YY,k,l,m
and p)
Modifying the value for N is also possible but would require additional
payload to overwrite portions of the memory of the running process
with valid data.
Detection of an exploitation attempt:
In view of the above, detection of an attack that exploits this
vulnerability should not rely entirely on packet bytes that can have
value arbitrary chosen.
A proper check should *at least* check for the required fixed values:
o == 0x8F
0x10 < N <= 0x20 (a value less than 0x10 does not overwrite the stack)
Relying on other packet bytes for a proper detection signature should
be subject to careful analysis as there might be other execution paths
reaching the vulnerable function.
The workaround proposed in Microsoft's bulletin MS04-011 does prevent
exploitation of this vulnerability.
After further research I've found that it may be possible to write
an exploit that doesn't need to carry a hardcoded address and would work
against Windows XP and 2000 systems independent of service pack and
hot fixes applied, except of course for MS04-011 which does fix
the problem.
Exploitation has been successfully tested against the following systems:
Windows 2000 Professional - sp4 (i386)
Windows 2000 Professional - sp3 (i386)
Windows 2000 Professional - sp2 (i386)
Windows 2000 Server - sp4 (i386)
Windows 2000 Server - sp3 (i386)
Windows 2000 Server - sp2 (i386)
Windows 2000 Advanced Server - sp4 (i386)
Windows 2000 Advanced Server - sp3 (i386)
Windows 2000 Advanced Server - sp2 (i386)
Windows XP Professional - sp0 (i386)
Windows XP Professional - sp1 (i386)
(NT 4 exploitation seems possible with the same technique.)
The following services can be used as attack vectors:
IIS 4.0
IIS 5.0
IIS 5.1
Exchange 5.0 with SSL enabled
Active Directory with SSL
The vulnerable IIS and Microsoft Exchange services are:
HTTPS 443/tcp
SMTP 25/tcp (STARTTLS)
IMAP 993/tcp,
POP3 995/tcp
NNTP 563/tcp.
Active Directory:
ldaps 636/tcp
globalcatLDAPssl 3269/tcp.
Exploitation through the Analysis Services 2000 (included with SQL
Server 2000) were not researched.
PCT must be enabled and a valid certificate installed.
References:
http://www.microsoft.com/technet/security/bulletin/MS04-011.mspx
http://www.develop.com/books/pws/draft-benaloh-pct-01.txt
http://www.graphcomp.com/info/specs/ms/pct.htm
http://www.coresecurity.com/products/coreimpact/index.php
Thanks
Halvar Flake helped with the initial vulnerability analysis which
demonstrated not only his code reversing expertise but also the great
power of his bindiff tool.