Phishnet is a first implementation of an anti-phishing milter written
in Python.  It operated as a sendmail/postfix mail filter ("milter")
process studying outbound e-mail from your institution to the Internet
at large, and rejecting messages that appear to contain a user's

Phishnet was developed in the fall of 2008 and considered both a useful
tool and a good approach to the phishing problem, but concerns were
raised that on deploying an outbound mail filter, Information Technology
staff would no longer be able to claim that we do not censor e-mail.
Support for the project bottomed out.

Phishnet is still a functionally complete tool though, and I want to get
this out of my closet, so I'm touching it up for presentation.



    This is the milter program itself.  It depends on the Python Milter
    toolkit: http://www.bmsi.com/python/milter.html


    The data directory is for holding credential databases -- the
    database of hashed username-password pairs that we wish to block.
    All usernames and all passwords are stored as md5 hashes.  Phishnet
    works by tokenizing mail, md5-hashing the tokens into (username,
    password) tuples, and checking whether a message contains any such


    This is the configuration file for the milter.  Its comments tell
    you how to configure it.


    phishnet.py contains the core text-processing engine and credential
    database manager.  It also provides simple tools for testing the
    engine and for building the hashed credential databases from
    plaintext source.

    qconfig.py is a wrapper around Python's getopt and ConfigParser
    classes to combine their behaviors.


    Sample e-mail designed to pass or fail the milter's test using the
    supplied example credential database.

Data files

A data file should consist of one or more lines like this:
hash: hash

or like this:
hash: hash,hash[...]

The first hash on a line is a hash of a valid user name that we wish
the scanner to search for.  All other hashes on a line are passwords
for that user.  If both the user name and a password are found, the
message triggers a response in the milter.

The current library code supports only md5 hashes with hex encoding.

To produce a credential database, run phishnet.py:

    unix$ lib/phishnet.py convert data/example.in

This produces data/example as output.

In enterprise-scale production you would probably not want to export
plaintext passwords for phishnet.py to process (if you're even able
to).  Rather, you would want your institutional authentication systems
to export to you a prepared file containing all the appropriate hash
pairs.  You do not want real credentials to reside in cleartext on the
mail server, at any rate.


Phishnet's "philter" program searches for its configuration file in
/etc/mail/philter.cfg, {prefix}/etc/philter.cfg, and the current
directory. "{prefix}" represents an installation prefix which also
contains bin/philter.

You can specify an alternate configuration file with the -f option.

You can name the milter socket with the -S option, or declare it in the
configuration file.  Philter will create this socket, and sendmail or
postfix should be told where to find it.


Philter logs extensively; see the configuration file.  It also tracks
its performance in great detail, and reports performance figures in the
log file(s).


To test the engine:

1. Build the example creddb.

   $ rm data/example
   $ lib/phishnet.py convert data/example.in
   $ ls data/example

2. Run the tests.

   $ lib/phishnet.py continuous data/example tests/