The Cult of a Cardinal Number
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
- ------------------------------------
The Cult of a Cardinal Number (Equal to the Sum of 1+1)
by Phantasmal Phantasmagoria
phantasmal@xxxxxxx
- ---- Table of Contents -------------
1 - Introduction
2 - Technical Details
3 - Final Thoughts
- ---- Introduction ------------------
On September 23 the ISS X-Force team released details of a flaw regarding
the handling of ASCII file translations in the ProFTPD server. The code
in question was rapidly patched by the ProFTPD team. However, a small
and more subtle overflow was left unnoticed, an off-by-one condition.
On closer analysis it was found that the patch created to fix the original
ISS flaw introduced yet another off-by-one overflow, effectively allowing
two bytes to overflow past the end of an internal buffer.
Exploitation of this vulnerabilty could lead to remote privilege escalation
to the root user. Both holes were fixed in a clean up of the problematic
code in version 1.2.9rc3.
Affected versions:
1.2.7/1.2.7p
1.2.8/1.2.8p
1.2.9rc1/1.2.9rc1p
1.2.9rc2/1.2.9rc2p
Unaffected versions:
1.2.9rc3
1.2.9
- ------------------------------------
- ---- Technical Details -------------
As in the case of the ISS bug this issue resides in the _xlate_ascii_write()
function, used to insert a preceeding CR for every LF. It can be triggered
by the RETR ftp command.
static void _xlate_ascii_write(char **buf, unsigned int *buflen,
unsigned int bufsize) {
char *tmpbuf = *buf;
unsigned int tmplen = *buflen;
unsigned int lfcount = 0;
unsigned int added = 0;
int res = 0;
register unsigned int i = 0;
if (tmpbuf[0] == '\n')
lfcount++;
..
if ((res = (bufsize - tmplen - lfcount)) <= 0) { /* [A] */
pool *copy_pool = make_sub_pool(session.xfer.p);
char *copy_buf - pcalloc(copy_pool, tmplen);
memmove(copy_buf, tmpbuf, tmplen);
session.xfer.bufsize = tmplen + lfcount; /* [B] */
session.xfer.buf = pcalloc(session.xfer.p,session.xfer.bufsize);
session.xfer.buf++; /* [C] */
session.xfer.bufstart = session.xfer.buf;
memmove(session.xfer.buf, copy_buf, tmplen); /* [D] */
destroy_pool(copy_pool);
tmpbuf = session.xfer.buf;
bufsize = session.xfer.bufsize;
}
if (tmpbuf[0] == '\n') {
memmove(&(tmpbuf[1]), &tmpbuf[0], bufsize); /* [E] */
tmpbuf[0] = '\r';
added++;
lfcount--;
}
..
tmpbuf[tmplen+added] = '\0'; /* [F] */
*buf = tmpbuf;
*buflen = tmplen + added;
}
These flaws are made possible at a number of stages. Firstly, we need
to get into the if statement at [A]. This is easy enough to do. The variable
bufsize is the actual size of the buffer we are attacking, which when
using the RETR command is 1024. For the sake of the overflows, we want
to get 'res' to exactly 0. There are a number of possible combinations
to do this, the simplest of which is passing a 1023 byte long buffer
containing a single LF in the first character to the _xlate_ascii_write()
function.
Knowing that we can trigger the if statement we can shift our attention
to session.xfer.buf, the buffer we will be overflowing. The first important
mistake occurs when session.xfer.bufsize is set to 1024 at [B], where
it should actually be 1025 (1023 + CR + NULL). This is followed by the
crux of the overflows at [C]. It is entirely unnessecary to increase
session.xfer.buf here. It essentialy reduces the amount of valid space
in the buffer to 1023. The final significant event leading to the overflows
is at [D], where 1023 bytes of our buffer (including the starting LF)
is moved to session.xfer.buf. Due to the slip-up at [C], we lose our
NULL terminating byte; our buffer is exactly contiguous to the end of
valid space.
The first off-by-one overflow occurs at [E]. The last character of our
1023 byte long argument to _xlate_ascii_write() is moved past the boundary
of allocated space for session.xfer.buf to make room for the preceeding
CR to our LF. We can control this value. We can't, however, control the
next off-by-one at [F]. Due to [C], the line at [F] should be setting
tmpbuf[1022] to NULL. The value at tmpbuf[1023] is what we just oveflowed.
Instead, tmpbuf[1023 + 1] gets set to NULL. Perhaps it would be more
accurate to call this an off-by-two, but as the overflow at [F] existed
even before the ISS bug was patched that would only introduce confusion.
- ------------------------------------
- ---- Final thoughts ----------------
It is difficult, if not impossible, to please every group of the security
community when releasing information pertaining to a vulnerability. Some
will say that I should of contacted the vendor, some will say I should
of kept the bug to myself, some will say I should of released exploit
code. I can only offer one account; The Cult of a Cardinal Number has
finished. It was found, exploited, and patched. And it has finished.
Some might label me - black hat, white hat. But quite honestly, there
is no such thing as 'hats'. There are those who can hack and there are
those who can't, regardless of what type of disclosure they choose, or
where they like to discuss security, or even what they use for a name.
To those in favour of full-disclosure, everything you need to know in
order to form a successful exploit is out there. I refuse to aid and
abet technically inept members on any side of the digital security divide
who are not willing and eager to learn. Programming does not make you
a hacker, breaking in to a computer does not make you a hacker. Learning
and thinking creatively, that's what it's really about. That's what makes
you a hacker.
- ------------------------------------
-----BEGIN PGP SIGNATURE-----
Note: This signature can be verified at https://www.hushtools.com/verify
Version: Hush 2.3
wkYEARECAAYFAkBDdjIACgkQImcz/hfgxg201wCfTBWOL+XcuC+UeDMqW41HWsJHEwEA
n0ml1AZLGfwwurjb1xsyvOdna2fW
=OIQH
-----END PGP SIGNATURE-----
Concerned about your privacy? Follow this link to get
FREE encrypted email: https://www.hushmail.com/?l=2
Free, ultra-private instant messaging with Hush Messenger
https://www.hushmail.com/services.php?subloc=messenger&l=434
Promote security and make money with the Hushmail Affiliate Program:
https://www.hushmail.com/about.php?subloc=affiliate&l=427