spam killing with poplib

Discussion in 'Python' started by Simon Burton, Sep 20, 2003.

  1. Simon Burton

    Simon Burton Guest

    This was so easy :)

    Simon Burton.


    #!/usr/bin/env python

    import sys
    from time import sleep
    from poplib import *

    canit = """Newest Internet Critical Pack
    New Internet Upgrade
    Message: User unknown
    Last Net Critical Patch
    last pack
    error notice
    Failure Advice
    failure message
    Bug Message
    Newest Internet Critical Pack
    Advice
    last net security pack
    Latest Microsoft Security Upgrade
    Latest Upgrade
    Last Network Critical Update
    Current Net Security Pack
    new net pack
    Last Network Security Pack
    Security Pack
    Security Update
    Critical Upgrade
    Undelivered Message
    Security Upgrade
    Net Update
    security pack
    Bug Letter
    Network Pack
    New Net Update
    """.split("\n")[:-1]
    #print canit
    #sys.exit(0)


    def doit():
    mbox = POP3( "pop.webone.com.au" )

    mbox.user( "XXX" )
    mbox.pass_( "XXX" )

    stat = mbox.stat()
    print "stat",stat

    ilist = mbox.list()
    olist = []
    for info in ilist[1]:
    info = str.split( info )
    i, sz = int(info[0]), int(info[1])
    spam = 0
    print "msg #%.3d\t%d"%( i, sz )
    header = mbox.top( i, 0 )[1]
    subject = ""
    sender = ""
    for line in header:
    #print "\t",line
    if line.startswith( "From:" ):
    sender = line
    if line.startswith( "Subject:" ):
    subject = line
    if line.startswith( "SUBJECT:" ):
    subject = line
    if line.startswith( "X-Spam-Level" ):
    spam = line.count( "*" )
    if subject:
    print " "+subject
    if sender:
    print " ", sender
    print " spam", spam
    sz_chk = 140000<sz<170000 # check for this size range
    if sz_chk:
    print " sz_chk"
    spam += 1
    for can in canit:
    if subject.count(can):
    print " can it: '%s'"%can
    spam += 1
    print " spam", spam
    if spam > 2: # life is harsh
    print " dele"
    #mbox.dele( i ) # uncomment when you are ready

    print "quit"
    mbox.quit()


    while 1:
    print
    doit()
    sleep(90)
    Simon Burton, Sep 20, 2003
    #1
    1. Advertising

  2. Simon Burton

    Phil Weldon Guest

    At best that will identify less than a third of the messages produced by
    this worm. A permutating and mutating bogus 'Undeliverable e-mail' message
    carrying the infection package is more common than the HTML message. Either
    type is over 100 KBytes, and will quickly clog a mailbox.

    Expect the HTML message body, FROM and SUBJECT to mutate also.

    Phil Weldon,

    "Simon Burton" <> wrote in message
    news:p...
    >
    > This was so easy :)
    >
    > Simon Burton.
    >
    >
    > #!/usr/bin/env python
    >
    > import sys
    > from time import sleep
    > from poplib import *
    >
    > canit = """Newest Internet Critical Pack
    > New Internet Upgrade
    > Message: User unknown
    > Last Net Critical Patch
    > last pack
    > error notice
    > Failure Advice
    > failure message
    > Bug Message
    > Newest Internet Critical Pack
    > Advice
    > last net security pack
    > Latest Microsoft Security Upgrade
    > Latest Upgrade
    > Last Network Critical Update
    > Current Net Security Pack
    > new net pack
    > Last Network Security Pack
    > Security Pack
    > Security Update
    > Critical Upgrade
    > Undelivered Message
    > Security Upgrade
    > Net Update
    > security pack
    > Bug Letter
    > Network Pack
    > New Net Update
    > """.split("\n")[:-1]
    > #print canit
    > #sys.exit(0)
    >
    >
    > def doit():
    > mbox = POP3( "pop.webone.com.au" )
    >
    > mbox.user( "XXX" )
    > mbox.pass_( "XXX" )
    >
    > stat = mbox.stat()
    > print "stat",stat
    >
    > ilist = mbox.list()
    > olist = []
    > for info in ilist[1]:
    > info = str.split( info )
    > i, sz = int(info[0]), int(info[1])
    > spam = 0
    > print "msg #%.3d\t%d"%( i, sz )
    > header = mbox.top( i, 0 )[1]
    > subject = ""
    > sender = ""
    > for line in header:
    > #print "\t",line
    > if line.startswith( "From:" ):
    > sender = line
    > if line.startswith( "Subject:" ):
    > subject = line
    > if line.startswith( "SUBJECT:" ):
    > subject = line
    > if line.startswith( "X-Spam-Level" ):
    > spam = line.count( "*" )
    > if subject:
    > print " "+subject
    > if sender:
    > print " ", sender
    > print " spam", spam
    > sz_chk = 140000<sz<170000 # check for this size range
    > if sz_chk:
    > print " sz_chk"
    > spam += 1
    > for can in canit:
    > if subject.count(can):
    > print " can it: '%s'"%can
    > spam += 1
    > print " spam", spam
    > if spam > 2: # life is harsh
    > print " dele"
    > #mbox.dele( i ) # uncomment when you are ready
    >
    > print "quit"
    > mbox.quit()
    >
    >
    > while 1:
    > print
    > doit()
    > sleep(90)
    >
    Phil Weldon, Sep 20, 2003
    #2
    1. Advertising

  3. Simon Burton

    Robin Becker Guest

    In article <S02bb.43098$>, Phil
    Weldon <> writes
    >At best that will identify less than a third of the messages produced by
    >this worm. A permutating and mutating bogus 'Undeliverable e-mail' message
    >carrying the infection package is more common than the HTML message. Either
    >type is over 100 KBytes, and will quickly clog a mailbox.
    >
    >Expect the HTML message body, FROM and SUBJECT to mutate also.
    >
    >Phil Weldon,
    >
    >"Simon Burton" <> wrote in message
    >news:p...
    >>
    >> This was so easy :)
    >>
    >> Simon Burton.

    ..... you're right, I had to use patterns like

    re.compile('^subject:\s*((Microsoft|MS|Upgrade|Net|Network|New|Newest|
    Latest|Last|Critical|Patch|Pack|internet|security|current|update)\s*)+$'
    ,re.IGNORECASE)

    and check the from value as well. Even so I'm not getting all of them
    and as you say mutation is happening.
    --
    Robin Becker
    Robin Becker, Sep 20, 2003
    #3
  4. Simon Burton

    Dave Kuhlman Guest

    Robin Becker wrote:

    [snip]
    >>Phil Weldon,
    >>
    >>"Simon Burton" <> wrote in message
    >>news:p...
    >>>
    >>> This was so easy :)
    >>>
    >>> Simon Burton.

    > .... you're right, I had to use patterns like


    Almost all the spam I'm receiving has an attachment whose file
    type is one of .exe, .bat, .com, .scr, .pif, and a few others. Is
    there a way for your Python script to check for that? How do you
    do that in Python.

    I'm guessing that you are not in the mood for receiving executable
    files right now.

    Here is a strange thing: I'm using procmail and junkfilter to
    dispose of these. I looked at procmail's log, and noticed that
    in many cases (but not all) I seem to be receiving exactly 2 spam
    emails from each From address. I suppose this worm does not want
    me to think I can do something so simple as send a request to one
    infected machine asking it to clean itself up.

    Dave

    [snip]

    --
    Dave Kuhlman
    http://www.rexx.com/~dkuhlman
    Dave Kuhlman, Sep 20, 2003
    #4
  5. Simon Burton fed this fish to the penguins on Friday 19 September 2003
    11:52 pm:

    >
    >
    >
    > This was so easy :)


    Probably helps to have an ISP that inserts the X-Spam-Level header <G>

    Was missing too many variants on my runs. So I took it as inspiration
    for this (not fully tested) variation which counts up words in both
    subject and from headers that match candidate lists.

    """
    SwenKill.py Dennis Lee Bieber September 20 2003
    Based upon a program presented on comp.lang.python

    Checks POP3 headers for hallmarks of a Swen trojan package and
    deletes
    any qualifying message before it is downloaded (note: depending on
    check times, the MUA may still download messages before this routine
    has checked them).

    Usage:
    python swenkill.py pop3.server.address user.name password

    If imported, one can create multiple instances of the checker, and
    imbed them within their own timing check loop.

    """

    import sys
    import time

    from poplib import *

    CHECKINTERVAL = 90 #seconds

    SubjectWords = """advice
    bug
    critical
    current
    error
    failure
    internet
    last
    latest
    letter
    microsoft
    net
    network
    new
    newest
    notice
    pack
    patch
    report
    returned
    security
    unkown
    undeliverable
    undelivered
    update
    upgrade
    user""".lower() #set all to lower case
    SubjectWords = SubjectWords.split("\n")

    FromWords = """Administrator
    Assistance
    Bulletin
    Center
    Corporation
    Delivery
    Department
    Email
    Inet
    Internet
    Mail
    Message
    Microsoft
    MS
    Net
    Network
    Program
    Public
    Section
    Security
    Service
    Storage
    Technical""".lower()
    FromWords = FromWords.split("\n")

    class SwenKiller:
    def __init__(self, pop3, username, password):
    self.pop3 = pop3
    self.username = username
    self.password = password

    def kill(self):
    mbox = POP3(self.pop3)
    mbox.user(self.username)
    mbox.pass_(self.password)

    stat = mbox.stat()
    print self.pop3, self.username, "\tstat", stat

    ilist = mbox.list()

    for info in ilist[1]:
    info = str.split(info) #? where did str come from?
    built-in?
    inum = int(info[0])
    sz = int(info[1])
    print "Msg #%.3d\t%d" % (inum, sz)

    header = mbox.top(inum, 0)[1]

    subject = ""
    sender = "" #from is a keyword, can't be used

    for line in header:
    line = line.lower()
    if line.startswith("from:"):
    sender = line.replace('"', '')
    if line.startswith("subject:"):
    subject = line.replace('"', '')

    size_check = 140000 < sz < 170000

    SubjectCount = 0
    FromCount = 0

    for wd in subject.split():
    if wd in SubjectWords:
    SubjectCount += 1

    for wd in sender.split():
    if wd in FromWords:
    FromCount += 1

    if subject == "" or subject == "subject: ":
    SubjectCount += 1

    if sender == "" or sender == "from: ":
    FromCount += 1

    print "(Scored: size=%s subject=%s from=%s)" % (size_check,
    SubjectCount, FromCount)

    if (SubjectCount > 2) or (FromCount > 2) \
    or (size_check and (SubjectCount or FromCount)):
    print "DELETED:"
    mbox.dele(inum)

    print "\t%s\n\t%s\n" % (subject, sender)

    print "Check Done"
    print " "
    mbox.quit()

    if __name__ == "__main__":
    if len(sys.argv) < 4:
    print __doc__
    else:
    killer = SwenKiller(sys.argv[1], sys.argv[2], sys.argv[3])
    try:
    while 1:
    print " "
    try:
    killer.kill()
    finally:
    pass #ignore errors inside the kill routine
    time.sleep(CHECKINTERVAL)
    finally:
    pass #allow <ctrl-c> to kill the sleep and exit




    I need to clean up the try: blocks, these were just quicky
    place-holders.

    --
    > ============================================================== <
    > | Wulfraed Dennis Lee Bieber KD6MOG <
    > | Bestiaria Support Staff <
    > ============================================================== <
    > Bestiaria Home Page: http://www.beastie.dm.net/ <
    > Home Page: http://www.dm.net/~wulfraed/ <
    Dennis Lee Bieber, Sep 20, 2003
    #5
  6. Dave Kuhlman fed this fish to the penguins on Saturday 20 September
    2003 02:39 pm:

    >
    > Almost all the spam I'm receiving has an attachment whose file
    > type is one of .exe, .bat, .com, .scr, .pif, and a few others. Is
    > there a way for your Python script to check for that? How do you
    > do that in Python.
    >

    Checking for the attachment requires scanning the body of the message
    -- in effect, downloading it anyway. The script, as is, is only
    accessing the headers and performing the delete on the server end.

    --
    > ============================================================== <
    > | Wulfraed Dennis Lee Bieber KD6MOG <
    > | Bestiaria Support Staff <
    > ============================================================== <
    > Bestiaria Home Page: http://www.beastie.dm.net/ <
    > Home Page: http://www.dm.net/~wulfraed/ <
    Dennis Lee Bieber, Sep 21, 2003
    #6
  7. On Sat, 20 Sep 2003 14:39:49 -0700,
    Dave Kuhlman <> wrote:
    > Almost all the spam I'm receiving has an attachment whose file
    > type is one of .exe, .bat, .com, .scr, .pif, and a few others. Is
    > there a way for your Python script to check for that? How do you
    > do that in Python.


    If you're using Exim as a mail server, you can compile Exim with Python as
    an extension language (elspy.sf.net). Rejecting all messages with
    executable attachments is then a matter of creating an exim_local_scan.py
    file containing:

    from elspy import execontent_simple
    def local_scan (fd, headers, info):
    # Trash executables
    execontent_simple.local_scan(fd, headers, info)

    # For now, do no other scanning
    return

    --amk
    A.M. Kuchling, Sep 21, 2003
    #7
  8. Simon Burton

    Donn Cave Guest

    Quoth "Phil Weldon" <>:
    | At best that will identify less than a third of the messages produced by
    | this worm. A permutating and mutating bogus 'Undeliverable e-mail' message
    | carrying the infection package is more common than the HTML message. Either
    | type is over 100 KBytes, and will quickly clog a mailbox.
    |
    | Expect the HTML message body, FROM and SUBJECT to mutate also.

    I've been getting one every two minutes or so for the last couple of
    days, so I had to do something this morning. Luckily I have shell
    access and fairly conventional UNIX mail delivery, so I put in a
    filter on delivery. My criterion is nowhere near as complicated as
    the rest of you folks, but after about 6 hours it caught 157 and
    missed no more than a dozen. I just look for 'boundary="[a-z]' in
    the header. Of course that could easily turn out to catch a legitimate
    email ... but of course, with an attachment, and I don't want your
    stupid Word document anyway.

    The filter is 38 lines of awk (with comments), and a C program to
    lock the folder and invoke the awk program.

    Donn Cave,
    Donn Cave, Sep 21, 2003
    #8
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Rene Pijlman
    Replies:
    22
    Views:
    710
    Fredrik Lundh
    Dec 10, 2003
  2. Sergio Correia
    Replies:
    7
    Views:
    281
    Ben Finney
    Sep 18, 2007
  3. Replies:
    3
    Views:
    459
  4. zax75
    Replies:
    1
    Views:
    1,087
  5. David Binnie
    Replies:
    2
    Views:
    437
    Rich Webb
    May 22, 2009
Loading...

Share This Page