Bug#697057: Arbitrary arguments can be passed to spfquery, bypassing SPF validation

Lekensteyn lekensteyn at gmail.com
Mon Dec 31 11:58:18 UTC 2012


Package: exim4-config
Version: 4.72-6+squeeze3
Tags: security

In setting up exim4 I have been considering to enable SPF validation. To do 
so, I had to install the following packages:

- exim4-daemon-light (default)
- spf-tools-perl

Furthermore, I edited /etc/exim4/update-exim4.conf.conf and added:

    CHECK_RCPT_SPF=1
I then ran "dpkg-reconfigure exim4-config". When finished it noted that it 
encountered the unspecified CHECK_RCPT_SPF value, but when checking 
/var/lib/exim4/config.autogenerated, the value was set.

The configuration looked suspicious, so I decided to perform some testing. 
Preparation:

    mv /usr/bin/spfquery.mail-spf-perl{,.orig}
    tee /usr/bin/spfquery.mail-spf-perl <<<EOF
    #!/bin/sh
    /usr/bin/spfquery.mail-spf-perl.orig "$@"
    retval=$?
    (IFS=:; echo "$* = $retval") >> /tmp/send-log
    exit $retval
    EOF
    chmod 755 /usr/bin/spfquery.mail-spf-perl

I performed tests in the following way:
1. nc the.server.here 25
2. Wait for banner, then send: HELO example.com
3. Wait for acknowledgement, then send: MAIL FROM: ${TEST_VALUE}
4. Wait for ackowledgement, trigger send: RCPT TO: root at localhost
5. Look at /tmp/send-log (arguments are colon-separated, ending with an equal 
sign followed by the exit code)
6. Send QUIT or Ctrl-C

The value from "MAIL FROM:" is used in the configuration as $sender_address 
(sender_address_domain is defined if $sender_address is set):

    condition = ${run{/usr/bin/spfquery.mail-spf-perl --ip \
                   \"$sender_host_address\" --identity \
                   ${if def:sender_address_domain \
                       {--scope mfrom  --identity \"$sender_address\"}\
                       {--scope helo --identity  \"$sender_helo_name\"}}}\
                   {no}{${if eq {$runrc}{1}{yes}{no}}}}

The below values have been tested following the above six steps, but with the 
${TEST_VALUE} replaced by the ones listed below:
1. Known invalid address: "$PWD"@example.com
2. Possibly bypass: " --help "ish at example.com
3. Valid address: legit at example.com

Results from a local test:
1. --ip:(snip):--identity:--scope:mfrom:--identity::$PWD"@example.com" = 255
Whatever happened, spfquery did not like it, but the recipient is accepted by 
exim. (a warning is printed)
2. --ip:(snip):--identity:--scope:mfrom:--identity::x:--help:@example.com = 0
"--help" is passed as a standalone option which makes spfquery print a help 
message and then exit with the zero status code. exim accepts this recipient 
too.
3. --ip:(snip):--identity:--scope:mfrom:--identity:legit at example.com = 1
The expected result as printed below:
550-[SPF] (snip) is not allowed to send mail from example.com.  Please see
550 
http://www.openspf.org/Why?scope=mfrom;identity=legit@example.com;ip=(snip)
The recipient is rejected by exim.

Conclusion:
Random arguments can be passed to the spfquery command as shown above. Or, 
putting it differently, SPF validation can be bypassed in exim using a 
specially crafted MAIL FROM value. Possible solutions include:
- Validate the sender, ensuring that quote characters cannot occur as this 
breaks the ${run} configuration. One has to check if this is in violation of 
SMTP (RFC5321) [1].
- Make ${run} split program arguments first and then expand variables while 
keeping the arguments order. This would require help from upstream.

${run} is only used in the Debian configuration for this SPF check which is 
disabled in a default Debian installation. For now I keep SPF disabled as this 
configuration is broken and may have other security implications.

 [1]: http://www.rfc-editor.org/rfc/rfc5321.txt



More information about the Pkg-exim4-maintainers mailing list