siim / ftp Goto Github PK
View Code? Open in Web Editor NEWLightweight FTP server written in C
License: BSD 3-Clause "New" or "Revised" License
Lightweight FTP server written in C
License: BSD 3-Clause "New" or "Revised" License
Bug report: Buffer Over-read
Revision: 31b66c3
A buffer over-read can be caused by sending a message with 1024 or more characters.
The buffer over-read is seen on the client side. On my system, it prints a superfluous "220 A very warm welcome!" message, and stops at that message's null character.
From a glance at the code, this seems to come from server.c:41:
while (bytes_read = read(connection,buffer,BSIZE)){
and line 47:
printf("User %s sent command: %s\n",(state->username==0)?"unknown":state->username,buffer);
buffer
is initially filled with \0
characters, so the printf works, unless you completely fill the buffer. In that case, there is no null terminator and the printf over-reads buffer
.
Example:
$ nc 10.202.13.142 8021
220 A very warm welcome!
USER CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCABC
530 Invalid username
500 Unknown command
Output on server:
User unknown sent command: USER CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC220 A very warm welcome!
User unknown sent command: ABC
Results may vary on other systems. It is not known with certainty what, if any, security threat this bug may pose.
This bug was found with the help of the Sulley Fuzzing Framework: https://github.com/OpenRCE/sulley.
I'm learning ftp protocol
find some bugs and just make a mark
don't mind ^ ^
result size 大小没控制好造成stackoverflow
void ftp_pwd(Command *cmd, State *state)
{
if(state->logged_in){
char cwd[BSIZE];//size 1024
char result[BSIZE];//size 1024
memset(result, 0, BSIZE);
if(getcwd(cwd,BSIZE)!=NULL){
strcat(result,"257 \"");//size 5
strcat(result,cwd); // maybe size 1024
strcat(result,"\"\n");//size 2
//result size max == 5 + 1024 +2
state->message = result;
}else{
state->message = "550 Failed to get pwd.\n";
}
write_state(state);
}
same problem as ftp_pwd
strcat stack overflow
if(mkdir(cmd->arg,S_IRWXU)==0){
strcat(res,"257 \"");
strcat(res,cmd->arg);
strcat(res,"\" new directory created.\n");
state->message = res;
sprintf use %s can also cause stack overflow when len(cwd)+len(cmd->arg)>1024
sprintf(res,"257 \"%s/%s\" new directory created.\n",cwd,cmd->arg);
Chay Strawbridge wrote:
Hi,
Your embeddable ftp client is jolly useful. I have a quick fix which allows it to work on big-endian platforms (at the moment it cannot accept a pasv connection on these).
In ftpserver.c, change the function getip() from this:
void getip(int sock, int *ip)
{
socklen_t addr_size = sizeof(struct sockaddr_in);
struct sockaddr_in addr;
getsockname(sock, (struct sockaddr *)&addr, &addr_size);
int host,i;
host = htonl(addr.sin_addr.s_addr);
for(i=0; i<4; i++){
ip[i] = (host>>i*8)&0xff;
}
}
To this:
void getip(int sock, int *ip)
{
socklen_t addr_size = sizeof(struct sockaddr_in);
struct sockaddr_in addr;
getsockname(sock, (struct sockaddr *)&addr, &addr_size);
char* host = inet_ntoa(addr.sin_addr);
sscanf(host,"%d.%d.%d.%d",&ip[0],&ip[1],&ip[2],&ip[3]);
}
//
Also, since sendfile() is often not available, a working implementation of that function is here:
#ifndef sendfile
#define BUF_SIZE 8192
ssize_t sendfile(int out_fd, int in_fd, off_t * offset, size_t count )
{
off_t orig;
char buf[BUF_SIZE];
size_t toRead, numRead, numSent, totSent;
if (offset != NULL) {
/* Save current file offset and set offset to value in '*offset' */
orig = lseek(in_fd, 0, SEEK_CUR);
if (orig == -1)
return -1;
if (lseek(in_fd, *offset, SEEK_SET) == -1)
return -1;
}
totSent = 0;
while (count > 0) {
toRead = count<BUF_SIZE ? count : BUF_SIZE;
numRead = read(in_fd, buf, toRead);
if (numRead == -1)
return -1;
if (numRead == 0)
break; /* EOF */
numSent = write(out_fd, buf, numRead);
if (numSent == -1)
return -1;
if (numSent == 0) { /* Should never happen */
perror("sendfile: write() transferred 0 bytes");
exit(-1);
}
count -= numSent;
totSent += numSent;
}
if (offset != NULL) {
/* Return updated file offset in '*offset', and reset the file offset
to the value it had when we were called. */
*offset = lseek(in_fd, 0, SEEK_CUR);
if (*offset == -1)
return -1;
if (lseek(in_fd, orig, SEEK_SET) == -1)
return -1;
}
return totSent;
}
#endif
All the best,
@mrchay
There is a small bug in server.c:173
void ftp_mkd(Command *cmd, State *state)
{
char res[2*BSIZE+32];
...
state->message = res;
...
state->message = "550 Failed to create directory. Check path or permissions.\r\n"; // local address
...
write_state(state);
}
void write_state(State *state)
{
write(state->connection, state->message, strlen(state->message)); // bug location: read previous local address
}
Reproduce
USER anonymous
PASS anonymous
MKD <filename> // filename should not be existed.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.