TapConfessions of an email spammer

A while ago, when this web site was really getting going, I discovered the need for a mail form to help people communicate back. At the time I was having problems with random senders being blocked and this seemed the easiest way to do it. I found what looked to be a good system in Jack’s Formmail.php v5.0!. I went through it carefully, pulled out parts which uploaded files to the server which I thought were dangerous, and used it. This has been running for a couple of years—until today.

Today I got a heap of bounced emails into an account that is not normally used much and looking at a few, it was clear that the originals had been generated by my modified script; I had signed them.

The content of a form generated email from my script is as follows, much the same as the original in fact:

 1. To: [recipient]
 2. Subject: [subject]
 3. MIME-Version: 1.0
 4. From: "[realname]" <[email]>
 5. Reply-To: [email]
 6. X-Mailer: DT Formmail5.0_RJP_2
 7. Content-Type: multipart/mixed;
 8.         boundary="----=_OuterBoundary_000"
 9. This is a multi-part message in MIME format.
10.
11. ------=_OuterBoundary_000
12. Content-Type: multipart/alternative;
13.         boundary="----=_InnerBoundery_001"
14.
15.
16. ------=_InnerBoundery_001
17. Content-Type: text/plain;
18.         charset="iso-8859-1"
19. Content-Transfer-Encoding: quoted-printable
20.
21. realname: [realname]
22. email: [email]
23. message: [message]
24.
25. Message sent by formail.php v5.0_RJP_2 from [HTTP_REFERER]
26.
27.
28. ------=_InnerBoundery_001--
29.
30. ------=_OuterBoundary_000--

Lines 1 & 2 are generated by the PHP mail() routine, lines 4 & 5 are generated by the script, lines 21-23 are obtained from the input form and the rest is pretty much fixed. I think my web host inserts Return-Path; [account email address] after line 8 and adds

Received: (from [account]@localhost)
by west-penwith.org.uk (8.12.11/8.12.11/Submit) id [id];
[datestamp]
Date: [datestamp]
Message-Id: [id]

to the front before the mail leaves home. [recipient] is fixed to my email address and coded in the script so that it can’t be harvested, [subject] is, I presume, sanitised by mail(). [email], the sender’s email address, is checked using a regexp and malformed ones rejected. [message] is not checked, but is protected by being inside a MIME type text/plain part.

Have you seen the flaw yet?

Looking at the bounced messages kindly provided by Yahoo! where they quoted the incoming message in full there were some strange additions. There was a big gap between lines 4 and 5 containing the spammy message. Also lines 21-23 were in a different order and there was a lot of additional text before line 25. This consisted of the same spammy message and a very long "bcc:" list. What they had done was inject

[bogus email address at west-penwith.org.uk]
Content-Transfer-Encoding: quoted-printable
Content-Type: text/plain
Subject: [spammy subject]
bcc: [lots of email addresses]

[Spammy content]

..

as the value for my variable [realname] and I hadn’t validated it. The insertion into the content of the message was benign, but in the header, it was taken and interpreted as written which is why all those bcc addresses were sent rubbish. As a last minute alteration, I thought it would be nice to have the mail come from a real person rather than just an email address and didn’t think of the consequences.

Verdict: Guilty as charged.

What I am curious about is a) why the mail stream wasn’t terminated by the “..” before line 5 as it is supposed to be and b) how they discovered the flaw. Unfortunately I haven’t been receiving mail from this form for a few weeks (this may be related) so I would have missed any test runs. Do they have a bot which picks up the variables used by a form and try injecting rubbish into them to see what happens, or has a human cracker been on the job?

I should point out that the flaw that was exploited was not in the original script, it was caused by an alteration I had made. The [subject] may also be vulnerable in a similar way, though it would depend on how mail() interprets it, the manual is vague on this. There are a lot of other things which even the original script doesn’t check so perhaps I should look around for a better one.

3 Responses to “Confessions of an email spammer”

References from other web pages (Pings and Trackbacks)

  1. Order of the Bath » Blog Archive » Blueyonder - Spam source

^ Top