[wp-hackers] New Security Vulnerability?
Owen Winkler
ringmaster at midnightcircus.com
Thu Mar 9 20:26:03 GMT 2006
Denis de Bernardy wrote:
> +1. an advisory with proof of concept code to mass-produce users. how
> __evil__. at this rate, we'll soon see an advisory with proof of concept
> code to mass-produce comments. ;)
Along those lines, here's a proof of concept to mass block user
registrations from the same IP within 5 minutes. (It also blocks brute
force password cracks.)
The comment blocking thing is already done, I think. ;)
Owen
-------------- next part --------------
<?php
/*
Plugin Name: Armor
Plugin URI: http://redalt.com/wiki/Armor Plugin
Description: Add some security-related features to WP.
Author: Owen Winkler
Version: 0.1
Author URI: http://asymptomatic.net
*/
class Armor
{
function Armor()
{
load_plugin_textdomain('armor');
add_action('wp_authenticate', array(&$this, 'wp_authenticate'), 99999);
add_filter('validate_username', array(&$this, 'validate_username'), 99999, 2);
}
function login_delay($content)
{
$error = __('ERROR: Too many retries. Login disabled for 10 minutes.', 'armor');
$content = preg_replace('/<div id=\'login_error\'>(.*?)<\/div>/i', "<div id='login_error'>$error</div>", $content);
return $content;
}
function wp_authenticate(&$auth_user, &$auth_pass)
{
global $using_cookie, $error;
wp_cache_flush();
$index = $_SERVER['REMOTE_ADDR'];
$timeouts = get_settings('login_failure_timeouts');
if(isset($timeouts[$index])) {
if(time() < $timeouts[$index]) {
$auth_pass = '';
ob_start(array(&$this, 'login_delay'));
}
}
if (!wp_login($auth_user, $auth_pass, $using_cookie) ) {
// Login failed
$retries = get_settings('login_failure_retries');
if(isset($retries[$index])) {
$retries[$index] ++;
}
else {
$retries[$index] = 1;
}
if($retries[$index] > 3) {
$auth_pass = '';
$retries[$index] = 0;
$timeouts[$index] = time() + 600; // Ten minute timeout
ob_start(array(&$this, 'login_delay'));
$message = sprintf(__('3 failed login attempts from IP: %s', 'armor'), $_SERVER['REMOTE_ADDR']) . "\r\n\r\n";
$message .= sprintf(__('Last user attempted: %s.', 'armor'), $auth_user) . "\r\n\r\n";
$message .= __('IP was blocked for ten minutes.', 'armor') . "\r\n";
wp_mail(get_settings('admin_email'), sprintf(__('[%s] Excessive failed login attempts', 'armor'), get_settings('blogname')), $message);
//$this->debug(get_settings('admin_email'), sprintf(__('[%s] Excessive failed login attempts', 'armor'), get_settings('blogname')), $message);
}
update_option('login_failure_retries', $retries);
update_option('login_failure_timeouts', $timeouts);
}
}
function validate_username($valid, $username)
{
global $errors;
$minsbetweenregs = 5;
if($valid) {
$index = $_SERVER['REMOTE_ADDR'];
$regs = get_settings('registration_retries');
if(isset($regs[$index]) && ((time() - $regs[$index]) < $minsbetweenregs * 60 )) {
$errors['armor'] = sprintf(__('Only one registration is allowed per IP address per %s minutes.'), $minsbetweenregs);
}
$regs[$index] = time();
}
update_option('registration_retries', $regs);
return $valid;
}
function debug($foo)
{
$args = func_get_args();
echo "<pre style=\"background-color:#ffeeee;border:1px solid red;\">";
foreach($args as $arg1)
{
echo htmlentities(print_r($arg1, 1)) . "<br/>";
}
echo "</pre>";
}
}
$armor = new Armor();
?>
More information about the wp-hackers
mailing list