The 'Security Digest' Archives (TM)

Archive: About | Browse | Search | Contributions | Feedback
Site: Help | Index | Search | Contact | Notices | Changes

ARCHIVE: 'Phage List' - Archives (1988 - 1989)
DOCUMENT: phage #267 [Re: ok, how about another sendmail hole?] (1 message, 2362 bytes)
SOURCE: http://securitydigest.org/exec/display?f=phage/archive/267.txt&t=text/plain
NOTICE: securitydigest.org recognises the rights of all third-party works.

START OF DOCUMENT

From: Lovstrand.EuroPARC@xerox.com
To: phage
Date: Fri 11:39:24 18/11/1988 EST
Subject: Re: ok, how about another sendmail hole?
References: [Thread Prev: 259] [Thread Next: 260] [Message Prev: 266] [Message Next: 269]

I'm not on the phags mailinglist, but John Larson at PARC forwarded your
message to me.

> So I'm wondering if one could construct a To: address with stuff like
> ^V, ^W, ^X embedded so that sendmail ends up passing it to the "program"
> mailer, say.  It may be that the normal test for program-mailer use
> during an SMTP session would block this from making any headway.

Yup, you're quite right.  Or, more precisely, you are quite right in that
the possibility exists but your mileage may vary since the success of such
an operation will be heavily dependent on the recipients site's
configuration file.  If (1) their sendmail.cf file is written in such a way
that an address with ^VPROG in it has a chance of fooling ruleset 0, and
(2) you know exactly how to compose that address, then (3) you have a
chance of becoming famous as Morris II (sorry).  What you want to look out
for is code in ruleset 0 that doesn't have a constant string after the $#
operator or some way for an address to pass through S0 without being caught
by a rule that sends it to an explicit mailer.    Even then it may not be
possible depending on the rest of the sendmail.cf file.  On the other hand,
if ruleset 0 has lines like:
	Rxxx		$#FOO_MAILER $@ yyy $: zzz
and ends with:
	R$*		$#ERROR $: Unparsable address: $1
it's probably safe.

The removal of the tTd(0, 1) code in recipient.c won't help in this case
since it is only used to determine whether an address previously resolved
to the LOCAL mailer now should be changed to the PROG mailer (because it
starts with a '|').  An address resolving directly to the PROG mailer would
never be passed through this test, and so would not be affected by the
normal security constraints.

Just blindly stopping prescan() to accept control characters won't cut the
ice, since it is used internally to scan the rule lines in the .cf file
(and in which case there will be lots of legitimate ^Vs, ^Ws, &c).
Hopefully, the patch enclosed below will do the trick though.  It will
allow control chars to be scanned if and only if it is called from readcf()
-- at all other instances they are stripped from the address.  Unless
someone can show me a case where it fails or suggest a better alternative,
I will include it in the next revision of the IDA Kit for those who use
that.

--Lennart <Lovstrand.EuroPARC@Xerox.COM>
Rank Xerox EuroPARC, 61 Regent Street, Cambridge, CB2 1AB, England

(context diff based on vanilla sendmail 5.59)

*** readcf.c.orig	Sat Apr  2 01:51:11 1988
--- readcf.c	Fri Nov 18 14:42:59 1988
***************
*** 73,78 ****
--- 73,79 ----
  	char pvpbuf[PSBUFSIZE];
  	extern char *fgetfolded();
  	extern char *munchstring();
+ 	extern bool AllowControls;
 
  	cf = fopen(cfname, "r");
  	if (cf == NULL)
***************
*** 132,137 ****
--- 133,142 ----
  			}
  			rwp->r_next = NULL;
 
+ 			/* the ruleset operators will be translated to control
+ 			   characters -- tell prescan() that they're OK */
+ 			AllowControls = TRUE;
+
  			/* expand and save the LHS */
  			*p = '\0';
  			expand(&buf[1], exbuf, &exbuf[sizeof exbuf], CurEnv);
***************
*** 150,155 ****
--- 155,163 ----
  			rwp->r_rhs = prescan(exbuf, '\t', pvpbuf);
  			if (rwp->r_rhs != NULL)
  				rwp->r_rhs = copyplist(rwp->r_rhs, TRUE);
+
+ 			/* end of fun */
+ 			AllowControls = FALSE;
  			break;
 
  		  case 'S':		/* select rewriting set */

*** parseaddr.c.orig	Mon Mar 14 05:31:53 1988
--- parseaddr.c	Fri Nov 18 14:43:14 1988
***************
*** 248,253 ****
--- 248,255 ----
  # define NOCHAR		-1	/* signal nothing in lookahead token */
 
  char	*DelimChar;		/* set to point to the delimiter */
+ bool	AllowControls = FALSE;	/* cntrl chars represent ruleset operators
and
+ 				   are only accepted when called from readcf */
 
  char **
  prescan(addr, delim, pvpbuf)
***************
*** 322,328 ****
 
  			/* chew up special characters */
  			*q = '\0';
! 			if (bslashmode)
  			{
  				/* kludge \! for naive users */
  				if (c != '!')
--- 324,338 ----
 
  			/* chew up special characters */
  			*q = '\0';
! 			if (!AllowControls && iscntrl(c) && !isspace(c))
! 			{
! 				/* control chars aren't allowed, but
! 				   signalling an error at this stage
! 				   seems to cause much more pain than
! 				   just silently eating them */
! 				c = NOCHAR;
! 			}
! 			else if (bslashmode)
  			{
  				/* kludge \! for naive users */
  				if (c != '!')

END OF DOCUMENT