Commit | Line | Data |
---|---|---|
c3aefacc HSHR |
1 | From qsa@qualys.com Wed Aug 14 01:29:25 CEST 2019 |
2 | Date: Tue, 13 Aug 2019 23:29:25 +0000 | |
3 | From: Qualys Security Advisory <qsa@qualys.com> | |
4 | To: Heiko Schlittermann <hs@schlittermann.de> | |
5 | Subject: Re: Help evaluating a Bug in Exim MTA | |
6 | Return-Path: <qsa@qualys.com> | |
7 | Authentication-Results: mx.net.schlittermann.de; iprev=pass | |
8 | (mx0b-001ca501.pphosted.com) smtp.remote-ip=148.163.158.195; spf=pass | |
9 | smtp.mailfrom=qualys.com; dkim=pass header.d=qualys.com header.s=qualyscom | |
10 | header.a=rsa-sha256; dkim=pass header.d=qualys.onmicrosoft.com | |
11 | header.s=selector2-qualys-onmicrosoft-com header.a=rsa-sha256; dmarc=none | |
12 | header.from=qualys.com | |
13 | Authentication-Results: ppops.net; spf=pass smtp.mailfrom=qsa@qualys.com | |
14 | Status: O | |
15 | Content-Length: 3899 | |
16 | Lines: 80 | |
17 | ||
18 | Hi Heiko, | |
19 | ||
20 | On Mon, Aug 12, 2019 at 11:56:12PM +0200, Heiko Schlittermann wrote: | |
21 | > So I'd say, you do not need to rush, but I'd like to close it sooner or | |
22 | > later in either manner. | |
23 | ||
24 | OK, below is our preliminary analysis. First: | |
25 | ||
26 | - From an attacker's point of view, most calls to | |
27 | string_interpret_escape() are uninteresting. For example, nextitem() | |
28 | in src/filter.c checks for buffer overflows, and string_dequote() | |
29 | seems to process trusted strings only (strings from configuration | |
30 | files). | |
31 | ||
32 | - On the other hand, string_unprinting() is very interesting: | |
33 | ||
34 | - It is used in tls_import_cert() (for peercert, for example); but | |
35 | certificates are in PEM format (i.e., base64) and hence unlikely to | |
36 | contain the problematic backslash-null-byte sequence. | |
37 | ||
38 | - It is used for peerdn and sni in src/spool_in.c; but peerdn is used | |
39 | only if client certificates are processed by Exim, and this is not | |
40 | the default (and although some sites use client-certificate | |
41 | authentication, this is not very common, and hence not very | |
42 | interesting for an attacker). | |
43 | ||
44 | - In any case, as long as Exim supports and accepts tls connections, | |
45 | an attacker can send an sni, and hence reach the problematic | |
46 | string_unprinting() and string_interpret_escape() functions. | |
47 | ||
48 | Next question: is it possible to send an sni that is written to the | |
49 | spool header file and that ends with the problematic backslash-null-byte | |
50 | sequence? The answer is yes, because of what we believe is another bug, | |
51 | in string_printing(): the sni is written to the spool header file via | |
52 | string_printing(tls_in.sni), which escapes characters with backslash, | |
53 | but does *not* escape the escaping character itself (backslash), | |
54 | although it definitely should. | |
55 | ||
56 | This bug is what makes it possible to reach and trigger the bug in | |
57 | string_unprinting() and string_interpret_escape(), with an sni that ends | |
58 | in an unescaped backslash (followed by the terminating null byte). | |
59 | ||
60 | Last question: is this exploitable? The answer is, almost certainly, yes | |
61 | (and, because spool_read_header() runs as root, this means remote root). | |
62 | ||
63 | The sni is read from the spool via string_unprinting(string_copy()), and | |
64 | both string_unprinting() and string_copy() use store_get(): as a result, | |
65 | the destination buffer is allocated right after the source buffer, and | |
66 | the characters that are read out-of-bounds after the end of the source | |
67 | buffer are the first characters of the destination buffer, which are | |
68 | fully under the attacker's control. This results in a heap overflow | |
69 | whose length and contents are both under the attacker's control (we | |
70 | verified this). This is almost certainly exploitable. | |
71 | ||
72 | Our advice is to start the security-release process as soon as possible. | |
73 | We know it is very painful, but we are really confident that this bug is | |
74 | exploitable; we will try to confirm this in the next few days. We also | |
75 | believe that an Exim server must support and accept tls connections to | |
76 | be remotely exploitable (via sni). | |
77 | ||
78 | During our analysis of this bug, we probably spotted three other bugs: | |
79 | ||
80 | - The unescaped backslash in string_printing() that we mentioned above. | |
81 | ||
82 | - A bug in spool_read_header(): before the for (;;) loop, p is set to | |
83 | big_buffer + 2; and inside the loop, big_buffer may be re-allocated; | |
84 | but p is never updated. This can lead to a use-after-free (we did not | |
85 | assess the security impact of this bug, though). | |
86 | ||
87 | - A bug in spool_write_header(): the return value of tls_export_cert() | |
88 | is not checked (for ourcert, but more importantly, for peercert). If | |
89 | this function fails (maybe because big_buffer is not big enough), then | |
90 | big_buffer may be uninitialized or unterminated, and garbage may be | |
91 | written to the spool file (we did not assess the security impact of | |
92 | this bug, either). | |
93 | ||
94 | We are at your disposal for questions, comments, and further | |
95 | discussions. Thank you very much for reaching out! With best regards, | |
96 | ||
97 | -- | |
98 | the Qualys Security Advisory team | |
99 | From qsa@qualys.com Mon Aug 19 00:23:03 CEST 2019 | |
100 | Date: Sun, 18 Aug 2019 22:23:03 +0000 | |
101 | From: Qualys Security Advisory <qsa@qualys.com> | |
102 | To: Heiko Schlittermann <hs@schlittermann.de> | |
103 | Subject: Re: Help evaluating a Bug in Exim MTA | |
104 | Return-Path: <qsa@qualys.com> | |
105 | Authentication-Results: mx.net.schlittermann.de; iprev=pass | |
106 | (mx0a-001ca501.pphosted.com) smtp.remote-ip=148.163.156.198; spf=pass | |
107 | smtp.mailfrom=qualys.com; dkim=pass header.d=qualys.com header.s=qualyscom | |
108 | header.a=rsa-sha256; dkim=pass header.d=qualys.onmicrosoft.com | |
109 | header.s=selector2-qualys-onmicrosoft-com header.a=rsa-sha256; dmarc=none | |
110 | header.from=qualys.com | |
111 | Authentication-Results: ppops.net; spf=pass smtp.mailfrom=qsa@qualys.com | |
112 | Status: RO | |
113 | Content-Length: 2484 | |
114 | Lines: 59 | |
115 | ||
116 | Hi Heiko, | |
117 | ||
118 | On Tue, Aug 13, 2019 at 11:29:25PM +0000, Qualys Security Advisory wrote: | |
119 | > we are really confident that this bug is exploitable | |
120 | ||
121 | We can confirm that this bug is indeed exploitable: we wrote a | |
122 | rudimentary exploit that remotely obtains root privileges (because | |
123 | deliver_message() runs as root). | |
124 | ||
125 | Some general notes on this exploit: | |
126 | ||
127 | - To the best of our knowledge, the string_interpret_escape() bug | |
128 | (backslash-null) is remotely exploitable if and only if Exim supports | |
129 | and accepts TLS connections (because the only attack vector that we | |
130 | know of is the string_unprinting() of SNI). | |
131 | ||
132 | - Both OpenSSL and GnuTLS installations are exploitable. | |
133 | ||
134 | - Our exploit is Linux-specific (because our heap-overflow exploitation | |
135 | is specific to glibc's malloc implementation), but works on both i386 | |
136 | and amd64. | |
137 | ||
138 | Some detailed notes on this exploit: | |
139 | ||
140 | - First, we connect to Exim with TLS and send an SNI that ends with | |
141 | backslash-null (this SNI is written unmodified to the spool because of | |
142 | the unescaped-backslash bug in string_printing2()). | |
143 | ||
144 | - Second, we exploit the backslash-null bug in string_interpret_escape() | |
145 | (our SNI is read from the spool and unescaped by string_unprinting()), | |
146 | and we transform this out-of-bounds read into an out-of-bounds write | |
147 | (a heap overflow). | |
148 | ||
149 | - Next, we use this heap overflow to overwrite the header of a free | |
150 | malloc chunk, and increase its size to make it overlap with other, | |
151 | already-allocated malloc chunks. | |
152 | ||
153 | - Last, we allocate this enlarged malloc chunk, and use it to overwrite | |
154 | large parts of the heap (the already-allocated malloc chunks) with | |
155 | arbitrary data: | |
156 | ||
157 | . we overwrite the "id" string: it is used to build the message-log | |
158 | file name, and therefore allows us to write to "/etc/passwd" (by | |
159 | overwriting "id" with "/../../../../../../../../etc/passwd"); | |
160 | ||
161 | . we overwrite the "sender_address" string: it is written to the | |
162 | message-log file, and therefore allows us to add a new user to | |
163 | "/etc/passwd". | |
164 | ||
165 | Other exploitation methods may exist. We will not publish our exploit: | |
166 | it is a quick and dirty proof of concept, and we will not have the time | |
167 | to clean it anytime soon. However, please feel free to quote us on the | |
168 | exploitability of this bug (we do have a working exploit), and please | |
169 | feel free to quote all or parts of this email in your announcements. | |
170 | ||
171 | We are at your disposal for questions, comments, and further | |
172 | discussions. Thank you very much! With best regards, | |
173 | ||
174 | -- | |
175 | the Qualys Security Advisory team |