There’s a wave of contact form spamming going around and it hit the Comic Marktplatz, too. The main purpose of this attack is to figure out websites providing forms that can be misused to send spam, effectivly turning them into open relays. This affects not only contact forms, but also blog comments.
Shortly said, you should remove line feeds from every user entered string that becomes part of a mail’s header. These usually are
- The sender (From:)
- The subject (Subject:)
David also suggests to remove common header tokens like “to:”, “subject:”, “mime-type:” etc. from this strings. I personally think, this is a good idea. I turned David’s code into a neat function, replacing the original preg_replace with str_replace, for performance purposes:
David also suggest to do this with the message text itself, which I personally regard as not beeing necessary, since the message text usually can do no harm.
It seems the robots are systematically scanning websites for input fields to provide an email, name and message. That’s why they also try this out on comment forms. Since these forms usually also send a mail to the post author, they are also vunerable. So you better watch for updates of your blog software.
Which finally brings me to one of my favourite topics: Architecture. Regarding the Comic Marktplatz, I needed to apply the fix to exactly one place, since all mailing is done through one single class representing a mail. No need to look up every possible vulnerable form throughout the application.
Compare this - just for example and without any judging - to my blog software, Wordpress 1.2 (yes, still… upgrading takes too much time). Do a search for “@mail” in the wordpress source files and you will find several occurances, all of whom potentially are vulnerable. There are even more including the plugins.
In Wordpress 1.5, this hasn’t been quite corrected. Though there is central function called wp-mail(), it acts just as a very small wrapper around the PHP mail() function. Basically it only adds a content type and MIME version. It howevers still requires the caller to prepare a basic header including the sender (From:), which exactly is where the attack takes place. All this calling code must be identified and fixed to secure the application, which is error prone.
Morale? Code duplication is bad, centralization is good. Think before you hack. Teach this, preach this!
PS: I always wondered why PHP mail() doesn’t take the sender as a parameter - this seems weird.
Update: There’s an article on Secure PHP investigating the full story.