mirror of
https://gerrit.wikimedia.org/r/mediawiki/extensions/AbuseFilter.git
synced 2024-09-24 02:38:16 +00:00
Add rangeblocks, a bit of a nuclear option for the abuse filter. Not intended for Wikimedia use
This commit is contained in:
parent
e2af4ae133
commit
74097d106e
|
@ -9,6 +9,7 @@ class AbuseFilter {
|
|||
public static $modifyCache = array();
|
||||
public static $condLimitEnabled = true;
|
||||
public static $condCount = 0;
|
||||
public static $filters = array();
|
||||
|
||||
public static function generateUserVars( $user ) {
|
||||
$vars = array();
|
||||
|
@ -130,6 +131,7 @@ class AbuseFilter {
|
|||
$filter_matched = array();
|
||||
|
||||
while ( $row = $dbr->fetchObject( $res ) ) {
|
||||
self::$filters[$row->af_id] = $row;
|
||||
if ( self::checkConditions( $row->af_pattern, $vars ) ) {
|
||||
$blocking_filters[$row->af_id] = $row;
|
||||
|
||||
|
@ -219,7 +221,7 @@ class AbuseFilter {
|
|||
case 'warn':
|
||||
wfLoadExtensionMessages( 'AbuseFilter' );
|
||||
|
||||
if (!$_SESSION['abusefilter-warned']) {
|
||||
if (!isset($_SESSION['abusefilter-warned']) || !$_SESSION['abusefilter-warned']) {
|
||||
$_SESSION['abusefilter-warned'] = true;
|
||||
|
||||
// Threaten them a little bit
|
||||
|
@ -259,12 +261,11 @@ class AbuseFilter {
|
|||
$block = new Block;
|
||||
$block->mAddress = $wgUser->getName();
|
||||
$block->mUser = $wgUser->getId();
|
||||
$block->mBy = User::idFromName( wfMsgForContent( 'abusefilter-blocker' ) ); // Let's say the site owner blocked them
|
||||
$block->mByName = wfMsgForContent( 'abusefilter-blocker' );
|
||||
$block->mBy = $filterUser->getId();
|
||||
$block->mByName = $filterUser->getName();
|
||||
$block->mReason = wfMsgForContent( 'abusefilter-blockreason', $rule_desc );
|
||||
$block->mTimestamp = wfTimestampNow();
|
||||
$block->mEnableAutoblock = 1;
|
||||
$block->mAngryAutoblock = 1; // Block lots of IPs
|
||||
$block->mAnonOnly = 1;
|
||||
$block->mCreateAccount = 1;
|
||||
$block->mExpiry = 'infinity';
|
||||
|
||||
|
@ -282,6 +283,47 @@ class AbuseFilter {
|
|||
|
||||
$display .= wfMsgNoTrans( 'abusefilter-blocked-display', $rule_desc ) ."<br />\n";
|
||||
break;
|
||||
case 'rangeblock':
|
||||
wfLoadExtensionMessages( 'AbuseFilter' );
|
||||
|
||||
global $wgUser;
|
||||
$filterUser = AbuseFilter::getFilterUser();
|
||||
|
||||
$range = IP::toHex( wfGetIP() );
|
||||
$range = substr( $range, 0, 4 ) . '0000';
|
||||
$range = long2ip( hexdec( $range ) );
|
||||
$range .= "/16";
|
||||
$range = Block::normaliseRange( $range );
|
||||
|
||||
// Create a block.
|
||||
$block = new Block;
|
||||
$block->mAddress = $range;
|
||||
$block->mUser = 0;
|
||||
$block->mBy = $filterUser->getId();
|
||||
$block->mByName = $filterUser->getName();
|
||||
$block->mReason = wfMsgForContent( 'abusefilter-blockreason', $rule_desc );
|
||||
$block->mTimestamp = wfTimestampNow();
|
||||
$block->mAnonOnly = 0;
|
||||
$block->mCreateAccount = 1;
|
||||
$block->mExpiry = Block::parseExpiryInput( '1 week' );
|
||||
|
||||
$block->initialiseRange();
|
||||
|
||||
$block->insert();
|
||||
|
||||
// Log it
|
||||
# Prepare log parameters
|
||||
$logParams = array();
|
||||
$logParams[] = 'indefinite';
|
||||
$logParams[] = 'nocreate, angry-autoblock';
|
||||
|
||||
$log = new LogPage( 'block' );
|
||||
$log->addEntry( 'block', SpecialPage::getTitleFor( 'Contributions', $range ),
|
||||
wfMsgForContent( 'abusefilter-blockreason', $rule_desc ), $logParams, self::getFilterUser() );
|
||||
|
||||
$display .= wfMsgNoTrans( 'abusefilter-blocked-display', $rule_desc ) ."<br />\n";
|
||||
break;
|
||||
|
||||
case 'throttle':
|
||||
$throttleId = array_shift( $parameters );
|
||||
list( $rateCount, $ratePeriod ) = explode( ',', array_shift( $parameters ) );
|
||||
|
@ -466,7 +508,7 @@ class AbuseFilter {
|
|||
|
||||
$anyMatch = false;
|
||||
|
||||
global $wgAbuseFilterEmergencyDisableThreshold, $wgAbuseFilterEmergencyDisableCount;
|
||||
global $wgAbuseFilterEmergencyDisableThreshold, $wgAbuseFilterEmergencyDisableCount, $wgAbuseFilterEmergencyDisableAge;
|
||||
|
||||
foreach( $filters as $filter => $matched ) {
|
||||
if ($matched) {
|
||||
|
@ -479,7 +521,10 @@ class AbuseFilter {
|
|||
$wgMemc->set( self::filterMatchesKey( $filter ), 1, self::$statsStoragePeriod );
|
||||
}
|
||||
|
||||
if ($match_count > $wgAbuseFilterEmergencyDisableCount && ($match_count / $total) > $wgAbuseFilterEmergencyDisableThreshold) {
|
||||
$filter_age = wfTimestamp( TS_UNIX, self::$filters[$filter]['af_timestamp'] );
|
||||
$throttle_exempt_time = $filter_age + $wgAbuseFilterEmergencyDisableAge;
|
||||
|
||||
if ($throttle_exempt_time > time() && $match_count > $wgAbuseFilterEmergencyDisableCount && ($match_count / $total) > $wgAbuseFilterEmergencyDisableThreshold) {
|
||||
// More than X matches, constituting more than Y% of last Z edits. Disable it.
|
||||
$dbw = wfGetDB( DB_MASTER );
|
||||
$dbw->update( 'abuse_filter', array( 'af_enabled' => 0, 'af_throttled' => 1 ), array( 'af_id' => $filter ), __METHOD__ );
|
||||
|
|
|
@ -42,7 +42,7 @@ In addition, as a security measure, some privileges routinely granted to establi
|
|||
A brief description of the abuse rule which your action matched is: $1",
|
||||
|
||||
'abusefilter-blocker' => 'Abuse filter',
|
||||
'abusefilter-blockreason' => 'Automatically blocked by abuse filter. Rule description: $1',
|
||||
'abusefilter-blockreason' => 'Automatically blocked by abuse filter. Description of matched rule: $1',
|
||||
'abusefilter-degroupreason' => 'Rights automatically stripped by abuse filter. Rule description: $1',
|
||||
|
||||
'abusefilter-accountreserved' => 'This account name is reserved for use by the abuse filter.',
|
||||
|
@ -133,6 +133,7 @@ A brief description of the abuse rule which your action matched is: $1",
|
|||
'abusefilter-edit-action-degroup' => 'Remove the user from all privileged groups',
|
||||
'abusefilter-edit-action-block' => 'Block the user and/or IP address from editing',
|
||||
'abusefilter-edit-action-throttle' => 'Trigger actions only if the user trips a rate limit',
|
||||
'abusefilter-edit-action-rangeblock' => 'Block the /16 range from which the user originates.',
|
||||
'abusefilter-edit-throttle-count' => 'Number of actions to allow:',
|
||||
'abusefilter-edit-throttle-period' => 'Period of time:',
|
||||
'abusefilter-edit-throttle-seconds' => '$1 {{PLURAL:$1|second|seconds}}',
|
||||
|
@ -171,6 +172,7 @@ A brief description of the abuse rule which your action matched is: $1",
|
|||
'abusefilter-edit-builder-misc-ternary' => 'Ternary operator (1 ? 2 : 3)',
|
||||
'abusefilter-edit-builder-misc-in' => 'contained in string (in)',
|
||||
'abusefilter-edit-builder-misc-like' => 'Matches regex (like)',
|
||||
'abusefilter-edit-builder-misc-stringlit' => 'String literal ("")',
|
||||
'abusefilter-edit-builder-group-funcs' => 'Functions',
|
||||
'abusefilter-edit-builder-funcs-length' => 'String length (length)',
|
||||
'abusefilter-edit-builder-funcs-lcase' => 'To lower case (lcase)',
|
||||
|
|
|
@ -27,10 +27,10 @@ $wgExtensionCredits['other'][] = array(
|
|||
$wgExtensionMessagesFiles['AbuseFilter'] = "$dir/AbuseFilter.i18n.php";
|
||||
$wgExtensionAliasesFiles['AbuseFilter'] = "$dir/AbuseFilter.alias.php";
|
||||
|
||||
$wgAutoloadClasses[ 'AbuseFilter' ] = "$dir/AbuseFilter.class.php";
|
||||
$wgAutoloadClasses[ 'AbuseFilterParser' ] = "$dir/AbuseFilter.parser.php";
|
||||
$wgAutoloadClasses[ 'AbuseFilterParserNative' ] = "$dir/AbuseFilter.nativeparser.php";
|
||||
$wgAutoloadClasses[ 'AbuseFilterHooks' ] = "$dir/AbuseFilter.hooks.php";
|
||||
$wgAutoloadClasses['AbuseFilter'] = "$dir/AbuseFilter.class.php";
|
||||
$wgAutoloadClasses['AbuseFilterParser'] = "$dir/AbuseFilter.parser.php";
|
||||
$wgAutoloadClasses['AbuseFilterParserNative'] = "$dir/AbuseFilter.nativeparser.php";
|
||||
$wgAutoloadClasses['AbuseFilterHooks'] = "$dir/AbuseFilter.hooks.php";
|
||||
$wgAutoloadClasses['SpecialAbuseLog'] = "$dir/SpecialAbuseLog.php";
|
||||
$wgAutoloadClasses['SpecialAbuseFilter'] = "$dir/SpecialAbuseFilter.php";
|
||||
|
||||
|
@ -50,17 +50,18 @@ $wgAvailableRights[] = 'abusefilter-view';
|
|||
$wgAvailableRights[] = 'abusefilter-log';
|
||||
$wgAvailableRights[] = 'abusefilter-private';
|
||||
|
||||
$wgAbuseFilterAvailableActions = array( 'flag', 'throttle', 'warn', 'disallow', 'blockautopromote', 'block', 'degroup' );
|
||||
$wgAbuseFilterAvailableActions = array( 'flag', 'throttle', 'warn', 'disallow', 'blockautopromote', 'block', 'degroup', 'rangeblock' );
|
||||
|
||||
// Conditions take about 4ms to check, so 100 conditions would take 400ms
|
||||
$wgAbuseFilterConditionLimit = 1000;
|
||||
|
||||
// Disable filters if they match more than X edits, constituting more than Y% of the last Z edits
|
||||
$wgAbuseFilterEmergencyDisableThreshold = 0.05;
|
||||
$wgAbuseFilterEmergencyDisableCount = 5;
|
||||
// Disable filters if they match more than X edits, constituting more than Y% of the last Z edits, if they have been changed in the last S seconds
|
||||
$wgAbuseFilterEmergencyDisableThreshold = 0.50;
|
||||
$wgAbuseFilterEmergencyDisableCount = 2;
|
||||
$wgAbuseFilterEmergencyDisableAge = 86400; // One day.
|
||||
|
||||
// Abuse filter parser class
|
||||
$wgAbuseFilterParserClass = 'AbuseFilterParserNative';
|
||||
$wgAbuseFilterParserClass = 'AbuseFilterParser';
|
||||
$wgAbuseFilterNativeParser = "$dir/parser_native/af_parser";
|
||||
$wgAbuseFilterNativeSyntaxCheck = "$dir/parser_native/syntax_check";
|
||||
$wgAbuseFilterNativeExpressionEvaluator = "$dir/parser_native/af_expr";
|
||||
|
|
|
@ -397,7 +397,7 @@ class SpecialAbuseFilter extends SpecialPage {
|
|||
'op-arithmetic' => array('+' => 'addition', '-' => 'subtraction', '*' => 'multiplication', '/' => 'divide', '%' => 'modulo', '**' => 'pow'),
|
||||
'op-comparison' => array('==' => 'equal', '!=' => 'notequal', '<' => 'lt', '>' => 'gt', '<=' => 'lte', '>=' => 'gte'),
|
||||
'op-bool' => array( '!' => 'not', '&' => 'and', '|' => 'or', '^' => 'xor' ),
|
||||
'misc' => array( 'val1 ? iftrue : iffalse' => 'ternary', 'in' => 'in', 'like' => 'like' ),
|
||||
'misc' => array( 'val1 ? iftrue : iffalse' => 'ternary', 'in' => 'in', 'like' => 'like', '""' => 'stringlit', ),
|
||||
'funcs' => array( 'length(string)' => 'length', 'lcase(string)' => 'lcase', 'ccnorm(string)' => 'ccnorm', 'rmdoubles(string)' => 'rmdoubles', 'specialratio(string)' => 'specialratio', 'norm(string)' => 'norm', 'count(needle,haystack)' => 'count' ),
|
||||
'vars' => array( 'ACCOUNTNAME' => 'accountname', 'ACTION' => 'action', 'ADDED_LINES' => 'addedlines', 'EDIT_DELTA' => 'delta', 'EDIT_DIFF' => 'diff', 'NEW_SIZE' => 'newsize', 'OLD_SIZE' => 'oldsize', 'REMOVED_LINES' => 'removedlines', 'SUMMARY' => 'summary', 'ARTICLE_ARTICLEID' => 'article-id', 'ARTICLE_NAMESPACE' => 'article-ns', 'ARTICLE_TEXT' => 'article-text', 'ARTICLE_PREFIXEDTEXT' => 'article-prefixedtext', 'MOVED_FROM_ARTICLEID' => 'movedfrom-id', 'MOVED_FROM_NAMESPACE' => 'movedfrom-ns', 'MOVED_FROM_TEXT' => 'movedfrom-text', 'MOVED_FROM_PREFIXEDTEXT' => 'movedfrom-prefixedtext', 'MOVED_TO_ARTICLEID' => 'movedto-id', 'MOVED_TO_NAMESPACE' => 'movedto-ns', 'MOVED_TO_TEXT' => 'movedto-text', 'MOVED_TO_PREFIXEDTEXT' => 'movedto-prefixedtext', 'USER_EDITCOUNT' => 'user-editcount', 'USER_AGE' => 'user-age', 'USER_NAME' => 'user-name', 'USER_GROUPS' => 'user-groups', 'USER_EMAILCONFIRM' => 'user-emailconfirm'),
|
||||
);
|
||||
|
|
Loading…
Reference in a new issue