list subscription spammers

I'm seeing massive numbers of subscription lists to various lists we host (including multiple requests to the same list).
These are submitted via a distributed network of hosts, presumably botnet victims / open proxies.
The requests are from foo+[0-9]{9}@gmail.com
e.g.,
foo+55216394@
where foo is one of several dropboxes.
Obviously, even after being banned, they're still getting a 200 response code, so they keep spamming away, but what's their goal here? Trying to get access to a list so that they can get archives / memberlists (or post to them)? Or just trying to create a nuissance? If the former, why do they submit so many requests for each list?
If anyone has seen similar behavior and has more info, please feel free to share on or off list.
w

And, self-followup, I had looked on list.org before, but hadn't checked the archives, so seems clear that the behavior is common. Running the RHEL5 Mailman currently (2.1.9) so still don't have the SUBSCRIBE_FORM_SECRET feature yet.
Mostly curious about the motivation behind this - what do these bots do if / when they are actually able to confirm or get confirmed?
w

On Tue, Aug 25, 2015 at 1:25 PM, Will Yardley <mailman@veggiechinese.net> wrote:
Mostly curious about the motivation behind this - what do these bots do if / when they are actually able to confirm or get confirmed?
They probably try to read the subscription list to get more email addresses. Of course, they can also post spam to the lists. Perhaps both, but I suspect the email addresses are of more value.
Skip

ps - Here are a couple of quick throwaway 'withlist' scripts I threw together to add a regexp matching the spammers' email addresses, and to purge pending subscription requests matching a similar regexp. Posting here in case someone finds them useful for this, or some other, purpose.
% cat purge_requests.py
# quick "withlist" script.
# call via withlist -r purge_requests LISTNAME
# or via loop:
# for LIST in ./list_lists -b
; do ./withlist -r purge_requests $LIST ; done
import re from Mailman import mm_cfg from Mailman.mm_cfg import DISCARD
email_re = re.compile('^(foo|bar.baz|blah)\+[0-9]+@example\.com')
def purge_requests(m): print "** Checking %s" % m.internal_name() m.Lock() for item in m.GetSubscriptionIds(): email_addr = m.GetRecord(item)[1] if email_re.match(email_addr): print ">> Discarding %s from %s" % (email_addr, m.internal_name()) m.HandleRequest(item, DISCARD) m.Save() m.Unlock()
% cat set_banlist.py
# quick "withlist" script.
# call via withlist -r set_banlist LISTNAME
# or via loop:
# for LIST in ./list_lists -b
; do ./withlist -r set_banlist $LIST ; done
# Obviously, the problem becomes a bit more complex if we want to adjust # the existing rule, vs. adding a new one; then we'd have to track the # item # within the list, and modify that item (this also shouldn't be # too hard).
from Mailman import mm_cfg
# This will append the item below to the ban_list for $LISTNAME # Note additional pattern below; that's just a check to see if the # pattern already exists. ban_item = '^(foo|bar.baz|blah)\\+[0-9]+@example\.com'
def set_banlist(m): # Rather than use regex, use this to see if substring is in list if not rule_exists(m.ban_list): print "**** Updating %s" % m.internal_name() m.Lock() m.ban_list.append(ban_item) m.Save()
# Could probably do this a little more tersely with 'lambda' def rule_exists(list): for item in list: if '\(foo' in item: return 1

On 08/26/2015 07:14 PM, Will Yardley wrote:
% cat set_banlist.py
...
Also see <https://www.msapiro.net/scripts/add_banned.py>.
-- Mark Sapiro <mark@msapiro.net> The highway is for gamblers, San Francisco Bay Area, California better use your sense - B. Dylan

On 08/25/2015 10:12 AM, Will Yardley wrote:
We have seen a huge rash of these on the python.org lists. Even with a SUBSCRIBE_FORM_SECRET set and SUBSCRIBE_FORM_MIN_TIME = seconds(8) a small percentage succeeded and that was still a lot.
Because of this, the head of the 2.1 branch at <https://launchpad.net/mailman/2.1/> now implements a GLOBAL_BAN_LIST and on mail.python.org, that is set to
GLOBAL_BAN_LIST = ['^.*\+\d{3,}@']
to ban any address whose local part ends with a '+' followed by 3 or more digits. Before doing this I checked and there was only one member of one list out of all the python.org list subscribers that had a local part ending with '+' and digits and it only had one digit between the '+' and '@'.
The attempts keep coming though.
-- Mark Sapiro <mark@msapiro.net> The highway is for gamblers, San Francisco Bay Area, California better use your sense - B. Dylan

And, self-followup, I had looked on list.org before, but hadn't checked the archives, so seems clear that the behavior is common. Running the RHEL5 Mailman currently (2.1.9) so still don't have the SUBSCRIBE_FORM_SECRET feature yet.
Mostly curious about the motivation behind this - what do these bots do if / when they are actually able to confirm or get confirmed?
w

On Tue, Aug 25, 2015 at 1:25 PM, Will Yardley <mailman@veggiechinese.net> wrote:
Mostly curious about the motivation behind this - what do these bots do if / when they are actually able to confirm or get confirmed?
They probably try to read the subscription list to get more email addresses. Of course, they can also post spam to the lists. Perhaps both, but I suspect the email addresses are of more value.
Skip

ps - Here are a couple of quick throwaway 'withlist' scripts I threw together to add a regexp matching the spammers' email addresses, and to purge pending subscription requests matching a similar regexp. Posting here in case someone finds them useful for this, or some other, purpose.
% cat purge_requests.py
# quick "withlist" script.
# call via withlist -r purge_requests LISTNAME
# or via loop:
# for LIST in ./list_lists -b
; do ./withlist -r purge_requests $LIST ; done
import re from Mailman import mm_cfg from Mailman.mm_cfg import DISCARD
email_re = re.compile('^(foo|bar.baz|blah)\+[0-9]+@example\.com')
def purge_requests(m): print "** Checking %s" % m.internal_name() m.Lock() for item in m.GetSubscriptionIds(): email_addr = m.GetRecord(item)[1] if email_re.match(email_addr): print ">> Discarding %s from %s" % (email_addr, m.internal_name()) m.HandleRequest(item, DISCARD) m.Save() m.Unlock()
% cat set_banlist.py
# quick "withlist" script.
# call via withlist -r set_banlist LISTNAME
# or via loop:
# for LIST in ./list_lists -b
; do ./withlist -r set_banlist $LIST ; done
# Obviously, the problem becomes a bit more complex if we want to adjust # the existing rule, vs. adding a new one; then we'd have to track the # item # within the list, and modify that item (this also shouldn't be # too hard).
from Mailman import mm_cfg
# This will append the item below to the ban_list for $LISTNAME # Note additional pattern below; that's just a check to see if the # pattern already exists. ban_item = '^(foo|bar.baz|blah)\\+[0-9]+@example\.com'
def set_banlist(m): # Rather than use regex, use this to see if substring is in list if not rule_exists(m.ban_list): print "**** Updating %s" % m.internal_name() m.Lock() m.ban_list.append(ban_item) m.Save()
# Could probably do this a little more tersely with 'lambda' def rule_exists(list): for item in list: if '\(foo' in item: return 1

On 08/26/2015 07:14 PM, Will Yardley wrote:
% cat set_banlist.py
...
Also see <https://www.msapiro.net/scripts/add_banned.py>.
-- Mark Sapiro <mark@msapiro.net> The highway is for gamblers, San Francisco Bay Area, California better use your sense - B. Dylan

On 08/25/2015 10:12 AM, Will Yardley wrote:
We have seen a huge rash of these on the python.org lists. Even with a SUBSCRIBE_FORM_SECRET set and SUBSCRIBE_FORM_MIN_TIME = seconds(8) a small percentage succeeded and that was still a lot.
Because of this, the head of the 2.1 branch at <https://launchpad.net/mailman/2.1/> now implements a GLOBAL_BAN_LIST and on mail.python.org, that is set to
GLOBAL_BAN_LIST = ['^.*\+\d{3,}@']
to ban any address whose local part ends with a '+' followed by 3 or more digits. Before doing this I checked and there was only one member of one list out of all the python.org list subscribers that had a local part ending with '+' and digits and it only had one digit between the '+' and '@'.
The attempts keep coming though.
-- Mark Sapiro <mark@msapiro.net> The highway is for gamblers, San Francisco Bay Area, California better use your sense - B. Dylan
participants (3)
-
Mark Sapiro
-
Skip Montanaro
-
Will Yardley