Solving a Mailing List “Gap Spam” Problem

We recently responded to an unusual and particularly wily problem on the SANS DFIR mailing list. This list, with nearly 7,000 members, is used for exchanging all manners of digital forensic and incident response information, and is a great resource for the DFIR community. However, several weeks ago, we found that anyone sending a message to the list almost immediately received what looked like a “response” containing spam.

Sample spam generated by unassociated source

Unfortunately, spam occasionally happens with list members. Normally, we just look up the sender of the spam message and remove them from the list. However, these messages were from senders that were not list members.

Gap Spam process diagram

It was clear that at least one recipient address was being used to harvest messages and forge the “replies”. Finding the one or two bad actors from a list of 7,000 was going to prove difficult. We entertained the idea of forcing all members to revalidate, and several other options, but all were either extremely labor-intensive or highly intrusive to list members. I inquired about this with some of the SANS Support Team, and Donald Endersby suggested some form of a mail merge. We would send individual messages to list members, each containing some form of a unique identifier, then track which identifier(s) garnered a response. It seemed simple enough, but the only tie between a legitimate sender and the corresponding spam “response” was the sender’s email address. This solution immediately became much more complex.

After a little virtual whiteboard work, we came up with an enacted the following solution:

  • Register a new domain and configured “catch-all” receipt so mail sent to any recipient on the domain is all delivered to a single real mail account. The domain used was “” – imaginary bonus points to anyone who figures out the meaning. (Also, for the enterprising reader, the catch-all has been disabled before publishing this!)
  • Configure the single real mail account (recipient) with a filter to file all messages sent to any “” address to a folder.
  • Use to create a CSV containing 10,000 “Firstname,Lastname” entries.
  • Use awk to convert the CSV to lines that look like the following:
    cat fakenamegenerator.csv | awk '{OFS=""; print $1," ",$2," <",tolower($1),".",tolower($2),">"}' > fake_senders.txt
  • Retrieve a list of all list subscribers and their true names (if that was set) using a handy python script. Because the spam “reply” was being sent almost immediately, we omitted the digest subscribers to narrow the scope of the probes.
    • Command:
    ./ -o recipients.txt -v -r -f $HOSTNAME $LISTNAME $PASSWORD
  • Merge the list of fake senders with list subscribers, so each line looks like one of the following:
    paste fake_senders.txt list_recipients.txt | sed 's/> />,/' > remailer_pairs.txt
  • Use a real message sent to the DFIR list to identify all relevant headers so each merged message would look as realistic as possible.
    • Selected header content with variables for the mail merge replacements:
    X-Original-To: $RECIPIENTX-Original-To: [email protected]: [email protected]: dfir@lists.sans.orgX-BeenThere: [email protected]: 2.1.20Precedence: listList-Id: "Incident-Response, Malware Analysis,    Digital Forensics Professionals in the SANS Community"    <>List-Unsubscribe: <>,    <mailto:[email protected]?subject=unsubscribe>List-Archive: <>List-Post: <mailto:[email protected]>List-Help: <mailto:[email protected]?subject=help>List-Subscribe: <>,    <mailto:[email protected]?subject=subscribe>Errors-To: [email protected]: "DFIR" <[email protected]>Subject: [DFIR] List smoke testReply-To: [email protected]: $SENDER Hello to the DFIR list.  We're running a smoke test right now, so please pardon the interruption.  We're eager to report our findings soon - so look for the blog post!!No need to reply to this message.  Thanks for your understanding and cooperation. -$FIRSTNAME
  • Generate a mail message using the headers and placeholders for the sender, recipient, and first name of the sender.
  • Use the sendmail binary on the mail server that operates the DFIR list to iterate through the CSV, sending a single email per loop iteration that contains the 1-to-1 paired sender/receiver data.
    • Command:
    cat remailer_tuples.txt | while IFS=, read SENDER RECIPIENT FIRSTNAME; do    RECIP_EMAIL=$( echo -n $RECIPIENT | sed -e 's/.*<(.*)>/1/' )    echo "$SENDER -> $RECIPIENT"    cat mail_template.txt | sed "s/$SENDER/$SENDER/" | sed "s/$RECIPIENT/$RECIPIENT/" | sed "s/$FIRSTNAME/$FIRSTNAME/" | sendmail $RECIP_EMAILdone
  • Wait for email responses to the catch-all domain.
  • It took a grand total of one minute before we’d found the culprit. They were immediately removed from the list. To our surprise, another one was discovered several minutes later – and was promptly removed from the list as well.

    All in all, this was an unexpected but interesting drill. I’m not sure if this “gap spam” approach is common with any other mailing lists, but this is one approach that can help if you encounter such tactics.

    DevOps Unbound Podcast

    *** This is a Security Bloggers Network syndicated blog from SANS Blog authored by SANS Blog. Read the original post at:

    Integrated Security Data PulseMeter

    Step 1 of 7

    What percentage of your organization’s security data is integrated into a SIEM or data repository you manage? (Select one)(Required)