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