Thread: Mys 1.3.3 Anti Brute-Force Attack Mod
View Single Post
  #1  
Old 08-06-2013, 03:55 PM
pachoofoosh's Avatar
pachoofoosh pachoofoosh is offline
Artist
 
Join Date: Dec 2012
Location: New York
Posts: 98
Gender: Unknown/Other
Credits: 15,535
pachoofoosh is on a distinguished road
Default Anti Brute-Force Attack Mod

A simple way to help stop brute-force attacks, taking advantage of PHP's sleep() function.

This mod automatically records login attempts to the database. If an IP has 5 or more login attempts, the script will start delaying for them, slowing the attack to a crawl. On successful login, all of the IP's login attempts are cleared.

How to 'install'


Step 1.) Open up classes/class_sidebar.php. Replace its contents with the following:
PHP Code:
<?php

/**
 * The Sidebar Class, defines a standard HTML Sidebar component.
 * It extends from the Widget class, while adding its own implementation.
 * @category Resource
 * @package Widget
 * @author Hall of Famer 
 * @copyright Mysidia Adoptables Script
 * @link http://www.mysidiaadoptables.com
 * @since 1.3.3
 * @todo Not much at this point.
 *
 */

class Sidebar extends Widget{

    
/**
     * The moneyBar property, specifies the money/donation bar for members.
     * @access protected
     * @var Paragraph
    */
    
protected $moneyBar;
    
    
/**
     * The linksBar property, stores all useful links for members.
     * @access protected
     * @var Paragraph
    */
    
protected $linksBar;
    
    
/**
     * The wolBar property, determines the who's online url in the sidebar.
     * @access protected
     * @var Link
    */
    
protected $wolBar;
    
    
/**
     * The loginBar property, specifies the loginBar for guests.
     * @access protected
     * @var FormBuilder
    */
    
protected $loginBar;

    
/**
     * Constructor of Sidebar Class, it initializes basic sidebar properties     
     * @access public
     * @return Void
     */
    
public function __construct(){
        
$mysidia Registry::get("mysidia");
        
$userLevel = ($mysidia->user->isloggedin)?"member":"visitor";
        
$stmt $mysidia->db->select("modules", array(), "widget = 'sidebar' and (userlevel = '{$userLevel}' or userlevel = 'user') and status = 'enabled' ORDER BY `order`");
        
        while(
$module $stmt->fetchObject()){
            
$method "set{$module->name}";
            if(
$this->hasMethod($method)) $this->$method();
            else 
$this->setModule($module);     
        }
    }
    
    
/**
     * The setDivision method, setter method for property $division.
     * It is set internally upon object instantiation, cannot be accessed in client code.
     * @param GUIComponent  $module
     * @access protected
     * @return Void
     */
    
protected function setDivision(GUIComponent $module){
        if(!
$this->division){
            
$this->division = new Division;
            
$this->division->setClass("sidebar");
        }    
        
$this->division->add($module);
    }
    
    
/**
     * The getMoneyBar method, getter method for property $moneyBar.
     * @access public
     * @return Paragraph
     */
    
public function getMoneyBar(){
        return 
$this->moneyBar;
    }
    
    
/**
     * The setMoneyBar method, setter method for property $moneyBar.
     * It is set internally upon object instantiation, cannot be accessed in client code.
     * @access protected
     * @return Void
     */
    
protected function setMoneyBar(){
        
$mysidia Registry::get("mysidia");
        
$this->moneyBar = new Paragraph;
        
$this->moneyBar->add(new Comment("You have {$mysidia->user->money} {$mysidia->user->cost}."));
        
        
$donate = new Link("donate");
        
$donate->setText("Donate Money to Friends");
        
$this->moneyBar->add($donate);
        
$this->setDivision($this->moneyBar);        
    }

    
/**
     * The getLinksBar method, getter method for property $linksBar.
     * @access public
     * @return Paragraph
     */
    
public function getLinksBar(){
        return 
$this->linksBar;
    }
    
    
/**
     * The setLinksBar method, setter method for property $linksBar.
     * It is set internally upon object instantiation, cannot be accessed in client code.
     * @access protected
     * @return Void
     */
    
protected function setLinksBar(){
        
$mysidia Registry::get("mysidia");
        
$this->linksBar = new Paragraph;
        
$linkTitle = new Comment("My Links:");
        
$linkTitle->setBold();
        
$this->linksBar->add($linkTitle);
        
        
$linksList = new LinksList("ul");
        
$this->setLinks($linksList);
        
        
$this->linksBar->add($linksList);
        
$this->setDivision($this->linksBar);    
    }

    
/**
     * The setLinks method, append all links to the LinksBar.
     * It is set internally upon object instantiation, cannot be accessed in client code.
     * @access protected
     * @return Void
     */
    
protected function setLinks(LinksList $linksList){
        
$mysidia Registry::get("mysidia");
        
$stmt $mysidia->db->select("links", array("id""linktext""linkurl"), "linktype = 'sidelink' ORDER BY linkorder");
        if(
$stmt->rowCount() == 0) Throw new Exception("There is an error with sidebar links, please contact the admin immediately for help.");
        
        while(
$sideLink $stmt->fetchObject()){
            
$link = new Link($sideLink->linkurl);
            
$link->setText($sideLink->linktext);
            if(
$sideLink->linkurl == "messages"){
                
$num $mysidia->db->select("messages", array("touser"), "touser='{$mysidia->user->username}' and status='unread'")->rowCount();
                if(
$num 0$link->setText("{$link->getText()} ({$num})");
            }
            
$link->setListed(TRUE);
            
$linksList->add($link);   
        }
        
        if(
$mysidia->user instanceof Admin){
            
$adminCP = new Link("admincp/"FALSEFALSE);
            
$adminCP->setText("Admin Control Panel");
            
$adminCP->setListed(TRUE);  
            
$linksList->add($adminCP);            
        }
    }
    
    
/**
     * The getWolBar method, getter method for property $wolBar.
     * @access public
     * @return LinksList
     */
    
public function getWolBar(){
        return 
$this->wolBar;
    }
    
    
/**
     * The setWolBar method, setter method for property $wolBar.
     * It is set internally upon object instantiation, cannot be accessed in client code.
     * @access protected
     * @return Void
     */
    
protected function setWolBar(){
        
$mysidia Registry::get("mysidia");
        
$this->wolBar = new Link("online");
        
$online $mysidia->db->select("online", array(), "username != 'Visitor'")->rowCount();
        
$offline $mysidia->db->select("online", array(), "username = 'Visitor'")->rowCount();
        
$this->wolBar->setText("There are {$online} users and {$offline} guests online.");
        
$this->setDivision($this->wolBar);
                
    }
    
    
/**
     * The getLoginBar method, getter method for property $loginBar.
     * @access public
     * @return FormBuilder
     */
    
public function getLoginBar(){
        return 
$this->loginBar;
    }
    
    
/**
     * The setLoginBar method, setter method for property $loginBar.
     * It is set internally upon object instantiation, cannot be accessed in client code.
     * @access protected
     * @return Void
     */
    
protected function setLoginBar(){
      
      include (
'/functions/functions.php');
      
        
$this->loginBar = new FormBuilder("login""login""post");
        
$loginTitle = new Comment("Member Login:");
        
$loginTitle->setBold();
        
$loginTitle->setUnderlined();
        
$this->loginBar->add($loginTitle);

        
$this->loginBar->buildComment("<label for='username'>username:</label><br /> "FALSE)
                       ->
buildTextField("username")
                       ->
buildComment("<label for='password'>password:</label><br /> "FALSE)
                       ->
buildPasswordField("password""password"""TRUE)    
                       ->
buildButton("Log In""submit""submit")
                       ->
buildComment("Don't have an account?"); 
                       
        
$register = new Link("register");
        
$register->setText("Register new Account");
        
$register->setLineBreak(TRUE);
        
$forgot = new Link("forgotpass");
        
$forgot->setText("Forgot password?");
        
        
$this->loginBar->add($register);
        
$this->loginBar->add($forgot);
        
$this->setDivision($this->loginBar);     
    }

    public function 
setModule($module){
        
$mysidia Registry::get("mysidia");
        
$moduleContainer = new Paragraph();
        if(
$module->subtitle$moduleContainer->add(new Comment($module->subtitleTRUE"b"));
        if(
$module->php) eval($module->php);
        if(
$module->html$moduleContainer->add(new Comment($module->html));
        
$this->setDivision($moduleContainer);     
    }
    
    
/**
     * The render method for Sidebar class, it renders the division component and thus all subcomponents.
     * @access public
     * @return String
     */    
    
public function render(){
        return 
$this->division->render();
    }
}
?>
Step 2.) Open up functions/functions.php. Now let's create the anti brute-force function, logAttempt(). Paste the following into the bottom of the file, just above the ending PHP tag (?>):
PHP Code:
function logAttempt() {

                    
$mysidia Registry::get("mysidia");
                    
$ip $_SERVER['REMOTE_ADDR']; 
                    
$query $mysidia->db->select("login_attempts", array("num_attempts"), "ip = '$ip'")->rowCount();
                    
$attempts $query 1;
                    
                    
$stmt $mysidia->db->insert("login_attempts", array("num_attempts" => "$attempts""ip" => "$ip"));
                      if( 
$attempts <= ) { // Equal to or less than 4 login attempts..
                          
$delay_time 0;
                      }
                      elseif( 
$attempts == ) { // Five login attempts...
                          
$delay_time 2;
                      }
                      elseif( 
$attempts >= ) { // Greater than or equal to 6 login attempts...
                          
$delay_time 5;
                      }
                    return 
sleep($delay_time); 
// End logAttempt function. 
Step 3.) We're almost finished; halfway there. c; Open up login.php. Replace its contents with the following:
PHP Code:
<?php

class LoginController extends AppController{

    private 
$view;
    private 
$subController;

    public function 
__construct(){
        
parent::__construct();
    }
    
    public function 
index(){
        
$this->flag "guest";
        
$this->handleAccess();
        
$mysidia Registry::get("mysidia");
        
$document $mysidia->frame->getDocument();

        if(
$mysidia->input->post("submit")){
            if(!
$mysidia->input->post("username") or !$mysidia->input->post("password")){
                
$document->setTitle($mysidia->lang->fail_title);
                
$document->addLangvar($mysidia->lang->fail_blank);    
            }
            else{
                
$validator = new UserValidator($mysidia->user, array("username" => $mysidia->input->post("username"), "password" => $mysidia->input->post("password")));
                
$validator->validate("username");
                
$validator->validate("password");
                
                if(!
$validator->triggererror()){
                    
// Validation succeeded, now begins the actual login procedure
         
                    
$document->setTitle($mysidia->lang->success_title);
                    
$document->addLangvar("Welcome back, {$mysidia->input->post("username")}{$mysidia->lang->success}");
                    
$ip $_SERVER['REMOTE_ADDR']; // Delete the user's previous login attempts.
                    
$mysidia->db->delete("login_attempts""ip = '$ip'");
         
                    
$mysidia->user->login($mysidia->input->post("username"));
                    if(
$mybbenabled == 1$mysidia->user->loginforum();
                    
$mysidia->session->terminate("clientip");
                }
                else{ 
                           
                    
$document->setTitle($mysidia->lang->fail_title);
                    
$document->addLangvar($mysidia->lang->fail_details);
                        
logAttempt();
                        
$mysidia->cookies->logincookies();
                            
                            
                }
            }
            return;
        }
        
        
$mysidia->session->assign("clientip"$_SERVER['REMOTE_ADDR']);
            
$document->setTitle($mysidia->lang->title);
        
$document->addLangvar($mysidia->lang->login);
                  
        
$loginForm $mysidia->frame->getSidebar()->getLoginBar();
        
$document->add($loginForm);    
    }
    
    public function 
logout(){
        
$this->flag "member";
        
$this->handleAccess();
        
$mysidia Registry::get("mysidia");
        
$document $mysidia->frame->getDocument();

        
$mysidia->user->logout();          
        
$document->setTitle($mysidia->lang->logout_title);
        
$document->addLangvar($mysidia->lang->logout);    
    }
}
?>
Step 4.) And finally, let's create the login_attempts table. uwu Open up PHPMyAdmin and click on the database you're going to use. Next, click the button that says '(+) New table' (At the bottom of the frame on the left side of the screen which displays all of the DB's tables).

For the criteria, it should look something like this:


And with that, everything is finished! :D If you come across any errors while using this Mod, I'll be happy to help fix it. Hope you guys will find good use of it! c:

Last edited by pachoofoosh; 09-25-2013 at 04:37 PM.
Reply With Quote