Mys 1.3.3 Anti Brute-Force Attack Mod

Forum
Last Post
Threads / Messages

pachoofoosh

Artist
Member
Joined
Dec 10, 2012
Messages
99
Points
6
Location
New York
Mysidian Dollar
10,255
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:
<?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/", FALSE, FALSE);
		    $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->subtitle, TRUE, "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:
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 <= 4 ) { // Equal to or less than 4 login attempts..
                          $delay_time = 0;
                      }
                      elseif( $attempts == 5 ) { // Five login attempts...
                          $delay_time = 2;
                      }
                      elseif( $attempts >= 6 ) { // 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:
<?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:
8wh4qo.png


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:
Whether it has ever been a problem or not, I don't think there can ever be enough security measures. php is so easy to crack and hack. Thanks for this mod!
 
Hall of Famer: Thanks! I hope so as well, you can never be safe enough with php. ^^

Nemesis: Thanks! c: I'm not really sure. cx Haha I tend to be rather paranoid when it comes to php, especially with anything that involves user input. Either way, brute-force attacks are vital to have prevention mechanisms for.

Kesstryl: Thank you! That is very true. uwu Hope you find this mod useful! :usedusedused:
 

Similar threads

Users who are viewing this thread

  • Forum Contains New Posts
  • Forum Contains No New Posts

Forum statistics

Threads
4,277
Messages
33,118
Members
1,602
Latest member
BerrieMilk
BETA

Latest Threads

Latest Posts

Top