OK, that's a pretty inflammatory title, and you might think that since
my program POPFile is both
Bayesian and gets used for spam fighting that I am crazy to publish a
paper about how to get around a spam filter.
Or perhaps you just think I'm evil.
But it's essential that everyone thinks about not only how their spam
filter works, but how it might be broken.
Here I describe a technique using email messages and web bugs that can
be used to test for the presence of a spam filter and then examine its
properties to see what types of spam are likely to get through.
The Problem (for a spammer)
Some antispam technologies (such as Spam Assassin) make it
easy for a spammer to determine whether their message is going to be
caught: they just run it through the program themselves (in Spam Assassin's
case they also publish a nice list of how they catch spam on their web
site which could be read as a HOWTO on what not to put in a spam message).
There are even companies like XXX that offer a service to people who want
to send out mail and get it past spam filters. They'll check the message
But Bayesian filters present a problem for the spammer... they are not
one-size-fits-all programs that anyone can run. They are tailored by each
individual and they learn as spam is received.
So the spammer is left with no defense against the spam filter, which is
why Bayesian filters are both popular and successful. They catch spam and
they make it hard for a spammer to figure out how to get their message to
They key question a spammer wants to know the answer to is "did my
message get through?" Luckily the use of HTML in email and the automatic
display of HTML gives them a way to answer that question.
Currently web bugs are used to validate your email address. They help a
spammer know which email addresses work and which should be junked, and they
work even though the spammer has forged the return address on the email.
A web bug is a tiny (often invisible) image that is part of the spam messages
that you receive. In HTML it could look something like this:
The email program will go to www.spammer-controlled-site.com and request
the image called webbug.cgi?email=ABCDEF. The site responds with a tiny
image (often white with 1 pixel by 1 pixel) but also makes a note of the email address
(your real email address would replace ABCDEF in the example). The instant
that you look at the spam, the spammer knows that your email address is valid and
boom you get more spam.
Web Bugs Can Track Filter Hopping
It's pretty easy to see that once a web bug fires the spammer can use it to pass
back any information that they want. One possibility would be to give every
spam they send out a unique number and have a web bug like this:
The ABCDEF is the email address of the recipient and the 12345 the
unique number of this specific message. When the spam is loaded the spammer can track
which people received exactlt which messages.
So you can imagine a process where a spammer sends a message to a specific recipient
and then tracks the firing of the web bug to see whether the spam passed through the
recipient's spam filter.
That process could even look like a long runnnig function call. Imagine that such
a function exists, call it filter-test, it might be defined like this:
bool filter-test( EMAIL_ADDRESS to, EMAIL_ID number )
A spammer would call filter-test with an email address to send the
message to, and the unique number of the message. filter-test would
send the message to the recipient with the specially designed web bug inside it, wait
for a response (with a timeout) and then return true if the message passed through
In pseudocode filter-test looks like this:
bool filter-test( EMAIL_ADDRESS to, EMAIL_ID number )
Retrieve the unique email with id number
Add the web bug
Send the email with recipient 'to'
Wait for the web bug to fire
If it fires then return true
If after some timeout period it does not fire return false
So now the spammer can use filter-test to send a sequence of emails and get back
yes/no responses that give a fuzzy idea of what happened. A yes means that the message
got through, a no means that perhaps it didn't get through, or perhaps the user is on
vacation, or perhaps the user is behind a firewall.
Fortunately, there are good machine learning algorithms for dealing with fuzzy information
and trying to make decisions from them. One search algorithm is, well, Bayes rule.
Bayes fights Bayes
What the spammer needs is a way of telling whether a message is likely to get past your
individual spam filter. What the user of a Bayesian filter has is an adaptive mechansim
for assigning a likelihood that a message is spam.
So what a spammer really needs is a Bayesian filter that is trained based on an individual
end user's acceptance or non-acceptance of various spam messages. With such a program the
spammer could test new spam messages to see whether they are likely to get through.
To make this work the spammer sets up a Bayesian learning system like POPFile with go
and no go categories. Messages are placed in go if they were received by
the end user and in no go if they were not. Using filter-test and a handful
of sample mails the spammer can automatically build the corpus for go and no go
and keep it up dated over time.
As new spam campaigns are created the spammer uses the Bayesian system by asking it how it would
classify the new message they are about to send. If it looks like a go then it gets sent,
if a no go then the message is tweaked (perhaps automatically) until it's a go.
As the campaign progresses the spammer can use feedback from filter-test on the campaign
mails to further refine the corpus.
Stopping the Arms Race
There's a simple solution to stopping this Bayes vs. Bayes arms race, it's essential to cut
spammers out of the feedback loop. Doing that means stopping web bugs, never replying to
spammers' mails and never bouncing spams.
If spammers cannot get feedback on whether their mails are being read, they can't refine
their message and Bayesian spam filters will remain successful. Practically speaking, that
means you should not bounce spams, and you should not reply to, or click on unsubscribe links. You should also
disable the loading of images by your email client (or even disable HTML email altogether).