python_feedgen_maxwelldulin.invades.space.rss.xml - sfeed_tests - sfeed tests and RSS and Atom files
(HTM) git clone git://git.codemadness.org/sfeed_tests
(DIR) Log
(DIR) Files
(DIR) Refs
(DIR) README
(DIR) LICENSE
---
python_feedgen_maxwelldulin.invades.space.rss.xml (96900B)
---
1 <?xml version='1.0' encoding='UTF-8'?>
2 <rss xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/" version="2.0"><channel><title>Maxwell Dulin's Blog</title><link>https://maxwelldulin.com/Blog</link><description>ꓘ's 1337 blog</description><docs>http://www.rssboard.org/rss-specification</docs><generator>python-feedgen</generator><language>en-US</language><lastBuildDate>Sat, 02 Oct 2021 00:00:03 +0000</lastBuildDate><item><title>Resetting Passwords - What Could Possibly Go Wrong?</title><link>https://maxwelldulin.com/BlogPost?post=3702041600</link><description><meta property="og:image" content="https://maxwelldulin.com/static/favicon.ico"/>
3
4 <h2>Introduction</h2>
5 <p>
6 Recently, a friend of mine (from outside the United States) had a third party make them a website for eCommerce sales and blogging. Because of this, they wanted me to do a quick review of the security of the application. After reviewing the account handling on the application I determined that the Password Reset functionality was the <b>worst implementation ever made</b>. If you can think of an issue I bet this had it... Below, we will be going into what went wrong and how to find these types of issues yourself.
7 </p>
8
9 <h2>Back to the Basics</h2>
10
11 <p>
12 If accounts exists on a website there are some basic features of it:
13 <ul>
14 <li>Create Account</li>
15 <li>Login</li>
16 <li>Forgot Password/ Password Reset</li>
17 <li>Update Account</li>
18 <li>Delete Account</li>
19 <li>View Account</li>
20 </ul>
21
22 If any of these is done in insecure way, major havoc can occur. In this blog post, we will be paying special attention to the <i>Password Reset</i> functionality of a website and how it can go wrong.
23 </p>
24
25 <h3>
26 Basic Flow of Password Reset
27 </h3>
28 <p>
29 What do you do if a user forgets their password? Well, you want them to be able to login, but you still want to make sure that it is the correct user. So, it is time to rest their password.
30 </p>
31 <p>
32 Generally, a users account is tied to an email. With this, the website can send this users email a <i>magic link</i>. This magic link deems that the user is trusted and will allow them to change the password.
33 </p>
34
35 <!-break-->
36
37 <p>
38 Once the link is clicked on, a user can select their new password. When the user sends the new password to the backend, the <i>magic value</i> is sent back along with it. This is so that the <i>magic value</i> can be verified from the link to ensure this is the correct user. With the correct value, the password is reset and the user can continue! What could possibly go wrong?
39 </p>
40
41 <h2>
42 What Went Wrong #1 - Email Enumeration (Low)
43 </h2>
44 <p>
45 From the very beginning, the reset functionality had issues. The initial request gave two different messages, depending on if the email was valid or invalid. The initial request, with an improper email, gave back the following error message:
46 <div style="width:98%; font-size:80%; text-align:center; float : left; border: 1px solid black; border-radius: 10px; margin: 10px;"><img src="https://live.staticflickr.com/65535/50124974596_bcd7877b69_c.jpg" width="95%" alt=""><center>Incorrect Email Message</center></div>
47
48 With a valid email, it just said that the email had been sent.
49 </p>
50 <p>
51 But, why is this bad? Because it is trivial to distinguish between a valid and invalid email, this can provide an easy way for <b>email enumeration</b> of users with an account. This by itself is not a huge deal, but can be used in further attacks and information leakage.
52 </p>
53
54 <h2>
55 What Went Wrong #2 - Host Header Injection (High)
56 </h2>
57
58 <p>
59 Now, this time, we are going to input a valid email address. Everything works are expected... So, let's tamper with the request itself!
60 </p>
61
62 <h3>
63 Host Header
64 </h3>
65 <p>
66 HTTP sends a plethora of different headers on each request, such as the Origin, Cookies, Content-Type and more. The important one for this attack is the <i>Host Header</i>. The Host Header is defined as
67 <code>Specifies the domain name of the server.
68 </code> by Mozilla. In layman's terms, this simply means the host name (domain) without the protocol.
69 </p>
70
71 <p>
72 Even though the Host is set in the browser on a normal request (and cannot be altered), software like Burp and Curl can trivially spoof header/value in a request made to the backend. If the backend is trusting any of these values in an improper way, havoc can unfold.
73 </p>
74
75 <h3>
76 Havoc
77 </h3>
78 <p>
79 The Host Header is sometimes used in order to create links from it. So, what if we alter the host header? It turns out that by altering the Host header, the <i>domain</i> of the link can be changed! For example, see the following screenshot:
80 <div style="width:98%; font-size:80%; text-align:center; float : left; border: 1px solid black; border-radius: 10px; margin: 10px;"><img src="https://live.staticflickr.com/65535/50127447947_747f10d5bd_c.jpg" width="95%" alt=""><center>Host Header Injection </center></div>
81 </p>
82
83 <p>
84 What's the attack here though? Well, this means that when the link is clicked (in the users email), the redirect (along with the magic value) will be sent to an <b>attacker controlled host</b>! Once the link has been clicked, the attacker can simply use this reset token and reset the users password. Below is an example of the password reset link, after the host header modification, with the magic value:
85
86 <div style="width:98%; font-size:80%; text-align:center; float : left; border: 1px solid black; border-radius: 10px; margin: 10px;"><img src="https://live.staticflickr.com/65535/50127221241_cdec327d96_c.jpg" width="95%" alt=""><center>Email Reset Link</center></div>
87 </p>
88
89 <h2>
90 What Went Wrong #3 - Short Reset Token (Medium/High)
91 </h2>
92 <p>
93 If we ignore the first issue (that takes a single click from the user) what else is out there? Immediately, when I hovered over the reset link, I noticed that only 6 digits were being used for the token. <b>SIX</b>.
94 </p>
95 <p>
96 Mathematically, this is 10^6 or 1,000,000 chances. With no throttling and a fairly long expiration time on the tokens (which are both issues in their own right), this is possible to brute force from a single computer.
97 </p>
98
99 <p>
100 By requesting a reset email for a single user then attempting <i>each</i> of the tokens in the set, it would be possible to reset the users password! Although this would take some time to perform, it is absolutely a viable attack method for taking over an account.
101 </p>
102
103 <h2>
104 What Went Wrong #4 - Lack of Server Side Validation (Critical)
105 </h2>
106
107 <p>
108 You are probably thinking <i>'There are already two ways to take over the account, what else could go wrong?'</i> You are in luck though, because there is one more major bug.
109 </p>
110
111 <p>
112 Upon clicking on the link to go back to the website, the magic token was validated. Now, all the user has to do is send the new password back to the backend. Do you see anything wrong with this?
113
114 </p>
115
116 <h3>
117 Lack of Validation of Token
118 </h3>
119 <p>
120 The first request validates the password reset token. But, the second request, where the password was actually being reset, did <b>not</b> include the <i>magic value</i>! Because of this, a single request could reset any users password; it was really as simple as that! A picture of the request in Burp is shown below:
121 <div style="width:98%; font-size:80%; text-align:center; float : left; border: 1px solid black; border-radius: 10px; margin: 10px;"><img src="https://live.staticflickr.com/65535/50124483628_ef20fa7938_c.jpg" width="95%" alt=""><center>Password Reset Request</center></div>
122
123 Notice that the above request does not include the <i>magic value</i> inside of it. Boom, a single request to compromise the account: no clicks or brute forcing needed.
124 </p>
125
126
127 <h2>
128 Fixing
129 </h2>
130 <p>
131 The creators of the website were from a third world country where English is not the primary language and the people only speak a little English. So, when looking for resources in their language, we could not find very much about the vulnerabilities discussed above. In particular, there was <i>nothing</i> online referring to Host Header Injection. To solve this problem, I took videos of myself exploiting the vulnerabilities while speaking slow and simple English. With this, I also sent links in the native language and in some better ones in English.
132 </p>
133
134 <p>
135 After reporting the findings, the token was being validated on the backend and the proper entropy was added to the reset tokens. However, because of the lack of resources (and difficulty) for the security patches, the <i>Host Header Injection</i> took <b>4 attempts</b> to try to fix. The owner of the site said they would not pay until the issue was fixed. Magically, the next day, the vulnerability was patched! So, I'm unsure if they did not care about patching the bug or if they just did not know how. Regardless, this makes me consider the security of websites outside of the normal public eye and whether or non-English speakers have the proper resources to make secure software.
136 </p>
137
138 <h2>
139 Test Cases
140 </h2>
141
142 <p>
143 Password reset functionality is one of the hardest aspects of the user experience to get right. When something does go wrong with this, an account compromise can occur. Below are a list of issues with the password reset functionality found during this security review:
144 <ul>
145 <li>Username/email enumeration</li>
146 <li>Host Header Injection</li>
147 <li>Insufficient Length of Reset Tokens </li>
148 <li>Lack of Validation of Magic Values</li>
149 <li>Extended Expiration Time on Token</li>
150 <li>Lack of Brute Force Protections</li>
151 </ul>
152
153 Besides the issues described above, there are a few more that should be tested for:
154
155 <ul>
156 <li>Sending New Passwords over Email</li>
157 <li>Lack of Two Factor Authentication</li>
158 <li>Multiple Uses for a Single Reset Token</li>
159 <li>Reset tokens Not Specific To User</li>
160 </ul>
161
162 This is a fairly good list for testing password reset functionality. But, the test cases differ depending on the implementation.
163 </p>
164
165 <h3>
166 Defense In Depth
167 </h3>
168 <p>
169 Some of the issues listed above do not lead to a direct compromise of the user account but are considered best practice. By having a <i>defense-in-depth</i> mindset, subtle issues become very difficult or impossible to exploit.
170 </p>
171
172 <p>For instance, the <i>insufficient token length</i> vulnerability was made possible to exploit by a lack of brute force protections and extended length of the tokens times. If the brute forcing was not possible, this vulnerability would have been very difficult to exploit.
173 </p>
174
175 <p>
176 Overall, adding slight security optimizations makes the overall security of the site much better. In the case that a single issue is found, having defense-in-depth measures can make the vulnerability more difficult to exploit for an attacker. During assessments, it is extremely important to point out not just impactful vulnerabilities but small/subtle things to help out the overall security of the site.
177 </p>
178
179
180 <h2>
181 Conclusion
182 </h2>
183 <p>
184 Security is hard to get right! This is why having hackers poke around is a good thing (of course, get permission first). I hope you enjoyed the article and learned something interesting about web applications today. Feel free to reach out to me (contact information is in the footer) if you have any questions or comments about this article. Cheers from <b>Maxwell "ꓘ" Dulin</b>.
185 </p></description><guid isPermaLink="false">https://maxwelldulin.com/BlogPost?post=3702041600</guid><pubDate>Sun, 19 Jul 2020 00:00:00 +0000</pubDate></item><item><title>House of Muney - Leakless Heap Exploitation Technique</title><link>https://maxwelldulin.com/BlogPost?post=6967456768</link><description><h2>
186 Introduction
187 </h2>
188 <p>
189 Exploiting different heap libraries tends to be difficult, complex and requires a deep knowledge of the library itself. Recently, Qualys decided to go back and exploit a <u>15 year</u> bug in QMail that was thought to unexploitable with some incredible techniques. <a href="https://www.qualys.com/2020/05/19/cve-2005-1513/remote-code-execution-qmail.txt">This exploit</a> uses a very interesting quirk of Malloc and exploit method that had not been seen before, which I have decided to name the <b>House of Muney</b>.
190 </p>
191
192 <p>In this article, I wanted to shed more light on the exploitation method that was used by the Qualys researchers to ensure there is a well-documented location for this exploit method. In short, it is broken up into <i>Munmap</i>ing part of LibC and to <i>rewrite</i> the symbol table to get code execution. There are two main perks of this technique: this <b>bypasses ASLR</b> entirely and works on <b>mmap</b> chunks in GLibC Malloc.
193 </p>
194
195 <p>
196 Just as a fair warning, this article has quite a bit of background knowledge to understand the exploit. If you think you have a good understanding a section, it is recommended you still review the section just to refamilarize yourself with the content. In this article, the following is discussed as background:
197 <ul>
198 <li>Malloc Chunk (general)</li>
199 <li>Mmap and Munmap</li>
200 <li>Malloc Mmap Chunks </li>
201 <li>ELF Symbol Resolution</li>
202 </ul>
203 </p>
204
205
206 <p>
207 The article also comes with a working POC on version 2.31 of Malloc on my Github (mdulin2) at <a href="https://github.com/mdulin2/munmap-and-rewrite"> House of Muney</a> if you would like to follow along. Additionally, if you want more security content, take a look at the <a href="https://maxwelldulin.com/Resources">resources</a> or other blog posts. Now, with the introduction out of the way, let's dive into the technical details.
208 </p>
209
210 <h2>
211 GLibC Malloc Background
212 </h2>
213
214 <h3>
215 Chunks
216 </h3>
217
218 <p>
219 Chunks are the main object that users interact with. There are two main states to a chunk: <i>allocated</i> and <i>free</i>. The following picture demonstrates a <i>free</i> chunk:
220 <div style="width: 98%; font-size:80%; text-align:center; float : left; border: 1px solid black; border-radius: 10px; margin: 10px;"><img src="https://docs.google.com/drawings/d/1YrlnGa081NpO0D3wcoaJbGvhnPi3X6bBKMc3bN4-oZQ/pub?w=940&h=669" width="95%" alt=""><center>Figure 1 - Free Chunk by Sploitfun</center></div>
221
222
223 The first field is the size of the previous chunk (prev_size). This is only used if the previous chunk is free. The second field is the <b>chunk size</b>. The chunk size represents the size of the data of the chunk and the metadata about the chunk. The metadata of the chunk includes three fields: prev_inuse (if the previous chunk is in use), mmap (is the previous chunk mmapped) and if the chunk is in a non-main arena.
224 </p>
225
226 <p>
227 On an allocated (non-free) chunk, the third and fourth field are used as data sections. However, on a free chunk, the third field is used in order to store a pointer to other freed chunks. This field is known as the forward pointer or the <i>Fd</i> field. The fourth field is exactly the same, except that it stores a backwards pointer or <i>bk</i>. <!-break-->
228 </p>
229
230 <p>
231 This is a very small background on chunks but is all that is needed for the article. For further information, please to refer to <a href ="https://sploitfun.wordpress.com/2015/02/10/understanding-glibc-malloc/">Sploitfun's</a> amazing article about GLibC.
232 </p>
233
234 <h2>
235 Mmap and Munmap
236 </h2>
237 <p>
238 <i>Mmap</i> is used in order to create a new address mapping in the virtual address space. Mmap is the system call used behind the beginning mapping of all programs and is an extremely low level function (well, it is even a syscall).
239 </p>
240
241 <p>
242 Munmap is the opposite of mmap: <i>munmap</i> deletes the mappings for the specified address range. If anything in this range is attempted to be accessed, it is considered an invalid address and results in an access violation. For more information on these low level functions, refer to the <a href="https://linux.die.net/man/2/munmap">man pages</a>.
243 </p>
244
245 <h2>
246 GLibC Malloc Mmap Chunks
247 </h2>
248 <p>
249 In Malloc, if a requested size is above a certain threshold then a separate call is made to mmap in order to get a new section of memory for this particular chunk. Very large chunks (which will be referred to as <b>Mmap chunks</b> from this point on) are not handled like normal chunks though.
250 </p>
251
252 <h3>
253 Mmap Chunks Differences
254 </h3>
255
256 <p>
257 <div style="width:97%; font-size:80%; text-align:center; border: 1px solid black; border-radius: 10px; margin: 10px;"><img src="https://live.staticflickr.com/65535/50316980181_4ff13b5811_z.jpg" width="97%"; alt=""><center>Figure 2 - Simplified Munmap Chunk GLibC 2.31 </center></div>
258
259 Once an mmap chunk is freed, they are sent back to system memory with a call to <i>munmap</i> (as seen in Figure 2). With a normal chunk, it is given back to a bin to be used later.
260 </p>
261
262 <p>
263
264 With mmap chunks, the prev_size field is used for part of the chunk that went unused with this specific allocation. The prev_size is added to the size of the mmap chunk to know how much memory to munmap, or free.
265 </p>
266
267 <p>
268 The final difference is that the second bit of the size is used in order to determine if this is an mmap chunk or not (the 'M' bit in Figure 1).
269 </p>
270
271 <h3>
272 Munmap Madness
273 </h3>
274
275 <p>
276 With the funky handling of mmap chunks in GLibC, it was bound that somebody had done research on this in the past. In a very well-done article by Tukan titled <a href="http://tukan.farm/2016/07/27/munmap-madness/">Munmap Madness</a>, the author dives into the possibilities of what can happen with corrupted mmap Malloc chunks. In this article, the author discusses how mmap chunks work, potential exploits and weird quirks about it. For more information on mmap chunks, please refer to his <a href="http://tukan.farm/2016/07/27/munmap-madness/">article</a>.
277 </p>
278
279 <p>
280 What we are taking from the the <i>Munmap Madness</i> article, is that the author mentions <i>altering the size</i> of an Mmap chunk to trigger the removal (munmap) of a section of memory. The main interests are the other parts of a program, such as a thread stack, LibC and so on. Although altering LibC may be difficult, the focus of this article will be on <i>munmapping</i> a small section of LibC in order to take control of the program later.
281 </p>
282
283
284 <h2>
285 Symbol Lookup
286 </h2>
287 <p>
288 With ELF files, one would think that Symbol Lookup would be a trivial task. However, Symbol lookup is vastly complex and takes quite of bit of time to understand. In this article, only the GOT/PLT sections will be briefly discussed and the actual dynamic symbol table lookup process will be briefly discussed later.
289 </p>
290
291 <h3>
292 PLT and GOT
293 </h3>
294
295 <p>
296 Have you ever wondered <b>how</b> library functions are magically found without the actual function being defined in the binary? Well, I can tell ya, it is pretty black magic-y!
297 </p>
298
299 <div style="width:97%; float:left; font-size:80%; text-align:center; border: 1px solid black; border-radius: 10px; margin: 10px;"><img src="https://eli.thegreenplace.net/images/2011/plt_before.png" width="97%"; alt=""><center>Figure 3 - GOT First Time by Eli Bendersky</center></div>
300
301 <p>
302 First off, a library function call is replaced with a function stub, known as the <i>Procedure Linkage Table</i> (PLT) at compile time (with dynamic linked binaries, which is the default compilation mode). When this is called, there are two known states: <i>first time</i> and <i>all others</i>.
303 </p>
304
305 <p>
306 The <i>first time</i> a call is made, the process is passed to the <i>loader</i> in order to resolve the symbol (more on this process later). This is seen in <i>Figure 3</i> by the <i>prepare resolver</i> line of code. Once the symbol is resolved, it is added to the <i>Global Offset Table</i> (GOT) for later usage.
307 </p>
308
309 <p>
310 The next time that the PLT entry for a function is called, the entry is IN the GOT table, as the resolver has already been set. Because of this, we can skip the resolving process and just use the entry in the GOT table for the symbol.
311 </p>
312
313 <p>
314 For more information on the PLT and GOT, please refer to the <a href="https://systemoverlord.com/2017/03/19/got-and-plt-for-pwning.html">article</a> by System Overlord and <a href="https://eli.thegreenplace.net/2011/11/03/position-independent-code-pic-in-shared-libraries/">this</a> article by Eli Bendersky.
315 </p>
316
317 <h3>
318 Symbol Resolving (ld)
319 </h3>
320
321 <p>
322 Now, here is the black magic-y part: <i>how does the loader know where symbols are located</i>? At a high level, the loader iterates through all loaded ELF file symbol tables until it finds an entry to this specific symbol. The full process for how the symbol resolving process is done is out of the scope of the article but a fair amount of it will be discussed below. For an in-depth explanation on this, please look at <a href="https://blogs.oracle.com/solaris/gnu-hash-elf-sections-v2">GNU Hash ELF Sections</a>.
323 </p>
324
325 <h2>
326 Game Plan
327 </h2>
328 <p>
329 Whooo... that was a lot of background information just to understand this technique! Now, with the stage set, we will give a high level overview of the attack technique then and then dive into each aspect of the technique individually.
330 </p>
331
332 <p>
333 The plan for exploitation is as follows:
334 <ol>
335 <li>
336 Overwrite mmap chunk <i>size</i> or <i>prev_size</i>.
337 </li>
338 <li>Free the mmap chunk (with munmap) to override part of the memory mapping of LibC (<code>.gnu.hash, .dynsym</code>)</li>
339 <li>Get mmap chunk over the top of LibC region.</li>
340 <li>Rewrite <code>.gnu.hash</code> and <code>.dynsym</code> sections of LibC ELF.</li>
341 <li>Call previously uncalled function for code execution.</li>
342 </ol>
343
344 At a high level, the steps are shown above. The goal is to rewrite the symbol table of LibC in order to redirect the course of execution when a new symbol for a function is being resolved. Let’s now understand each of the steps listed above in detail.
345 </p>
346
347 <h2>
348 Altering Mmap Chunk Size
349 </h2>
350 <h3>
351 Why?
352 </h3>
353 <p>
354 The purpose of this step is to change the size of the chunk to <i>overlap</i> with LibC. Then, when we free this chunk, it will munmap memory associated with LibC. The fruit of altering the size is only apparent after freeing and reallocating in later steps. But, our main goal is to control a normally <i>read-only</i> section of LibC: <code>.gnu.hash</code> and <code>.dynsym</code>.
355 </p>
356
357 <h3>
358 Mmap Chunk Review
359 </h3>
360 <p>
361 Mmap chunks have two main components that dictate the addresses to be freed: <i>size</i> and <i>prev_size</i>.
362 </p>
363
364 <p>
365 By altering the <i>size</i> of a chunk, we can control the amount of bytes that are unmapped from the point of the original allocation, or going <i>forward</i>. Additionally, the <i>prev_size</i> can be used to munmap chunks going <i>backwards</i> from the original point of allocation. The prev_size field is used for the <b>current chunk</b> with mmap chunks, not for the size of the previous chunk. For the purpose of this exploit, only altering the size is going to be useful though. I wanted to make mention of altering the <i>prev_size</i> because it can be useful in other mmap chunk heap exploits though!
366 </p>
367
368 <h3>
369 Valid Chunks
370 </h3>
371
372 <p>
373 For an mmap chunk, the following must to be true:
374 <ul>
375 <li>Mmap bit must be set (2nd bit of the size metadata)</li>
376 <li><code>prev_size + size</code> must to be a page size (0x1000 for example) </li>
377 </ul>
378
379 The source code for both of these checks can be seen in Figure 2 (way above).
380 </p>
381
382 <h3>
383 Chunk Attack Size
384 </h3>
385 <p>
386 The size of the chunk is different on a case by case basis. The important part is that the chunk needs to overlap with the <code>.gnu.hash</code> and <code>.dynsym</code> of LibC in order to rewrite the symbol table entry later on. To see the sizes of these sections, the tool <code>readelf</code> is extremely useful.
387 </p>
388
389 <p>
390 In general, the size to overwrite with can be calculated with the following forumla: <code>size_of_chunk = bytes_to_libc + bytes_to_overlap__dynsym</code>. Then, in the next step, when the chunk is freed, LibC (or a different library) will be gone from the virtual address mapping.
391 </p>
392
393 <h2>
394 Free the Chunk
395 </h2>
396 <p>
397 From the previous step, we have created an mmap chunk that has a size overlapping part of LibC. All of the hard work for this was done! All we have to do is to call <i>free</i> on this corrupted chunk. Now, part of LibC will be unmapped from the virtual address space.
398 </p>
399
400 <h2>
401 Overlap Chunk with LibC
402 </h2>
403
404 <p>
405 <div style="width:97%; font-size:80%; text-align:center; float : left; border: 1px solid black; border-radius: 10px; margin: 10px;"><img src="https://live.staticflickr.com/65535/50317704177_395cc78219_w.jpg" width="97%"; alt=""><center>Figure 4 - Overlap Mmap Chunk on LibC </center></div>
406
407 From the previous step, we have removed a significant portion of LibC from the virtual address space. The goal of this step is to <b>gain control</b> of this section of LibC (as seen in Figure 4).
408 </p>
409
410 Although the allocation appears to be simple, it is more complicated than one would think. There are two main pain points with this:
411 <ul>
412 <li>mmap_threshold</li>
413 <li>Heap Locations</li>
414 </ul>
415
416 </p>
417
418 <h3>
419 mmap_threshold
420 </h3>
421 <p>
422 Very large chunks (<i>mmap chunks</i>) are assigned in a completely different way in order to prevent fragmentation with <i>one-off</i> extremely large chunks. The <i>mmap_threshold</i> is used in order to determine the largest chunk size that should go onto the standard section of the heap. In order to allocate an mmap chunk, the size has to be larger than the <i>mmap_threshold</i>.
423 </p>
424
425 <p>
426 When an mmap chunk is freed, the size of the chunk is checked with the <u>previously largest freed</u> mmap chunk (or the default size), which is known as the <i>mmap_theshold</i>. If the size being freed is larger, then the mmap_threshold is updated. For example, mmap_theshold is 0x100000. If we free a chunk of size 0x200000 then the mmap_theshold gets updated to 0x200000.
427 </p>
428
429 <p>
430 If the size of the chunk being allocated is NOT larger than the mmap_threshold value, then the chunk will be put into the normal heap section instead of getting a special mmap chunk.
431 </p>
432 <h3>
433 Heap Locations
434 </h3>
435 <p>
436 The heap locations is just about if the physical spot in memory is actually available or not. This can be fixed with proper <i>heap feng shui</i>. Heap Feng Shui is the process of arranging the heap memory in the exact way that an attacker needs.
437 </p>
438
439 <p>
440 Getting the mmap chunks directly behind LibC just requires some knowledge of how these chunks are allocated. From empirical observations of my own and Tukan, here is what the common ordering from (at least, on my 16.04 Ubuntu instance):
441
442 <ul>
443 <li>Memory above LibC and below the loader</li>
444 <li>Below the mmap_base (practically, just below LibC). Allocations are made consecutively below each other.</li>
445 </ul>
446 </p>
447
448 <p>
449 Now that the chunk has been allocated into the proper location (over LibC) we can move on to the next step. A visual diagram of the <i>before</i> and <i>after</i> can be seen above in Figure 4.
450 </p>
451
452 <p>
453 NOTE: Mmap initializes all memory to be NULL. So, all of the values from the original mapping of LibC (that we munmapped) are gone.
454 </p>
455
456 <h2>
457 Rewriting LibC .gnu.hash and .dynsym
458 </h2>
459 <p>
460 Recall, from the previous step, we control a chunk that overlaps with what used to be the beginning of LibC.
461 </p>
462
463 <p>
464 Now begins the real fun :) Rewriting the symbol resolution process! In order to rewrite the parts of LibC, there are multiple ways to go about it:
465 <ol>
466 <li>Copy in the LibC sections byte for byte. Then, make several small changes to the symbol table. This is the technique that Qualys chose to use.</li>
467 <li>Completely reverse the process and deterministically figure out what to write. </li>
468 <li>Step through the code in GDB to understand the loader and write only what is needed.</li>
469 </ol>
470
471 Option 1 is likely easiest but would not help me understand the resolving process as a whole. Upon my preliminary research of option 2, it seemed to be too complex for my purposes. The symbol resolution process uses complicated hashing, bloom filters and other crazy things. So, rewriting this section with a completely deterministic understanding sounded like too much effort for this project, but doable (could be a future research project though). For more information on this, please visit <a href="https://blogs.oracle.com/solaris/gnu-hash-elf-sections-v2">here</a>.
472
473 <p>
474 After ruling out the copy-paste method of 1 and the hard reversing of 2, I decided to go with option 3. Although option 1 would have worked, option 3 looked new and interesting to learn about!
475 </p>
476
477 <h3>
478 What Is Actually Needed?
479 </h3>
480 <p>
481 First, let's setup a nice debugging ENV. Viewing assembly by itself is very complex and tedious to look at. So, for the purpose of this, having the LibC source code attached is really nice. This can be done by downloading the source code of the version of LibC you are trying to debug and running the following command in GDB: <code>gdb> dir /libc/source/location</code>. This is to set GDB to look for source code at the location that is set.
482 </p>
483 <p>
484 After stepping through a program with the source code hooked up, I realized that there were 4 main locations that needed to be set (from empirical testing):
485 <ul>
486 <li>l_gnu_bitmask</li>
487 <li>l_gnu_buckets</li>
488 <li>l_gnu_chain_zero</li>
489 <li>Symbol Table Entry</li>
490 </ul>
491
492 The first three entries have to do with <b>locating</b> the actual spot where the symbol table is located. The last field we are overwriting is symbol table entry itself.
493 </p>
494
495 <h3>
496 Symbol Table Entry Locating
497 </h3>
498 <p>
499 After setting up a version of LibC with debugging symbols and source code attached, the reversing was ready to go. To do the actual debugging, I had two windows open: the modified version (corrupted) and one with the regular flow (non-corrupted). The corrupted version will only have NULLs in this section to start with because mmap initializes all memory to NULL. Figure 5 shows this setup:
500 <div style="width:97%; font-size:80%; text-align:center; border: 1px solid black; border-radius: 10px; margin: 10px;"><img src="https://live.staticflickr.com/65535/50317109232_ae6a87cdd4_c.jpg" width="97%"; alt=""><center>Figure 5 - Two Screen Difference </center></div>
501 </p>
502
503 <p>
504 After reversing the symbol table resolving process for a while, it became apparent that the function doing the actual symbol resolving (that handled parts of LibC that we corrupted) was the function <code>do_lookup_x</code>. This is called from the trampoline function <code>_dl_runtime_resolve</code>, which is the first thing called from the PLT stubs.
505 </p>
506
507 <p>
508 The function <code>do_lookup_x</code>
509 iterates all ELF files until it finds the one with the proper symbol. Step through <a href="https://code.woboq.org/userspace/glibc/elf/dl-lookup.c.html#332">do_lookup_x</a> until <i>LibC</i> comes up as the ELF entry to look for the symbol to resolve. Once there, I did the following steps (on repeat), until the symbol resolution process worked again:
510 <ol>
511 <li>Found a LibC value that is corrupted (this is going to be NULL instead of proper value). This is shown in the right terminal in <i>Figure 5</i>.</li>
512 <li>Found <i>proper</i> value in non-corrupted version of the binary with a regular symbol resolution process. This is shown in the left terminal in <i>Figure 5</i>.</li>
513 <li>Wrote proper value to the same exact location in LibC (corrupted version) via the overlapping mmap chunk that we allocated in step 3. Now, this step in the symbol resolution process will start working again.</li>
514 <li>Repeat steps 1-3 until the entire symbol resolution process is working, as expected.
515 </ol>
516
517 After repeating this step a handful of times, the proper values will be set to finally resolve the symbol we want!
518 </p>
519
520 <h3>
521 Symbol Tables
522 </h3>
523 <p>
524 Once the entry has been located, faking the symbol table entry is very simple. <a href="https://code.woboq.org/userspace/glibc/elf/elf.h.html#529">Symbol table entries</a> are made up of the following format:
525 <pre>
526 typedef struct {
527 Elf64_Word st_name;
528 unsigned char st_info;
529 unsigned char st_other;
530 Elf64_Half st_shndx;
531 Elf64_Addr st_value;
532 Elf64_Xword st_size;
533 } Elf64_Sym;
534 </pre>
535
536 It is recommended that the <i>entire</i> symbol table entry is just copied into memory so that the rest of the lookup process looks as expected. There is ONE extremely important field to point out though: <b>st_value</b>.
537 </p>
538
539 <p>
540 Assuming this is a relative offset entry (which can be altered with the type field), edit the <i>st_value</i> to be the offset of whatever function you would like to call! For a situation where a function is being resolved, we can set this to point to ANY function, including <b>system</b> or a one_gadget.
541 </p>
542
543 <h2>
544 Function Call
545 </h2>
546 <p>
547 What can we call? We can call ANY function (or in the middle of a function) that is within a close proximity of the symbol we overwrote. Practically, anything within the same relative address space could be called, even functions/symbols from other libraries loaded close by (although, I have not tested this myself, this should work). All we need to know is a relative offset from LibC (or the library we are overwriting).
548 </p>
549
550 <p>
551 The function that is going to be called must be a symbol table overwritten within a library. Additionally, this function must <u>not have been called before</u>. This is because the symbol resolving process is what we are overriding, which only happens the first time a symbol in a dynamically linked library is resolved (recall this from the PLT/GOT section in the background).
552 </p>
553
554 <p>
555 This can be used to call <i>system</i>, a one_gadget, another function or be the start of a ROP chain. At this point, this is where all of the hard work passes off! :)
556 </p>
557
558 <h2>
559 Thoughts
560 </h2>
561 <p>
562 Overall, this technique is pretty devastating but is extremely technical and tedious. Below are the pros and cons of this technique.
563 </p>
564 <h3>
565 Pros
566 </h3>
567 <p>
568 Very large chunks (mmap) are typically not discussed much with heap exploitation techniques. <i>House of Muney</i> is an opening into this realm.
569 </p>
570
571 <p>
572 Here are some pros to the technique:
573 <ul>
574 <li>Bypasses <u>address space layout randomization</u> (ASLR) because symbol tables can have relative offsets.</li>
575 <li>Requires NO leaks.</li>
576 <li>A single buffer overflow can be enough to start this exploitation method.</li>
577 <li>Mmap chunk heap exploitation technique, which is not discussed very much. <i>House of Muney</i> is an opening into this realm. </li>
578 </ul>
579 </p>
580
581 <h3>
582 Cons
583 </h3>
584 <p>
585
586 <ul>
587 <li>This vulnerability does require the ability to overwrite the size of a mmap chunk. </li>
588 <li>Known <b>relative</b> location of the overwritten chunk. In some scenarios, this may need to be brute forced.</li>
589 <li>Full RELRO or static compilation would prevent this attack from being successful because all symbols are loaded prior to the program running (no lazy symbol resolution).</li>
590 <li>The LibC (or other library) version being attacked must be known or brute forced in order to have the offsets work properly.</li>
591 <li>Fairly good control over the size of allocations in order to get mmap chunks in the proper locations</li>
592 </ul>
593
594 Being able to overwrite the size of an <i>mmap</i> chunk is a little odd. Two of the main vulnerabilities with heap exploitation, use after free and double free, are not nearly as viable (but still possible) because mmap chunks are <i>not</i> put into bins. Because of this, either a bad indexing method or (more likely) a buffer overflow vulnerability needs to be found.
595 </p>
596
597 <h3>
598 POC
599 </h3>
600 <p>
601 Want to see an actual POC? As part of documenting this technique, the Github repo <a href="https://github.com/mdulin2/munmap-and-rewrite">House of Muney</a> has everything needed in order to understand this technique. In particular, it has a well-commented proof of concept, a pre-made pwntools script to load the file with the non-optmized LibC version with debugging symbols and a nice compilation script. If you really want to understand the technique, it is recommended that you play with this POC. It should be noted that one of the values (to be written) is skipped because it is not completely necessary to write, but should be accounted for when indexing.
602 </p>
603
604 <h2>
605 Conclusion
606 </h2>
607
608 <p>
609 Overall, this is an incredible technique for gaining code execution, although highly technical and complicated. In the future, I would love to see more techniques about exploiting LibC with mmap chunks and gaining code execution in different/interesting ways. I hope you enjoyed the article and learned something interesting about heap exploitation and computers today.
610 </p>
611
612 <p>
613 Major S/O's to the <a href="https://dayzerosec.com/">Day[0]</a> podcast for putting the Qmail exploit on my radar, Tukan for his work on malloc mmap chunks, Georgi Guninski for his QMail finding 15+ years ago, both Dinesh Shetty and iamalsaher for the reviews and Qualys for posting this technique in their exploit. Feel free to reach out to me (contact information is in the footer) if you have any questions or comments about this article. Cheers from <b>Maxwell "ꓘ" Dulin</b>.
614 </p>
615 </description><guid isPermaLink="false">https://maxwelldulin.com/BlogPost?post=6967456768</guid><pubDate>Thu, 08 Oct 2020 00:00:00 +0000</pubDate></item><item><title>House of Mind - Fastbin Variant in 2021</title><link>https://maxwelldulin.com/BlogPost?post=2257705984</link><description><h2>
616 Introduction
617 </h2>
618
619 <p>
620 Have you ever discovered something amazing only to later realize that somebody else had already beaten you to it? In this article, I wanted to describe a new (rediscovered) GLibC heap exploitation method that works on all versions of the allocator. With this method, an attacker can write a heap value to an arbitrary location (WRITE-WHERE primitive).
621 </p>
622
623 <p>
624 When I started looking for new ways to exploit the allocator via the <i>non-main arena</i> chunks, I thought I had found a new technique! However, part way through writing this article, I reread the original post (<a href="https://dl.packetstormsecurity.net/papers/attack/MallocMaleficarum.txt">Malloc Malefaricum</a>) on the House of Mind
625 only to realize that there is a <i>fastbin</i> variant of the attack as well. The original use case for the fastbin variant of the House of Mind writes a heap pointer to a GOT address to jump to shellcode. But, this technique to trivially pop a shell is no longer viable because of NX. With the original House of Mind being patched and the fastbin variant no longer being an auto shell, this technique was mostly forgotten about, waiting to be rediscovered for a new purpose. So, new or not, nobody seems to be talking about this technique. In this article I wanted to shed light onto the House of Mind's Fastbin Variant as a useful WRITE-WHERE primitive and discuss when it can be used.
626 </p>
627
628 <p>
629 This post will (hopefully) have a POC in <a href="https://github.com/shellphish/how2heap/pull/136">how2heap</a>; the link is currently to a pull request with all of the code. For more security related content, check out this blog for other things, such as the <a href="https://maxwelldulin.com/BlogPost?post=6967456768">House of Muney</a> heap exploitation technique.
630 </p>
631
632 <p>
633 Before we get to the meat of the technique, we will go over how the heap allocator works. I cannot stress enough how important understanding the allocator is for heap exploitation. Trying to pwn the heap without understanding the inner workings of the allocator is like trying to shot a fish in a lake.
634 </p>
635
636 <h2>
637 Chunks
638 </h2>
639
640 <p>
641 Chunks are the main object that users interact with. There are two main states to a chunk: <i>allocated</i> and <i>free</i>. The following picture demonstrates a <i>free</i> chunk:
642 <div style="width: 98%; font-size:80%; text-align:center; float : left; border: 1px solid black; border-radius: 10px; margin: 10px;"><img src="https://docs.google.com/drawings/d/1YrlnGa081NpO0D3wcoaJbGvhnPi3X6bBKMc3bN4-oZQ/pub?w=940&h=669" width="95%" alt=""><center>Figure 1 - Free Chunk by Sploitfun</center></div>
643
644
645 The first field is the size of the previous chunk (prev_size). This is only used if the previous chunk is free. The second field is the <b>chunk size</b>. The chunk size represents the size of the data of the chunk and the metadata about the chunk. The metadata of the chunk includes three fields: prev_inuse (if the previous chunk is in use), mmap (is the previous chunk mmapped) and if the chunk is in a non-main arena. We will touch on the <i>non-main arena</i> bit more in depth later.
646 </p>
647
648 <p>
649 On an allocated (non-free) chunk, the third and fourth field are used as data sections. However, on a free chunk, the third field is used in order to store a pointer to other freed chunks. This field is known as the forward pointer or the <i>Fd</i> field. The fourth field is exactly the same, except that it stores a backwards pointer or <i>bk</i>. <!-break-->
650 </p>
651
652 <h2>
653 Bins
654 </h2>
655
656 <p>When using Malloc, chunks that are freed are put into a local storage to be reused. The storage locations for the free chunks are called <i>bins</i>.
657 </p>
658
659 <p>
660 There are a multiple kinds of bins for different sizes and situations. All bins use a <a href="https://www.geeksforgeeks.org/data-structures/linked-list/">linked list</a> data structure in order to keep track of the free chunks in the bin. For the purposes of this technique, only a single bin needs to be understood: <i>fastbins</i>.
661 </p>
662
663 <h3>
664 Fastbin
665 </h3>
666
667 <p>
668 Prior to version 2.26 (current at 2.33), the fastbin was the first location where chunks were put into, if the size matched up. Fastbin chunks are very small chunks with the idea that small chunk sizes are going to be used frequently. On 64-bit systems (assumed for the rest of the article) the bins range from chunk sizes of 0x20-0x80 bytes in 0x10 byte intervals.
669 </p>
670
671 <p>
672 Fastbins use a <i>singly linked list</i>, while several of the other bins use doubly linked lists. This means that free chunks only have a single pointer to the chunk in front of it ('fd' field in figure 1). Because of this, validation of fastbin pointers is difficult to do.
673 </p>
674
675 <p>
676 Only fastbins are necessary for understanding how this technique works. However, this article only scratches the surface of how the allocator works, in particular, bins and chunks. If you want to learn more about the allocator, <a href="https://azeria-labs.com/heap-exploitation-part-2-glibc-heap-free-bins/">Azeria Labs</a> and <a href="https://sploitfun.wordpress.com/2015/02/10/understanding-glibc-malloc/">Sploitfun</a> have awesome articles on this.
677 </p>
678
679 <h2>Arenas</h2>
680
681 <p>
682 Arenas are a <code>struct</code> that is shared between threads which contains references to heaps, as well as the bins (where the free chunks are stored at) and other state information about a heap. Threads assigned to each arena will allocate memory from that arena's free lists. In layman's terms, the arena is the metadata information that makes the allocator work. All of this state information is stored in the <code>malloc_state</code> struct.
683 </p>
684
685 <p>
686 A single threaded process has a single arena called the <i>main arena</i>. When threads become involved, multiple arenas are used in order to allow for concurrent heap data access, as heap data is specific to a process. These other arenas are called <i>non-main</i> arenas. So, this begs the question: <i>"How does the allocator know which arena a chunk belongs to when being freed?"</i> Excellent question!
687 </p>
688
689 <h3>
690 Non-Main Arena Bit
691 </h3>
692
693 <p>
694 First, we need to learn about the third bit of the <i>size</i> field (labeled as the 'N' bit in figure 1 above). This is used in order to specify if this chunk belongs in a <i>non-main arena</i> or not. If this bit is set, then the chunk belongs to a <i>non-main arena</i> and if the bit is NOT set, the chunk belongs to the <i>main arena</i>. This bit is set at allocation time, prior to the chunk being passed back to the user.
695 </p>
696
697 <h3>
698 Finding the Arena
699 </h3>
700
701 <p>
702 <div style="width: 500px; font-size:80%; text-align:center; padding: 10px; float: right; border-radius: 10px; margin: 20px;"><img src="https://live.staticflickr.com/65535/51014104368_3865d361f3_o.png" width="350px" alt=""><center>Figure 2 - Get non-main arena from chunk </center></div>
703 The <a href="https://elixir.bootlin.com/glibc/glibc-2.23/source/malloc/arena.c#L127">code</a> below finds the arena to be used in GLibC:
704 <pre>
705 #define arena_for_chunk(ptr) \
706 chunk_non_main_arena (ptr) ? \
707 heap_for_ptr (ptr)->ar_ptr : \
708 &main_arena
709 </pre>
710 </p>
711
712 <p>
713 The else (second part of the conditional from the <a href="https://www.freecodecamp.org/news/c-ternary-operator/">ternary operator</a> at line #4 above) is easier to understand, so we will start there. If the chunk is in the <i>main arena</i> (or, not a non-main arena chunk) then return a pointer to the <a href="https://elixir.bootlin.com/glibc/glibc-2.23/source/malloc/malloc.c#L1761">main arena</a> global variable. This is all that is done to find the main arena.
714 </p>
715
716 <p>
717 The first part of the conditional (line #3 above) is for a <i>non-main arena</i> chunk, which is specified by the <i>non-main arena</i> bit flag on the size discussed earlier. If this is the case, it calls another macro called <a href="https://elixir.bootlin.com/glibc/glibc-2.23/source/malloc/arena.c#L125">heap_for_ptr</a>, which is where most of the magic happens at. This macro is shown below:
718 <pre>
719 #define heap_for_ptr(ptr) \
720 ((heap_info *) \
721 ((unsigned long) (ptr) & \
722 ~(HEAP_MAX_SIZE - 1))) \
723 </pre>
724 </p>
725
726 <p>
727 The <code>heap_for_ptr</code> macro takes the chunk being freed and removes a large portion of the least significant bits. This is done by ANDing the value with a large quantity of 0s. But why? Here's the punchline! The bottom of a <i>non-main arena</i> heap has a <u>pointer to our arena</u>! To be precise, this is the <a href="https://elixir.bootlin.com/glibc/glibc-2.23/source/malloc/arena.c#L48">heap_info</a> struct; the first field (<code>ar_ptr</code>) has the pointer to the arena. Notice the <code>(ptr)->ar_ptr</code> code being used in the <code>arena_for_chunk</code> macro above to get the arena from the <code>heap_info</code> struct.
728 </p>
729
730 <p>
731 This is quite clever! The user will always have a pointer to the malloc chunk (the chunk is being freed). So, by storing the arena at the bottom of the heap itself, we can just remove the least significant bits of the chunk to find the arena! If this does not make sense, I completely understand. Figure 2 has a visual representation of this that should help.
732 </p>
733
734 <p>
735 To wrap this up, here are the important notes:
736 <ul>
737 <li>The <code>arena_for_chunk</code> macro gets the arena by using the chunk itself.</li>
738 <li> The <i>non-main arena</i> bit specifies which functionality to use for getting an arena. </li>
739 <li>The <i>main arena</i> is stored in a global variable and the <i>non-main arena</i> does some clever math on the chunk in order to get the arena.</li>
740 </ul>
741
742 For more information on GLibC arenas, sploitfun covers it extensively <a href="https://sploitfun.wordpress.com/2015/02/10/understanding-glibc-malloc/">here</a> and the Malloc Maleficarum paper covers it quite well too.
743 </p>
744
745 <h2>
746 Flow of the Attack
747 </h2>
748 <p>
749 The attack writes the pointer of a chunk being freed to a nearly arbitrary location; this is known as a WRITE-WHERE primitive. In the land of GLibC Heap exploitation, the <a href="https://ctf-wiki.github.io/ctf-wiki-en/pwn/linux/glibc-heap/unsorted_bin_attack/">Unsorted Bin Attack</a> and the <a href="https://ctf-wiki.org/pwn/linux/glibc-heap/large_bin_attack/">Large Bin Attack</a> are good reference points for similar WRITE-WHERE primitives.
750 </p>
751
752 <p>
753 For the attack itself, it can be broken up into several stages:
754
755 <ul>
756 <li>Heap Feng Shui (aligning controllable data with <code>heap_info</code> struct)</li>
757 <li>Creating a fake <code>heap_info</code> and arena</li>
758 <li>Corrupting a fastbin sized chunk</li>
759 <li>Trigger the write via freeing the altered chunk</li>
760 </ul>
761
762 The steps for this attack will be broken down in the sections below.
763 </p>
764
765 <h2>
766 Heap Feng Shui
767 </h2>
768 <p>
769 As in the original House of Mind, our main goal is to create a fake arena to be abused. In order to get the arena, we first need to create a fake <code>heap_info</code> struct. Where is this located at?
770 </p>
771
772 <p>
773 From looking at the macro <code>heap_for_ptr</code> (shown above) the pointer is found by removing a large portion of the least significant bits of the chunk. For instance, a heap pointer like 0x555558a4340 would be transformed into 0x55555000000 to find the <code>heap_info</code> struct. An example of this can be seen in Figure 2 above. So, to create a fake <code>heap_info</code> struct and set the pointer for the arena properly, we will need to setup the pointer at the EXACT right spot in memory. How is this done?
774 </p>
775
776 <h3>
777 Alignment of Allocations
778 </h3>
779 <p>
780 By allocating a large amount of chunks from the heap (ensure the size of each chunk smaller than the <a href="https://elixir.bootlin.com/glibc/glibc-2.23/source/malloc/malloc.c#L1731">mmap_threshold</a>), we can control a section in memory that can be used for a fake <code>heap_info</code> struct!
781 All we have to do is manipulate the heap so that the
782 attacker controls the area of memory that the corrupted chunk is aligned down to at intervals of <a href="https://elixir.bootlin.com/glibc/glibc-2.23/source/malloc/arena.c#L27">HEAP_MAX_SIZE</a> when calling <code>arena_for_chunk</code>; this can be seen in figure 3. <div style="width: 500px; text-align:center; float: left; border: 1px solid black; padding: 10px; border-radius: 10px; margin: 20px; font-size:80%"><img src="https://live.staticflickr.com/65535/51014895122_ebf1acc008_o.png" width="300px" alt=""><center>Figure 3 - Fake Heap Info Alignment</center></div>
783 </p>
784
785 <p>
786 The <code>HEAP_MAX_SIZE</code> value varies depending on many settings. From empirical testing on a Ubuntu 16.04 64-bit machine, the size is 4MB. Because the <i>main_arena</i> is not aligned to values of <code>HEAP_MAX_SIZE</code>, this will require an average of '0x2000000' bytes of memory being allocated but no more than '0x4000000' bytes. In practice, this alignment is necessary because chunks at lower areas of the heap align down to an area of memory that is neither attack controlled nor mapped at all.
787 </p>
788
789 <p>
790 Once we have a chunk at the proper location lined up, we need to setup two fake structures for this to work. The alignment is just the first piece in the puzzle.
791 </p>
792
793 <h2>
794 Setting Up Fake Heap_info
795 </h2>
796
797 <p>
798 <pre>
799 typedef struct _heap_info
800 {
801 malloc_state ar_ptr; // Arena
802 ...
803 }
804 </pre>
805
806 Once we have control of the aligned memory necessary for a <code>heap_info</code> struct, we need to <i>prepare</i> a fake one. Luckily for us, only a single field needs to be faked: <code>ar_ptr</code>. This field, which is the first entry of the <a href="https://elixir.bootlin.com/glibc/glibc-2.23/source/malloc/arena.c#L48">heap_info</a> struct, is the arena pointer. So, at a <code>MAX_HEAP_SIZE</code> aligned value, we need to specify the location (pointer) of the arena, which seems easy enough. Where do we put this at for maximum damage though? This is where things start to come together!
807 </p>
808
809 <h2>
810 Fake Arena
811 </h2>
812
813 <h3>
814 Fake Arena Location
815 </h3>
816
817 <p>
818 From here, we will work backwards from the WRITE to the get to the proper location of the fake arena. The WRITE takes place <a href="https://elixir.bootlin.com/glibc/glibc-2.23/source/malloc/malloc.c#L3948">here</a> when writing a fastbin pointer into the arenas free list. If we want to overwrite somewhere with our heap chunk, we have to consider two items: arena location and the fastbin size.
819 </p>
820
821 <p>
822 Because the fake arena is controlled directly by us and can be set to an arbitrary location; this is the most important value to consider. Recall, this is set in the fake <code>heap_info->ar_ptr</code> struct discussed above. If we want to overwrite a specific location in memory with our heap chunk, we must put the arena close to the target memory address.
823 </p>
824
825 <h3>
826 Arena Writing Offset
827 </h3>
828 <p>
829 <pre>
830 struct malloc_state
831 {
832 mutex_t mutex;
833 int flags; // Formly max_fast
834
835 mfastbinptr fastbinsY[NFASTBINS]; // Fastbins
836 ...
837 }
838 </pre>
839 Besides the location of the arena, the writing of the chunk to a fastbin adds an <i>offset</i> to the WRITE. The <code>fastbinsY</code> array (shown above in the <code>malloc_state</code> struct) is an array of pointers that makes up the fastbins data storage; the <code>fastbinsY</code> array is the third entry in the <code>malloc_state</code> struct. This causes an offset of all of the struct fields that are ahead of the <code>fastbinsY</code>. For instance, in 2.23 (shown above), the offset is only 0x8 because of the 4 byte mutex and the 4 byte flags field. In 2.27+, the additional field <a href="https://elixir.bootlin.com/glibc/glibc-2.27/source/malloc/malloc.c#L1684">have_fastchunks</a> makes the offset 16 bytes until the <code>fastbinsY</code> array.
840 </p>
841
842 <p>
843 Finally, we can deal with the fastbins offset itself. When the chunk is written into the <code>fastbinsY</code> array, the index is based upon the <u>chunk size</u>. Different chunk sizes are written to different locations of the array, as each chunk size has its own bin. For instance, the smallest size 0x20 is written into the <code>fastbinsY[0]</code> and the largest size 0x80 is written into <code>fastbinsY[6]</code>.
844 </p>
845
846 <p>
847 When choosing the location of the arena, the offset (to overwrite the proper memory location) must be carefully chosen based upon the size of the chunk being freed and the version of malloc.
848 </p>
849
850 <h3>
851 Numerical Example
852 </h3>
853 <p>
854 Let's assume our target is the address <code>0x5555554444</code> for GLibC 2.23 and we are writing a chunk of size 0x30. In order to write to the proper location, we would need to subtract the offset to <code>fastbinsY</code> (8 bytes) array. Additionally, we need to account for the index of the fastbins chunk being written. A size of 0x30 is the 2nd entry in the fastbins, which results in 8 more bytes needing to be subtracted. This ends up being <code>0x5555554444-8-8 = 0x5555554434</code> for the arena location to use. Now, when we write the chunk to the fastbins, the 8+8 will be added back into the address to write to our actual target <code>0x5555554444</code>.
855 </p>
856
857 <p>
858 At first, the subtraction on the location of the arena does not seem intuitive. However, let's do this improperly with the same problem from above. If we choose the arena to be <code>0x5555554444</code> (our target) then the added offset will actually write to <code>0x5555554454</code> because the write occurs at arena + 0x10. Sometimes, I wish I would have paid more attention to math as a 3rd grader!
859 </p>
860
861 <h3>
862 Fixing the Size Sanity Check
863 </h3>
864 <p>
865 <pre>
866 if next_chunk_size <= 0x10 or
867 next_chunk_size >= arena->system_mem
868
869 Crash
870 </pre>
871
872 Using the fastbin variant of the House of Mind on recent versions of LibC only one security check needs to be bypassed. The <a href="https://elixir.bootlin.com/glibc/glibc-2.23/source/malloc/malloc.c#L3897">code</a> (pseudocode shown above) is validating that the next chunks size is not larger than the system allocation and the next chunks size is not smaller than the smallest possible chunk (0x10). In layman's terms, check if the next chunk size is crazy small or crazy large. If the above conditional is true, then the program will abort.
873 </p>
874
875 <p>
876 For the smaller end, the size of the <i>next chunk</i> needs to be greater than or equal to 0x10. This should be trivial to bypass because there is already a chunk above this one! So, you can just set the size of the fake chunk to line up with the original size of the chunk for the bypass. If this is not possible (for offset reasons), then this value could be written to a controllable offset.
877 </p>
878
879 <p>
880 The validation on the larger side is a little more complicated though. Because we have created the arena, the value of the arenas <code>system_mem</code> needs to be set. <code>system_mem</code> needs to be larger than the next chunk size (which has a minimum of 0x10). The <code>system_mem</code> value is at an offset of 0x880 on 2.23 and 2.29 is at 0x888 for the <code>malloc_state</code> struct. The offset depends on the version of GLibC's <code>malloc_state</code> struct but can easily be found while using GDB.
881 </p>
882
883 <p>
884 Once you find an alignment for the arena that has a proper value at the offset (or you write it yourself), the sanity check has been bypassed! With this check bypassed, the chunk will be put into the arenas fastbin to overwrite the memory address when the chunk is freed.
885 </p>
886
887 <h2>
888 Corrupting a Fastbin Chunk
889 </h2>
890
891 <p>
892 <div style="width: 500px; font-size:80%; text-align:center; float: right; border: 1px solid black; padding: 10px; border-radius: 10px; margin: 20px;"><img src="https://live.staticflickr.com/65535/51014857006_b08c15358a_o.png" width="450px" alt=""><center>Figure 4 - Fake Chunk Proper Setup</center></div>
893 In order to force a fake arena to be used, we must free a chunk! So, what should this chunk look like? There are a few main items to consider (shown in figure 4):
894 <ul>
895 <li>Use the correct chunk size. This comes down to three things:
896 <ul>
897 <li>Setting up a size of the chunk being freed for the proper offset on the WHERE place to write. Naturally, this has to be a fastbin sized chunk.</li>
898 <li>Setting the chunk size to align with a valid <code>next_chunk</code> size.</li>
899 <li>Set the non-main arena bit (bit #3 as shown in figure 1) for a chunk.
900 </li>
901 </ul>
902 </li>
903 <li>The chunk MUST align down to the <code>HEAP_MAX_SIZE</code> for our fake arena to be used when the chunk is freed.</li>
904 <li>Use the heap value being written in a smart way.</li>
905 </ul>
906
907
908 Everything above has already been discussed in previous sections besides the final point. So, we will go a little deeper into where to write.
909 </p>
910
911 <h3>
912 Where to Write?
913 </h3>
914 <p>
915 This is a WRITE-WHERE primitive. An attacker fully controls the <i>location</i> (memory address) being written to but NOT the <i>value</i> itself. Although this is mostly true, the value being written is the address of the chunk that we are freeing! So, we do not fully control this value but we can manipulate it by freeing chunks at different spots on the heap.
916 </p>
917
918 <p>
919 This primitive is usually a step in the chain, not the full exploit itself. A common use case for a WRITE-WHERE primitive is to overwrite a maximum index value to a large value in order to induce a further out of bounds read/write issues. For example, in the <a href="https://maxwelldulin.com/BlogPost?post=3107454976">House of Husk</a>, a maximum index value is overwritten in order to overwrite a variety of values in LibC to eventually pop a shell. This works quite well but in certain situations we can do better!
920 </p>
921
922 <p>
923 The value being written is a heap memory pointer. Because this is a pointer, we can use this to overwrite <i>another pointer</i> to cause further corruption. For example, let's picture a string that has a size of 0x200. Then, we use this technique to overwrite a pointer to this string. Later on, we go to edit the string which NOW only has a heap pointer of only 0x70 bytes because of the overwrite. When this edit occurs, it creates a major buffer overflow on the 0x70 sized chunk because it is expects something of size 0x200. If the chunk above our freed chunk (next chunk) has important data in it, this could lead to major memory corruption.
924 </p>
925
926 <h2>
927 Boom Goes the Dynamite (Free)
928 </h2>
929 <p>
930 <center><div style="width: 85%; font-size:80%; text-align:center; border: 1px solid black; padding: 10px; border-radius: 10px; margin: 20px;"><img src="https://live.staticflickr.com/65535/51014237258_3d8a8fd7f9_o.png" width="80%" alt=""><br/>Figure 5 - Full Technique Setup</div></center>
931
932 At this point, we have created the <code>heap_info</code> struct, setup a fake arena and have crafted the perfect chunk, all while avoiding some security checks. Figure 5 (shown above) has the full technique setup in a diagram, in order to make it easier to see. Now all we have to do is call <b>free</b> on our crafted chunk to cause the memory write to occur! We did all of the hardwork already and get to reap the fruit of that work.
933 </p>
934
935 <h2>
936 Profit
937 </h2>
938 <p>
939 Once the chunk has been written, you can now use this to cause even more corruption to eventually pop a shell! Have fun with this WRITE-WHERE primitive.
940 </p>
941
942
943 <h2>
944 Pros & Requirements
945 </h2>
946
947 <p>
948 This attack allows for a WRITE-WHERE primitive of a heap pointer. This attack has its positives and negatives though.
949 </p>
950 <h3>
951 Pros
952 </h3>
953 <p>
954 <ul>
955 <li>
956 Works on all versions of Malloc! The bulk of techniques are version locked.
957 </li>
958 <li>Only requires a single byte controlled value overflow of the size and a heap leak.</li>
959 <li>Writes a large value to a nearly arbitrary location. This can be used as the start of deeper memory corruption, such as the Unsorted Bin Attack usage in the <a href="https://1ce0ear.github.io/2017/11/26/study-house-of-orange/">House of Orange</a>.</li>
960 <li>
961 Writes a heap pointer, which could be used in a similar way to the <a href="https://heap-exploitation.dhavalkapil.com/attacks/unlink_exploit">Unsafe Unlink</a> attack, to cause further memory corruption by overwriting pointers.
962 </li>
963 <li>If the vulnerability for corrupting the chunk can be triggered multiple times, it is possible to trigger the write as many times as you need! For the location to write to, the original arena pointer can be edited or a different offset of <code>MAX_HEAP_SIZE </code> can be used to set a new fake arena.
964 </ul>
965 </p>
966
967 <h3>
968 Requirements
969 </h3>
970 <p>
971 Instead of a cons section, below is a list of requirements for this to work:
972 <ul>
973 <li>Ability to corrupt fastbin sized chunk size field. A single byte overflow would suffice this condition.</li>
974 <li>Known location to write to (fake arena location). This may require a leak.</li>
975
976 <li>Ability to create a fake <code>heap_info</code> struct. This comes down to two things:
977 <ul>
978 <li>An attacker needs to know their relative location on the heap for proper placement of the fake <code>heap_info</code> structure, which likely requires a heap leak. This could potentially be sprayed if the attacker has good enough control of the data though.</li>
979 <li>An attacker must be able to allocate a significant amount of heap data to reach the proper offset for the fake <code>heap_info</code> struct. </li>
980 </li>
981 </ul>
982
983 <li>The overflown chunk MUST be in the <i>main arena</i>. This is because <i>non-main arenas</i> have a size limit to prevent this exact issue from occurring.</li>
984 <li>The next chunk (of the freed fastbin chunk) must be larger than 0x10 and smaller than <code>system_mem</code>.</li>
985 <li>The fake arena <code>system_mem</code> value of the fake arena must be larger than the <i>next chunk</i> value, with a minimum value of 0x10. This is because of a security chunk of the size of a freed chunk.</li>
986 <li>With versions using TCache (2.26+), the TCache bin needs to be filled for the fastbin chunk size where the attack is being performed.</li>
987 </ul>
988
989 Although this feels like a lot of requirements, some of these are trivial to do, such as the next size chunk alignment or using the <i>main arena</i>. If the situation is right, this can be a devastating attack.
990 </p>
991
992 <h2>
993 Future Work
994 </h2>
995
996 <p>
997 Heap exploitation techniques are awesome, but vastly complicated. Because of this, I post fairly consistently about it and contribute to the how2heap repository whenever something interests me. I am in the process of developing a <u>GLibC Malloc Heap Exploitation workshop</u> to help teach this very complex subject. I am looking to start giving this workshop at conferences by the end of the year (2021). I have applied to single conference so far (looking at you DEFCON) but plan on applying to many other technical conferences to give the course. So far, the beta testing has gone extremely well and I have been happy with the participants understanding of the material after taking the course. So, keep an eye out for this course in the future :)
998 </p>
999
1000 <h2>
1001 Conclusion
1002 </h2>
1003 <p>
1004 This went from the heart-pounding <i>new discovery</i> to a <i>let me explain</i> article. Regardless, I hope you enjoyed this and learned something interesting about heap exploitation and computers today. I am happy that this forgotten technique will now be more accessible to those in the binary exploitation world.
1005 </p>
1006 <p>
1007 Feel free to reach out to me (contact information is in the footer) if you have any questions or comments about this article. Cheers from <b>Maxwell "ꓘ" Dulin</b>.
1008 </p></description><guid isPermaLink="false">https://maxwelldulin.com/BlogPost?post=2257705984</guid><pubDate>Mon, 22 Mar 2021 00:00:00 +0000</pubDate></item><item><title>Business Logic Ratings Bug</title><link>https://maxwelldulin.com/BlogPost?post=7676291072</link><description><p>
1009 The web is full of user reviewed rating websites that we trust with our lives every day. Glassdoor allows us to see inside a company; Amazon reviews allow us to see what it is like to own a product; Yelp for restaurants... this is just the world that we live in.
1010 </p>
1011
1012 <p>
1013 But, what if you could <i>sway</i> the rating system? On Yelp, you could make a restaurant appear at the top of every search! Like in a dream, everyone would flock to your restaurant. Or, you could kill a competitors business, making yours look more appealing. This would be an amazing weapon to gain a competitive advantage on the rest of the market. In this article, we discuss a business logic vulnerability that was able to skew the ratings systems on a popular location-based ratings site.
1014 </p>
1015
1016 <h2>
1017 Vulnerability - The Case of Bad Input Validation
1018 </h2>
1019
1020 <h3>
1021 Juice Shop Version
1022 </h3>
1023
1024 <p>
1025 The company asked to remain anonymous and to have no screenshots of the bug. So, we will get creative! To demo the bug, we will look at <a href="https://owasp.org/www-project-juice-shop/">Juice Shop</a>; the bug from OWASP Juice Shop is essentially the same as the real site. For those not familiar, OWASP Juice Shop is an intentionally vulnerable site from the Open Web Application Security Project (OWASP). In fact, this was one of my main resources for learning prior to becoming a security engineer at my current company.
1026 </p>
1027
1028 <p>
1029 OWASP Juice Shop has a <i>customer feedback</i> functionality, which is normal for many applications. This ratings system is on a scale of 1-5 where a sliding scale can be set to choose the rating. On the backend request, this is simply an <i>integer</i> being sent. What if we changed this to something that is NOT 1,2,3,4 or 5? The request for the <i>customer feedback</i> is shown in <i>Figure 1</i> below within Burp.
1030 </p>
1031
1032 <center><div style="width:95%; font-size:80%; text-align:center; border: 1px solid black; border-radius: 10px; margin: 10px; center;"><img src="https://live.staticflickr.com/65535/51398887771_6a87e4f5b8_z.jpg" width="90%" alt=""><center>Figure 1: -100 Rating </center></div></center>
1033
1034 <p>
1035 By changing the <u>rating</u> to a non-expected value, such as -100 shown in Figure 1, we can drastically affect the overall customer ratings! This works in either the positive or negative direction.
1036 The challenge for this is titled <a href="https://github.com/apox64/OWASP-Juice-Shop-Write-Up/blob/master/juice-shop-writeup.md#7-give-a-devastating-zero-star-feedback-to-the-store">give a devastating zero-star feedback to the store</a>. On Juice Shop, we can change the <i>rating</i> value to be set to 0 in order to solve this challenge. Now, this website is meant to be vulnerable. Does this bug look the same on a real and in production website?
1037 </p>
1038
1039 <h3>
1040 The Actual Site
1041 </h3>
1042
1043 <p>
1044 The target website stores information about a location and allows for ratings this specific type of location. When giving a rating on the user interface, the options are given as a collection of 5 stars. The user highlights the amount of stars for the rating (1-5) and this is the value sent to the backend. As a result, it is not possible to enter a value other than 1-5 in the UI. As demonstrated in the example above, this is not enough though! Client-side restrictions are a futile security protection.
1045 </p>
1046
1047 <p>
1048 This seemed like fertile testing ground to go through, as I remembered the Juice Shop example from years ago. I used a web app pentesters best friend Burp to proxy the request and altered the rating to be <b>-5000</b>. But, this failed with a <code>500</code> error, which surprised me, since the application had never thrown me a <code>500</code> error like this before. After trying increasingly smaller negative numbers, to my surprise, <b>-500</b> worked! I did the same thing in the positive direction with positive <b>500</b> and this worked as well. It appears they had some sanity checking on the values but not enough. What does this actually mean though?
1049 </p>
1050
1051 <h3>
1052 Impact of Bug
1053 </h3>
1054
1055 <p>
1056 Most rating systems are calculated by taking the <i>average</i>. This average is then used everywhere on the website for finding locations to visit. In fact, this <i>overall rating</i> is the most important descriptor about a location to decide if people do or do not go somewhere. Being able to inject a rating of -500 or +500 would drastically raise the average rating (even past 5 stars) or drop the rating of the location significantly. Raising it could make the location extremely popular while dropping it would make the location unlikely to be visited.
1057 </p>
1058
1059 <p>
1060 In a community that relies upon the reviews of others, being able to have this <u>large of a stake</u> in the voting on each location allows for the rise in popularity or the downfall of a place by a single person. This compromises the people sourced system entirely; eventually, this could break the trust of the users and force them to use other services. Luckily, the fix for the bug is simple: only allow values from 1-5 on the backend.
1061 </p>
1062
1063 <h2>
1064 Disclosure
1065 </h2>
1066
1067 <p>
1068 From previous experiences, I am nervous when trying to report security vulnerabilities. As a result, I have learned to be very kind and come from the perspective of "<i>I found this bad bug. Please let me help you fix it.</i>" If you go in guns blazing and attacking the service team with comments about how crappy the software is and how great of a hacker you are, then you are unlikely to have a good response with the team (we've all made this mistake before). Keep this in mind when reporting to companies or people without a formal bug disclosure program especially. Yes, I know testing on these sites is technically illegal; I hope that people see the good in us though, as the testing is done in good faith. In this particular case, the company had the best response I have ever received!
1069 </p>
1070
1071 <p>
1072 My initial communication with the company was to a senior engineer over LinkedIn. The company did not have a security email so this was my best course of action. Eventually, a support ticket from the <code>support@company.com</code> got back to me as well but hours after the initial contact with the engineer on LinkedIn.
1073 </p>
1074
1075 <p>
1076 Since the initial LinkedIn message only allows for only 300 characters, after the initial connection I sent a longer message explaining the details of the bug with a few screenshots. In particular, I sent a screenshot with the overall rating for the location being <b>0 stars</b> and the next one being <b>9 stars</b>, even though the limit is 5 stars. At this point, the engineer replied <i>Oh wow, that's pretty bad. we are on it. </i>" The engineering team fixed the bug immediately.
1077 </p>
1078
1079 <p>
1080 After this, the CTO of the company added me on LinkedIn and thanked me for the finding and responsible disclosure. The CTO let me know that a security engineering position would be opening up soon; they wanted me on the short list for the job once the position opened up. Additionally, they offered me a lifetime membership to the application! Considering I use the application quite a lot, this was very exciting for me :) A huge shoutout to the engineer and CTO for the amazing response to the finding. This makes me happy to find bugs and report them to make the internet a safer place.
1081 </p>
1082
1083 <h2>
1084 Conclusion
1085 </h2>
1086
1087 <p>
1088 Vulnerabilities are not always complicated injection attacks. Commonly, they are centered around how the logic of the site; these bugs are undetectable by scanners. Although throwing <code>&lt;script&gt;alert(1)&lt;/script&gt; </code> may find some XSS, lots of bugs require an understanding of the applications logic and expected functionality. Prior to throwing random inputs everywhere, ensure that you understanding the business-logic of the application in test.
1089 </p>
1090
1091 <p>
1092 Feel free to reach out to me (contact information is in the footer) if you have any questions or comments about this article. Cheers from <b>Maxwell "ꓘ"Dulin</b>.
1093 </p></description><guid isPermaLink="false">https://maxwelldulin.com/BlogPost?post=7676291072</guid><pubDate>Wed, 25 Aug 2021 00:00:00 +0000</pubDate></item><item><title>Finding Number Related Memory Corruption Vulns</title><link>https://maxwelldulin.com/BlogPost?post=9715056640</link><description><p>
1094 The root cause of many vulnerabilities are from the mishandling of numbers. The standard <code>int</code> type can go from <code>0x7FFFFFFF</code> all the way to <code>-0x80000000</code> (notice the negative) with an integer overflow. Or, it can be truncated and change the number from positive to negative. Integers can be a nightmare in C and have caused many memory corruption vulnerabilities over the years.
1095 </p>
1096
1097 <p>
1098 Recently quite a few findings have caught my attention that fall into the integer bug classes. A few to call out are the <a href="https://www.qualys.com/2021/07/20/cve-2021-33909/sequoia-local-privilege-escalation-linux.txt">integer truncation bug</a> in the Linux kernel found by Qualys, the <a href="https://securitylab.github.com/advisories/GHSL-2021-088_093-freebsd-bhyve/">signedness conversion</a> bug (issue 2) in the BSD hypervisor by GHSL and an <a href="https://research.checkpoint.com/2021/i-can-take-over-your-kindle/">integer overflow</a> in the Kindle on a buffer allocation size found by Checkpoint. Then, my hacking buddy <a href="https://twitter.com/seiranib">seiraib</a> found an integer overflow bug fuzzing but we could not find where the overflow actually occurred at. All of this got me wondering: "<i>Can these bug classes be discovered at compilation or immediately crash at runtime?</i>"
1099 </p>
1100
1101 <p>
1102 Yes, yes they can! GCC and Clang have compilation flags to find several bug classes at compile time. Additionally, there are some runtime protections that can cause crashes to make root causing MUCH easier. This blog post is about <b>finding vulnerabilities via compiler warnings and dynamic instrumentation</b>. All of the source code snippets with extra examples can be found at <a href="https://github.com/mdulin2/integer_compilation_flags">mdulin2/integer_ compilation_flags</a>.
1103 </p>
1104
1105 <h2>
1106 Bug Classes
1107 </h2>
1108 <p>
1109 The goal is to change a number in a way that the program does not expect to cause memory corruption down the road. There are three number (but mainly integer) vulnerability classes in C that will be focused on:
1110 <ul>
1111 <li><b>Overflow/underflow</b>: Integers will simply wrap around if you go past the maximum or minimum value of the type in C. For instance, an overflow of a signed integer would go from <code>0x7FFFFFFF</code> all the way to <code>-0x80000000</code>. The underflow goes in the opposite direction and happens when subtracting values instead. </li>
1112 <li><b>Truncation</b>: Shrinking the storage capacity of a number. For instance, going from <code>uint64_t</code> to <code>uint32_t</code> would cut the storage capacity of the number in half. This has the potential to drastically change the value and signedness of the number. </li>
1113 <li><b>Signedness conversion</b>: Numbers are either signed and unsigned (<code>unsigned int</code> and <code>int</code> for example). Going between these can have terrible consequences when converting from a negative signed number to an unsigned number or a very large unsigned number to a signed number. For instance, an unsigned integer of <code>0xFFFFFFFF</code> converted to a signed integer would be -1 instead of a very large number. </li>
1114 </ul>
1115 </p>
1116
1117 <!-break-->
1118
1119 <h2>
1120 Static Analysis
1121 </h2>
1122
1123 <p>
1124 Two of these bug classes can be determined at <i>compile time</i> via specific compilation flags. Although there will likely be an exceptional amount of unexploitable occurrences of this, there are wonderful leads for finding vulnerabilities.
1125 </p>
1126
1127 <h3>
1128 Truncation
1129 </h3>
1130
1131 <p>
1132
1133 <div style="width:100%; box-sizing: border-box; display: flex; border: 1px solid black; border-radius: 10px">
1134 <div style = "flex: 45%; margin: 6px"
1135 ><img src="https://live.staticflickr.com/65535/51444718168_8df5903730_o.png" style="width:98%;" alt="Truncation Warning Source Code WConversion"><center>Figure 1 - Truncation code </center></div>
1136 <br/>
1137 <div style = "flex: 45%; margin: 6px"><img src="https://live.staticflickr.com/65535/51444476571_f84db04862_o.png" style="width:98%; border-left: 1px;" alt="Signedness conversion Warning Source Code WConversion"><center>Figure 2 - Signedness Conversion Code </center></div>
1138 </div>
1139 </p>
1140
1141 <p>
1142 Using the <code>Wconversion</code> flag during compilation will output the warning "<i>implicit conversions that may alter a value</i>". This is directly referencing <a href="https://github.com/mdulin2/integer_compilation_flags/blob/main/gcc/truncation.c">truncation</a> and <a href="https://github.com/mdulin2/integer_compilation_flags/blob/main/gcc/conversion.c">conversion</a> bugs!
1143 </p>
1144
1145 <p>
1146 For example, code for the <i>truncation </i> case can seen in <i>Figure 1</i>. This code has a type of <code>long long</code> that is being converted to an <code>int</code>. Because this changes the storage capacity from 64-bit to 32-bit, this has the potential to cause corruption. When this code is compiled with the <code>Wconversion</code> flag, a warning message will appear mentioning a truncation issue! This warning can be seen in Figure 3. This exact error message could have been used to find the <a href="https://www.qualys.com/2021/07/20/cve-2021-33909/sequoia-local-privilege-escalation-linux.txt">Linux Kernel</a> kernel bug mentioned above, when the conversion from <code>size_t</code> (unsigned long long) to <code>int</code> was performed.
1147 <br/><br/><br/>
1148 </p>
1149
1150 <p>
1151 <center>
1152 <div style="border: 1px solid black; margin: 10px; border-radius: 10px;">
1153 <img src="https://live.staticflickr.com/65535/51444209760_44eca2b1ff_h.jpg" width="95%" alt="Truncation warning message" style="border-radius: 0px;"/>
1154 <center>Figure 3 - Truncation warning message</center></div>
1155 </center>
1156 </p>
1157
1158 <p>
1159 Another interesting item to consider is the case with <code>float</code> and <code>double</code>. Since a <code>double</code> is 2x the size of a float, the same type of truncation can be detected by the same compilation flag. An example of this in code is shown <a href="https://github.com/mdulin2/integer_compilation_flags/blob/main/gcc/float_truncation.c">here</a>.
1160 </p>
1161
1162 <h3>
1163 Signedness
1164 </h3>
1165 <p>
1166 The <code>Wconversion</code> flag can also be used in the detection of <a href="https://github.com/mdulin2/integer_compilation_flags/blob/main/gcc/conversion.c">signedness conversion</a> bugs. This happens when converting from a signed to an unsigned or converting from an unsigned integer to a signed integer; both of these issues are shown in Figure 2 above. An example of the compile time error message is shown in Figure 4 below.
1167
1168 <center>
1169 <div style="border: 1px solid black; margin: 10px; border-radius: 10px;">
1170 <img src="https://live.staticflickr.com/65535/51442547757_542b8beab9_h.jpg" width="95%" alt="Signedness conversion warning message" style="border-radius: 0px;" />
1171 <center>Figure 4 - Signedness conversion warning message </center></div>
1172 </center>
1173 </p>
1174
1175 <h3>
1176 Static Analysis Wrap Up
1177 </h3>
1178 <p>
1179 These flags only check for <i>implicit</i> conversions. Sometimes, a value needs to be converted from an unsigned integer to a signed integer in order to do some math, which is valid and expected C. When a number is casted explicitly, these error messages will not show up, as a result. In order to find explicit casts, using something like CodeQL, manual review or dynamic testing is the way to go.
1180 </p>
1181
1182 <p>
1183 Although we have only been using <code>Wconversion</code> for the static analysis so far, there are a plethora of flags that actually make up this single flag. For instance, <code>Wsign-conversion</code> flag warns for implicit conversions that may change the sign of an integer value. For more information on these, visit the <a href="https://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html">GCC documentation</a>. But, the tldr; is to just use <code>Wconversion</code> to catch all of these issues at compilation time.
1184 </p>
1185
1186 <h2>
1187 Dynamic Instrumentation
1188 </h2>
1189 <p>
1190 The static analysis is likely to pull up mostly false positives with a few real bugs. However, dynamic analysis, will always find real bugs, if the code path can be triggered. Below, we will show instrumentation options to crash/notify on integer related bugs. Instead of discussing bug classes, we are going to talk about a few specific flags in GCC and Clang.
1191 </p>
1192
1193 <h3>
1194 ftrapv
1195 </h3>
1196 <p>
1197 This option generates traps for signed overflows on addition, subtraction and multiplication operations. Again, since this is dynamic testing, this will cause the program to crash whenever this occurs! An example of this code can be seen below:
1198 <pre>
1199 int main(){
1200 int a = 0x7FFFFFFF;
1201 a = a + 1;
1202 printf("Value: %d\n", a);
1203 }
1204 </pre>
1205 </p>
1206
1207 <p>
1208 The code above will cause an integer overflow when the line <code>a = a + 1;</code> is executed since the maximum size of an integer in C is 0x7FFFFFFF. What happens? The program is aborted and never reaches the print statement. By forcing the crash when the overflow occurs, we guarantee that the bug is detected and the cause of the overflow is much easier to find. This is extremely useful when fuzzing and trying to root cause a crash!
1209 </p>
1210
1211 <p>
1212 It should also be noted that this flag detects <a href="https://github.com/mdulin2/integer_compilation_flags/blob/main/gcc/underflow.c">signed integer underflows</a> as well.
1213 </p>
1214
1215 <h3>
1216 fsanitize=integer
1217 </h3>
1218 <p>
1219 The <a href="https://clang.llvm.org/docs/UndefinedBehaviorSanitizer.html">UBSAN</a> (Uninitialized Behavior Sanitizer) for finding integer bugs is amazing! This flag is specific to Clang, for the integer related bugs.
1220 </p>
1221
1222 <p>
1223 While the <code>ftrapv</code> catches only <i>signed</i> integer overflows, <code>fsanitize=integer</code> will crash on unsigned and signed integer overflows (<code>signed-integer-overflow</code> and <code>unsigned-integer-overflow</code>). This means that all integer overflows, regardless of sign, via addition, subtraction or multiplication will be caught at runtime! Damn, this is a major improvement.
1224 </p>
1225
1226 <p>
1227 Besides the discovering of overflow/underflows in programs, we can find the two other bug classes mentioned with this flag: truncation (<code>implicit-signed-integer-truncation</code> & <code>implicit-unsigned-integer-truncation</code>) and conversion (<code>implicit-integer-sign-change</code>). Unlike the <i>static</i> method above, a bad math operation must occur to trigger UBSAN to crash the program.
1228 </p>
1229
1230 <p>
1231 Let's see this in action though! We will use the original signedness issue (Figure 1). When we run the code, the <code>long long</code> with the value <code>LONG_MAX</code> ( 0x7FFFFFFFFFFFFFFF) will be cut in half (truncated) because of the conversion to an integer. As a result, this will be <code>0xFFFFFFFF</code> or -1 as a signed integer. Because of the extra instrumentation added, the program crashes upon this truncation happening! Nice for us, the instrumentation does not require a sign change; it checks that the value inside of the <code>long long</code> will not fit into the <code>int</code>. This crash can be seen in Figure 5 below.
1232 </p>
1233
1234 <p>
1235 <center>
1236 <div style="border: 1px solid black; margin: 10px; border-radius: 10px;">
1237 <img src="
1238 https://live.staticflickr.com/65535/51444688718_88c594fa3e_b.jpg" width="95%" alt="Truncation Crash Clang" style="border-radius: 0px;" />
1239 <center>Figure 5 - Truncation Conversion Crash</center></div>
1240 </center>
1241 </p>
1242
1243 <h2>
1244 Are We Missing Anything?
1245 </h2>
1246 <p>
1247 We have mentioned dynamic and static checks for integer overflows/underflows, integer truncation's and signedness conversion issues. However, there is one thing missing from the dynamic instrumentation: floating point math.
1248 </p>
1249
1250 <p>
1251 When a float is overflowed in C, it goes to <a href="https://github.com/mdulin2/integer_compilation_flags/blob/main/NaN_inf.c">infinity</a> or <code>inf</code>. Oddly enough, the float never truly wraps around because of how floating point math handles precision; it simply just goes to infinity! An example of this overflow can be seen at <a href="https://github.com/mdulin2/integer_compilation_flags/blob/main/clang/float_overflow.c">here</a>.
1252 </p>
1253
1254 <p>
1255 An additional uncaught bug is float truncation. For instance, the conversion from a <code>double</code> to a <code>float</code> is not caught at runtime. There is a misleading UBSAN flag (<code>-fsanitize=float-cast-overflow</code>) that only finds bad double/float to integer conversions but NOT truncation bugs between floating point numbers. An example of this can be seen <a href="https://github.com/mdulin2/integer_compilation_flags/blob/main/clang/float_truncation.c">here</a>.
1256 </p>
1257
1258 <p>Knowing about floats becoming <code>inf</code> and <code>NaN</code> may be useful to know since some crazy issues, such as Jack Bakers <a href="https://www.youtube.com/watch?v=4weoWSzuCxs">NaN propagation</a> bug in the Unreal Gaming Engine do happen. However, there is currently no detection on the overflowing, underflowing, truncation or <a href="https://github.com/mdulin2/integer_compilation_flags/blob/main/NaN_inf.c">NaN/Inf</a> usage of floating point numbers in C at runtime. A deep dive into the craziness of floating point math in C is out of the scope for this article but it is really interesting and worth an afternoon of learning about, as it is easy to make mistakes with.
1259 </p>
1260
1261 <h2>
1262 Conclusion
1263 </h2>
1264 <p>
1265 When trying to find vulnerabilities, any help from automated tools or instrumentation is a huge win. Besides the integer vulnerability classes mentioned above, there are loads of other interesting flags and instrumentation, such as the well known ASAN (Address Sanitizer) to help find use after free bugs or the lesser known <a href="https://docs.microsoft.com/en-us/cpp/sanitizers/error-stack-use-after-scope?view=msvc-160">use after scope</a> vulnerability on stack memory. There are many other compilation flags and instrumentation options to help find specific bugs classes as well; this article only focuses on finding integer related vulnerability classes.
1266 </p>
1267
1268 <p>
1269 I hope the knowledge of these compilation warnings and dynamic instrumentation helps you find many bugs in the future! Feel free to reach out to me (contact information is in the footer) if you have any questions or comments about this article. Cheers from <b>Maxwell "ꓘ" Dulin</b>.
1270