HFS is "an HTTP File Server that can be to send and receive files". A directory traversal vulnerability in HFS allows remote attackers to upload files to locations that reside outside the bounding HTTP root directory.
Vulnerable Systems:
* HTTP File Server (HFS) version 2.2a and prior
* HTTP File Server (HFS) version 2.3beta and prior
Immune Systems:
* HTTP File Server (HFS) version 2.2b #150
* HTTP File Server (HFS) version 2.3 beta #160
HFS allows the uploading of files to the real folders added to the Virtual File System. The problem is that an attacker can upload files outside the destination folder reaching the root or any other directory on the disk in which is located the upload folder using the ../ pattern.
Note that uploading must be enabled on the target folder, that the attacker must have access to it (is possible to restrict the access to that folder to a specific account) and that is not possible to overwrite existing files because the server avoids it (for example if a file called file.txt already exists the new one will be called file(1).txt).
mydownlib
by Luigi Auriemma
e-mail: aluigi@autistici.org
web: aluigi.org
Copyright 2006,2007 Luigi Auriemma
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#define VISDELAY 500
#define BUFFSZ 4096
#define MAXARGS 8 // modify it if you need more args in mydown_scanhead
#define MAXDNS 32
#define TEMPOZ(x) TEMPOZ1; \
x = TEMPOZ2
int dns_db_max = 0,
dns_db_add = 0;
dns_db_t dns_db[MAXDNS];
void mydown_get_host(uint8_t *url, uint8_t **hostx, uint16_t *portx, uint8_t **urix, uint8_t **userx, uint8_t **passx, int verbose);
uint8_t *mydown_http_delimit(uint8_t *data);
uint8_t *mydown_uri2hex(uint8_t *uri);
uint8_t *mydown_hex2uri(uint8_t *uri);
void mydown_scanhead(uint8_t *data, int datalen, ...);
uint8_t *mydown_http_skip(uint8_t *buff, int len, int *needed, int *remain);
void mydown_free(uint8_t **buff);
int mydown_chunked_skip(uint8_t *buff, int chunkedsize);
int mydown_unzip(z_stream z, uint8_t *in, int inlen, uint8_t **outx, int *outxlen);
int mydown_sscanf_hex(uint8_t *data, int datalen);
int mydown_timeout(int sock, int secs);
int mydown_recv(int sd, uint8_t *data, int len, int timeout);
uint8_t *mydown_showhttp80(uint16_t port);
void mydown_showstatus(uint32_t fsize, uint32_t ret, int timediff, int verbose);
uint8_t *mydown_base64_encode(uint8_t *data, int *length);
in_addr_t mydown_resolv(char *host);
if(filename) { // last useless check to avoid directory traversal
s = strrchr(filename, ':');
if(s) filename = s + 1;
s = strrchr(filename, '\\');
if(s) filename = s + 1;
s = strrchr(filename, '/');
if(s) filename = s + 1;
s = strrchr(filename, '.'); // automatic gzip decompression on the fly
if(s && !stricmp(s, ".gz")) {
if(onflyunzip) {
httpgzip = 1;
*s = 0;
}
}
}
}
if(!filename || !filename[0]) {
if(verbose >= 0) fprintf(stderr, "\nError: no filename retrieved, you must specify an output filename\n\n");
if(filesize) *filesize = MYDOWN_ERROR;
GOTOQUIT;
}
if(chunkedlen < chunkedsize) { // we have more data than how much we need
memcpy(chunkedbuff, buff, chunkedlen);
chunkedsize -= chunkedlen;
memmove(buff, buff + chunkedlen, chunkedsize);
} else { // we have only part of the needed data
memcpy(chunkedbuff, buff, chunkedsize);
for(len = chunkedsize; len < chunkedlen; len += t) {
t = mydown_recv(sd, chunkedbuff + len, chunkedlen - len, timeout);
if(t <= 0) GOTOQUIT;
}
chunkedsize = 0;
}
chunkedtmp = buff;
buff = chunkedbuff;
len = chunkedlen;
}
/* DECOMPRESSION */
if(httpz) {
if(httpgzip && !ret) { // gzip is really stupid...
t = len;
s = buff;
if((httpgzip == 1) && !httpskipbytes) httpskipbytes = 3;
/* UPDATE THE AMOUNT OF UNCOMPRESSED BYTES DOWNLOADED */
// ret is the total size of the data we have downloaded (uncompressed)
// httpret is the total size of the data we have downloaded from the server
// len is the size of the current block of data we have downloaded (uncompressed)
ret += len;
/* WRITE THE DATA INTO FILE OR MEMORY */
if(filedata) {
if(filedatasz < ret) {
filedatasz = ret;
filedatatmp = realloc(filedatatmp, filedatasz);
if(!filedatatmp) GOTOQUIT;
}
memcpy(filedatatmp + ret - len, buff, len);
} else if(fd) {
if(fwrite(buff, 1, len, fd) != len) {
fprintf(stderr, "\nError: I/O error. Probably your disk is full or the file is write protected\n");
GOTOQUIT;
}
fflush(fd);
}
mydownlib
by Luigi Auriemma
e-mail: aluigi@autistici.org
web: aluigi.org
Copyright 2006,2007 Luigi Auriemma
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
typedef struct {
uint32_t from; // download from byte, use -1 for the latest tot bytes
uint32_t tot; // download tot bytes
int showhead; // show the http header and stop (1 = yes, 0 = no)
int resume; // resume a download (1 = yes, 0 = no)
int onlyifdiff; // download only if differs from local file (1 = yes, 0 = no)
uint8_t *user; // username for authentication
uint8_t *pass; // password for authentication
uint8_t *referer; // referer string
uint8_t *useragent; // user-agent string
uint8_t *cookie; // cookie string
uint8_t *more_http; // additional http parameters
int verbose; // verbosity (-1 = quiet, 0 = normal, 1 = verbose)
uint8_t **filedata; // use it if you want to store the downloaded file in memory
int *keep_alive; // keep-alive socket
int timeout; // seconds of timeout
int *ret_code; // HTTP code from the server
int onflyunzip; // unpack the file on the fly if possible (usually gzipped)
uint8_t *content; // data to post
int contentsize; // optional size of content (default is auto)
uint8_t *get; // the type of request, like GET or POST or HEAD or anything else
} mydown_options;
uint32_t mydown( // ret: file size
uint8_t *myurl, // the URL
// can be like http://aluigi.org/mytoolz/mydown.zip
// or http://user:pass@host:port/blabla/blabla.php?file=1
uint8_t *filename, // NULL for automatic filename or forced like "test.txt"
mydown_options *opt // the above structure for your options
);
uint32_t mydown_http2file( // ret: file size
int *sock, // socket for keep-alive
int timeout, // seconds of timeout
uint8_t *host, // hostname or IP
uint16_t port, // port
uint8_t *user, // username
uint8_t *pass, // password
uint8_t *referer, // Referer
uint8_t *useragent, // User-Agent
uint8_t *cookie, // Cookie
uint8_t *more_http, // additional http parameters (ex: mycookie: blabla\r\npar: val\r\n)
int verbose, // verbose
uint8_t *getstr, // URI
FILE *fd, // file descriptor
uint8_t *filename, // force filename
int showhead, // show headers
int onlyifdiff, // download only if differs from local file
int resume, // resume
uint32_t from, // download from byte
uint32_t tot, // download tot bytes
uint32_t *filesize, // for storing file size
uint8_t **filedata, // use it if you want to store the downloaded file in memory
int *ret_code, // HTTP code from the server
int onflyunzip, // on fly decompression
uint8_t *content, // data to post
int contentsize, // optional size of content (default is auto)
uint8_t *get // request
);
myhttpup.c:
/*
Copyright 2007 Luigi Auriemma
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
do {
seed = (time(NULL) * 0x343FD) + 0x269EC3;
} while(seed < 0xffff); // in reality MIME uses a 64 bit value
sprintf(tmp, UPLOAD0, seed); // but this is enough