One thing Dave mentioned is that TFTP servers are notoriously buggy, so I thought a nice exercise would be to take a look at one and see if I could find something. I'd been playing around in IDA Pro for a while and I was about sick of it, so I was ready to knock that off and read some actual source code. I went to SourceForge and downloaded the first TFTP server I saw. Sure enough, I had a remote DoS within probably 10 minutes. It can most likely even run code, though I'm not hugely interested in proving it right now. That might make a good rainy day project.
So, rather than go through a bunch of hassle, I just posted it on the bug tracker for the project. Was that bad? I kind of thought it was a tiny bit of code that nobody's probably using, but I just checked and it's had 60,000+ downloads.
If you're interested, the bug report is here. It's pretty simple, you need to successfully TFTP GET a file with a long enough filename to overflow the log message buffer. You can do that by requesting "./" a bunch of times before the filename you want. So, basically something like:
tftp X.X.X.X PUT `perl -e'print "A"x128'`will cause the server to segfault.
tftp X.X.X.X GET `perl -e'print "./"x100'`/`perl -e'print "A"x128'`
UPDATE 4/3: Haha, oh I suck. Exploit code was posted for this bug a couple days after I made the initial bug report (http://www.offensive-security.com/0day/sourceforge-tftpd.py.txt) and
it's much simpler than I thought.
UPDATE AGAIN: Actually it looks like the code and advisories came out the week BEFORE I made the bug report. Now THAT is a weird coincidence, given that the vulnerable release of the server code has been sitting out there since June 2007. What are the odds? Anyway, original update continues...
Turns out the overflow happens well before I thought it did, and the logging function has nothing to do with it. I'm not sure what I failed to check that made me miss this. Actually, I think what I was doing was looking for a way specifically to overflow the log buffer, rather than the struct that holds the filename in the first place. I likely failed to check the simpler option of just sending a GET long filename
Specifically, the processRequest function starts by defining two variables:
char logbuff[512];The request struct looks like:
request req;
struct requestAnd part of the processRequest function includes an unsafe:
{
timeval tv;
fd_set readfds;
pthread_t threadId;
int m_socket;
BYTE sockInd;
BYTE attempt;
char path[256];
FILE *file;
char *filename;
char *mode;
char *alias;
...
strcpy(req.path, cfig.homes[0].target);So, yeah. Next time just grep for strcpy and strcat.
strcat(req.path, req.alias);