* exploit for pavuk web spider - infamous42md AT hotpop DOT com
* shouts to mitakeet, skullandcircle, and thanks to matt murphy for making me
* realize a n00bish mistake i made.
* this exploit probably deserves a bit of an explanation as it was not exactly
* straight forward. the vulnerable code looks like this, with some comments
* inlined by me:
char *http_get_digest_auth_str(auth_digest, method, user, pass, urlp, buf)
/* this is the buffer we bitch slap */
char *d = url_encode_str(urlp->p.http.document, URL_PATH_UNSAFE);
/* this turns into a 32 byte string */
a2 = _md5(pom);
* this is the point that we overflow the buffer. we control
* auth_digest->nonce, and that is where all of our evil code go. but crap,
* look, the string a2 gets appended to the nonce buffer, that means
* whatever lives above the saved EIP we overwrite is going to get fuxxored
* to. that means the arguments to the function get trashed, usually not a
* problem, but look below at the following sprintf(). those variables get
* used again, so we have to restore them to a sane state.
sprintf(pom, "%s:%s:%s", a1, auth_digest->nonce, a2);
a3 = _md5(pom);
/* more crap, we need to repair nearly all of the parameters */
strcat(buf, ", opaque=\"");
* so u can see we can't just overflow and go. we need to recreate at least
* the auth_digest pointer, the user pointer, and the buf pointer. so, the
* strategy is as follows:
* + overwrite auth_digest to point into the buffer we control
* + where we point auth_digest must also contain valid pointers as they are
* used as the strings that get printed into buffer.
* + so we point those pointers towards the very end of our buffer. the
* strings they point to should not be so long. our buffer is NULL termed so if
* they point towards the end of it, we know they'll end at a set point.
* + we set the user pointer to the same place as the auth_digest pointer.
* + we set buf to point past the end of our buffer, at some higher address.
* that is where all the other strings get printed to in sprintf() and
* + and that's about it. so our buffer looks like this:
* ALIGN NOPS SHELL STRING_PTRS RETADDR USER_AND_DIGEST_PTRS BUF_PTRS
* |----------------------------^ |------^
* the only arg you pass is the base address of the buffer that we overwrite,
* which lays somewhere on the stack. note this is not the location of our
* original buffer, but the location of the pom variable from above func. and
* you need to be root as we bind to port 80 and pretend to be a webserver.
* [firstname.lastname@example.org] ./ps
* Usage: ./ps <base of nonce buffer>
* [email@example.com] ./ps 0xbfffdb34
* got a shell
* uid=1000(n00b) gid=100(users) groups=100(users)