Skip to content

Commit

Permalink
Initial Commit
Browse files Browse the repository at this point in the history
  • Loading branch information
W1zzardTPU committed Dec 2, 2015
0 parents commit aee7bd4
Show file tree
Hide file tree
Showing 18 changed files with 1,521 additions and 0 deletions.
18 changes: 18 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# TPU: Detect and Block Spam Registrations

This XenForo addon uses custom detection methods to identify automated and manual registrations that are trying to spam your forum.

You may score based on:

Visitor's country
E-Mail address
E-Mail length
Username
IP hostname
Internet Provider name
Open TCP port (requires PHP-sockets extension)
StopForum Spam API
Project Honeyport API
TOR client detection

Visit the addon's page: https://xenforo.com/community/resources/tpu-detect-and-block-spam-registrations.2973/
470 changes: 470 additions & 0 deletions addon-TPUDetectSpamReg.xml

Large diffs are not rendered by default.

119 changes: 119 additions & 0 deletions upload/library/TPUDetectSpamReg/AS.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
<?php

class TPUDetectSpamReg_AS
{
static function reverseIP($ip)
{
$parts=explode('.', trim($ip));
if (count($parts)!=4)
return false;

$parts=array_map('intval', $parts);
$parts=array_reverse($parts);

return implode('.', $parts);
}

static function reverseIPv6($ip)
{
$addr = inet_pton($ip);
$unpack = unpack('H*hex', $addr);
$hex = $unpack['hex'];
return implode('.', array_reverse(str_split($hex)));
}

static function isIPv6($ip)
{
return filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6);
}

static function getASNameAndNumber($ip, &$asNumber, &$asName)
{
if (self::isIPv6($ip))
$dns=dns_get_record(self::reverseIPv6($ip).'.origin6.asn.cymru.com', DNS_TXT);
else
$dns=dns_get_record(self::reverseIP($ip).'.origin.asn.cymru.com', DNS_TXT);

if ((is_array($dns)) && (isset($dns[0])))
{
$items=explode('|', $dns[0]['txt'], 2);
$items=array_shift($items);
$asNumber=intval($items);
if ($asNumber>0)
{
$dns=dns_get_record('AS'.$asNumber.'.asn.cymru.com', DNS_TXT);
if ((is_array($dns)) && (isset($dns[0])))
{
$tokens=explode('|', $dns[0]['txt']);
$asName=trim($tokens[4]);

return TRUE;
}
}
}

return FALSE;

// Old slow code
try {
$networkinfo=json_decode(file_get_contents('https://stat.ripe.net/data/network-info/data.json?resource='.$ip));
$asNumber=$networkinfo->data->asns[0];
$asInfo=json_decode(file_get_contents('https://stat.ripe.net/data/as-overview/data.json?resource=AS'.$asNumber));
$asName=$asInfo->data->holder;

return TRUE;
} catch (Exception $e) {};

return FALSE;
}

static function getRegSpamScore(&$score, array $user, $verbose, $debug, $model)
{
$o=XenForo_Application::getOptions();

if (trim($o->TPUDetectSpamRegAS)!='')
{
if (self::getASNameAndNumber($user['ip'], $asNumber, $asName))
{
if ($verbose)
$model->logScore('tpu_detectspamreg_as_detected', 0, array('number'=>$asNumber, 'name'=>$asName));

foreach (explode("\n", $o->TPUDetectSpamRegAS) as $entry)
{
$entry=explode('|', trim($entry));
if (count($entry)!=2)
continue;

list($points, $match)=$entry;

if ((is_numeric($match)) && ($match>0))
{
if ((int)$match==(int)$asNumber)
{
$model->logScore('tpu_detectspamreg_as_fail', $points, array('number'=>$asNumber, 'name'=>$asName));
if (is_numeric($points))
$score['points']+=$points;
else
$score[$points]=true;
}
} else
{
$asName=strtok($asName, ' ');
$regex=$model->buildWildcardRegex($match);

if (preg_match('/^'.$regex.'$/iU', $asName))
{
$model->logScore('tpu_detectspamreg_as_fail', $points, array('number'=>$asNumber, 'name'=>$asName));
if (is_numeric($points))
$score['points']+=$points;
else
$score[$points]=true;
} else
if ($debug)
$model->logScore('tpu_detectspamreg_as_ok', 0, array('number'=>$asNumber, 'name'=>$match));
}
}
}
}
}
}
35 changes: 35 additions & 0 deletions upload/library/TPUDetectSpamReg/Cleanup.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<?php

class TPUDetectSpamReg_Cleanup
{
public static function cleanup()
{
$o=XenForo_Application::getOptions();

// Remove permanently banned users from user-permissions to improve performance
$userIds=XenForo_Application::getDb()->fetchAll('SELECT xf_permission_entry.user_id FROM xf_permission_entry LEFT JOIN xf_user ON xf_permission_entry.user_id=xf_user.user_id LEFT JOIN xf_user_ban ON xf_permission_entry.user_id=xf_user_ban.user_id WHERE permission_id="TPUSpamRegModAllPosts" AND xf_permission_entry.user_id!=0 AND end_date=0');
foreach($userIds as $row)
{
$permissions=array('general'=>array('TPUSpamRegModAllPosts'=>'unset'));
XenForo_Model::create('XenForo_Model_Permission')->updateGlobalPermissionsForUserCollection($permissions, 0, $row['user_id']);
}

// Permanently delete users who have made no posts and haven't logged on for x days
if ($o->TPUDetectSpamRegScoreModPosts['purgedays']>0)
{
$userIds=XenForo_Application::getDb()->fetchAll('SELECT xf_permission_entry.user_id FROM xf_permission_entry LEFT JOIN xf_user ON xf_permission_entry.user_id=xf_user.user_id WHERE permission_id="TPUSpamRegModAllPosts" AND xf_permission_entry.user_id!=0 AND message_count=0 AND last_activity<UNIX_TIMESTAMP(DATE_SUB(NOW(), INTERVAL ? DAY))', array($o->TPUDetectSpamRegScoreModPosts['purgedays']));

foreach($userIds as $row)
{
// Let's make sure the user has no deleted posts
$hasPosts=XenForo_Application::getDb()->fetchOne('SELECT user_id FROM xf_post WHERE user_id=?', $row['user_id']);
if ($hasPosts!==FALSE)
continue;

$writer = XenForo_DataWriter::create('XenForo_DataWriter_User', XenForo_DataWriter::ERROR_EXCEPTION);
$writer->setExistingData($row);
$writer->delete();
}
}
}
}
20 changes: 20 additions & 0 deletions upload/library/TPUDetectSpamReg/ControllerPublicRegister.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<?php

class TPUDetectSpamReg_ControllerPublicRegister extends XFCP_TPUDetectSpamReg_ControllerPublicRegister
{
protected function _completeRegistration(array $user, array $extraParams = array())
{
$result=parent::_completeRegistration($user, $extraParams);

if (class_exists('TPUDetectSpamReg_ModelSpamPrevention', false))
{
if (TPUDetectSpamReg_ModelSpamPrevention::$moderateAllPosts)
{
$permissions=array('general'=>array('TPUSpamRegModAllPosts'=>'allow'));
$this->getModelFromCache('XenForo_Model_Permission')->updateGlobalPermissionsForUserCollection($permissions, 0, $user['user_id']);
}
}

return $result;
}
}
36 changes: 36 additions & 0 deletions upload/library/TPUDetectSpamReg/Email.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<?php

class TPUDetectSpamReg_Email
{
static function getRegSpamScore(&$score, array $user, $verbose, $debug, $model)
{
$o=XenForo_Application::getOptions();

if (trim($o->TPUDetectSpamRegEmail)!='')
{
$email=$user['email'];

foreach (explode("\n", $o->TPUDetectSpamRegEmail) as $entry)
{
$entry=explode('|', trim($entry));
if (count($entry)!=2)
continue;

list($points, $match)=$entry;

$regex=$model->buildWildcardRegex($match);

if (preg_match('/^'.$regex.'$/iU', $email))
{
$model->logScore('tpu_detectspamreg_email_fail', $points, array('email'=>$match));
if (is_numeric($points))
$score['points']+=$points;
else
$score[$points]=true;
} else
if ($debug)
$model->logScore('tpu_detectspamreg_email_ok', 0, array('email'=>$match));
}
}
}
}
36 changes: 36 additions & 0 deletions upload/library/TPUDetectSpamReg/EmailLength.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<?php

class TPUDetectSpamReg_EmailLength
{
static function getRegSpamScore(&$score, array $user, $verbose, $debug, $model)
{
$o=XenForo_Application::getOptions();

$items=explode('@', $user['email']);
$email=array_shift($items);

if (trim($o->TPUDetectSpamRegEmailLen20)!=0)
{
if (strlen($email)>=20)
{
$model->logScore('tpu_detectspamreg_emaillen_fail', $o->TPUDetectSpamRegEmailLen20, array('length'=>20, 'email'=>$email));
$score['points']+=$o->TPUDetectSpamRegEmailLen20;
return;
} else
if ($debug)
$model->logScore('tpu_detectspamreg_emaillen_ok', 0, array('length'=>20, 'email'=>$email));
}

if (trim($o->TPUDetectSpamRegEmailLen15)!=0)
{
if (strlen($email)>=15)
{
$model->logScore('tpu_detectspamreg_emaillen_fail', $o->TPUDetectSpamRegEmailLen15, array('length'=>15, 'email'=>$email));
$score['points']+=$o->TPUDetectSpamRegEmailLen15;
return;
} else
if ($debug)
$model->logScore('tpu_detectspamreg_emaillen_ok', 0, array('length'=>15, 'email'=>$email));
}
}
}
51 changes: 51 additions & 0 deletions upload/library/TPUDetectSpamReg/HoneyPot.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
<?php

class TPUDetectSpamReg_HoneyPot
{
static function getRegSpamScore(&$score, array $user, $verbose, $debug, $model)
{
$o=XenForo_Application::getOptions();

if ($o->TPUDetectSpamRegHoneyPotEnabled)
{
// Only IPv4 supported
if (filter_var($user['ip'], FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)==FALSE)
return;

$dnsBl=new XenForo_DnsBl($o->TPUDetectSpamRegHoneyPotAPIKey.'.%s.dnsbl.httpbl.org');
$res=$dnsBl->checkIp($user['ip']);
if (is_array($res))
{
if ($res[0]=='127')
{
$lastSeen=intval($res[1]);
$threatLevel=intval($res[2]);

if ($lastSeen<$o->TPUDetectSpamRegHoneyPotCutoff)
{
$scoreToGive=0;

if (($threatLevel>=10) && ($threatLevel<20))
$scoreToGive=$o->TPUDetectSpamRegHoneyPotScore10;
elseif (($threatLevel>=20) && ($threatLevel<40))
$scoreToGive=$o->TPUDetectSpamRegHoneyPotScore20;
elseif (($threatLevel>=40) && ($threatLevel<60))
$scoreToGive=$o->TPUDetectSpamRegHoneyPotScore40;
elseif (($threatLevel>=60) && ($threatLevel<80))
$scoreToGive=$o->TPUDetectSpamRegHoneyPotScore60;
elseif (($threatLevel>=80) && ($threatLevel<100))
$scoreToGive=$o->TPUDetectSpamRegHoneyPotScore80;

if ($scoreToGive!=0)
{
$model->logScore('tpu_detectspamreg_honeypot_fail', $scoreToGive, array('lastseen'=>$lastSeen, 'threatlevel'=>$threatLevel));
$score['points']+=$scoreToGive;
} else
$model->logScore('tpu_detectspamreg_honeypot_pass', 0, array('lastseen'=>$lastSeen, 'threatlevel'=>$threatLevel));
} else
$model->logScore('tpu_detectspamreg_honeypot_ok', 0);
}
}
}
}
}
39 changes: 39 additions & 0 deletions upload/library/TPUDetectSpamReg/Hostname.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
<?php

class TPUDetectSpamReg_Hostname
{
static function getRegSpamScore(&$score, array $user, $verbose, $debug, $model)
{
$o=XenForo_Application::getOptions();

if (trim($o->TPUDetectSpamRegHostname)!='')
{
$hostname=gethostbyaddr($user['ip']);

if ($verbose)
$model->logScore('tpu_detectspamreg_hostname_detected', 0, array('hostname'=>$hostname));

foreach (explode("\n", $o->TPUDetectSpamRegHostname) as $entry)
{
$entry=explode('|', trim($entry));
if (count($entry)!=2)
continue;

list($points, $match)=$entry;

$regex=$model->buildWildcardRegex($match);

if (preg_match('/^'.$regex.'$/iU', $hostname))
{
$model->logScore('tpu_detectspamreg_hostname_fail', $points, array('hostname'=>$match));
if (is_numeric($points))
$score['points']+=$points;
else
$score[$points]=true;
} else
if ($debug)
$model->logScore('tpu_detectspamreg_hostname_ok', 0, array('hostname'=>$match));
}
}
}
}
Loading

0 comments on commit aee7bd4

Please sign in to comment.