route : ratelimit the errors to not allow the hackers to brute force the backend

git-svn-id: https://svn.fournier38.fr/svn/ProgSVN/trunk@2543 bf3deb0d-5f1a-0410-827f-c0cc1f45334c
This commit is contained in:
2016-02-23 12:35:08 +00:00
parent 9dbd64d6a2
commit 188ed7cd96
2 changed files with 54 additions and 10 deletions

View File

@@ -320,4 +320,22 @@ class test_route extends PHPUnit_Framework_TestCase
echo $route->requestURL ();
$this->expectOutputString("var=1");
}
/** Ratelimiting in errors */
public function test_errorRateLimit1 ()
{
$route = new route ();
$route->error (new \Exception ("test1", 500));
$route->error (new \Exception ("test2", 500));
$route->error (new \Exception ("test3", 500));
$route->error (new \Exception ("test4", 500));
$route->error (new \Exception ("test5", 500));
$route->error (new \Exception ("test6", 500));
$route->error (new \Exception ("test7", 500));
$route->error (new \Exception ("test8", 500));
$route->error (new \Exception ("test9", 500));
$route->error (new \Exception ("test0", 500));
$route->error (new \Exception ("test11", 500));
$this->expectOutputRegex("#Too much error requests#");
}
}

View File

@@ -4,6 +4,7 @@
@author Dominique Fournier <dominique@fournier38.fr> */
require_once ("domframework/http.php");
require_once ("domframework/ratelimitfile.php");
/** The routing module, base of the DomFramework */
class route
@@ -32,6 +33,9 @@ class route
just display a "Unauthorized" message */
public $authenticationURL = null;
// Ratelimit the errors in route.php to not allow the hackers to brute force
// the backend. The objct can be put to null to disable the feature
public $ratelimiter = null;
/// RENDERER PART ///
/** Output type to no previous catched renderer (allow : json, xml, txt html)
@@ -50,6 +54,12 @@ class route
/** Array to variable definition */
public $variable = array ();
/** The route constructor : initialize the parameters */
function __construct ()
{
$this->ratelimiter = new ratelimitfile ();
}
/** Return the baseURL of the site
Always finish with a slash
@param string|null $module The module name (if thereis one) */
@@ -485,6 +495,21 @@ class route
/** Print an error page. If a custom page exists, use it
@param $e Exception to print */
public function error ($e)
{
$ipClient = null;
if (isset ($_SERVER["HTTP_X_FORWARDED_FOR"]))
$ipClient = $_SERVER["HTTP_X_FORWARDED_FOR"];
elseif (isset ($_SERVER["REMOTE_ADDR"]))
$ipClient = $_SERVER["REMOTE_ADDR"];
elseif (defined ("PHPUNIT"))
$ipClient = "CLI";
if ($this->ratelimiter !== null && $ipClient !== null &&
$this->ratelimiter->set ("error-$ipClient") === false)
{
$getCode = 406;
$message = dgettext("domframework", "Too much error requests");
}
else
{
if ($e->getCode () === "" || $e->getCode () === 0)
$getCode = 500;
@@ -494,6 +519,7 @@ class route
$message = $e->getMessage ();
if ($e->getCode () === 0)
$message .= "<p>The Exception code was 0 and converted to 500</p>\n";
}
// If an error class/method is defined, use it in place of the default
// one.
@@ -508,7 +534,7 @@ class route
$a = new $this->errors[0];
$method = $this->errors[1];
$a->$method ($getCode, $message);
exit;
return true;
}
if ($this->authenticationURL !== null && $getCode === 401)
@@ -543,11 +569,11 @@ class route
"{baseurlmodule}"=>$this->baseURLmodule()));
$renderer->variable = $this->variable;
$renderer->run ();
exit;
return true;
$class = "output".$this->output;
require_once ("$class.php");
$output = new $class ();
$output->out ($message, $http->codetext ($getCode));
exit;
return true;
}
}