NEW Enhance the anti XSS filter

This commit is contained in:
Laurent Destailleur 2017-09-07 13:50:16 +02:00
parent cff9ff01c8
commit a9e44a2cf5
2 changed files with 141 additions and 54 deletions

View File

@ -94,18 +94,23 @@ function test_sql_and_script_inject($val, $type)
// This is all cases a browser consider text is javascript:
// When it found '<script', 'javascript:', '<style', 'onload\s=' on body tag, '="&' on a tag size with old browsers
// All examples on page: http://ha.ckers.org/xss.html#XSScalc
// More on https://www.owasp.org/index.php/XSS_Filter_Evasion_Cheat_Sheet
$inj += preg_match('/<script/i', $val);
$inj += preg_match('/<iframe/i', $val);
$inj += preg_match('/Set\.constructor/i', $val); // ECMA script 6
if (! defined('NOSTYLECHECK')) $inj += preg_match('/<style/i', $val);
$inj += preg_match('/base[\s]+href/si', $val);
$inj += preg_match('/<.*onmouse/si', $val); // onmousexxx can be set on img or any html tag like <img title='...' onmouseover=alert(1)>
$inj += preg_match('/onerror\s*=/i', $val); // onerror can be set on img or any html tag like <img title='...' onerror = alert(1)>
$inj += preg_match('/onfocus\s*=/i', $val); // onfocus can be set on input text html tag like <input type='text' value='...' onfocus = alert(1)>
$inj += preg_match('/onload\s*=/i', $val); // onload can be set on input text html tag like <input type='text' value='...' onfocus = alert(1)>
if ($type == 1)
{
$inj += preg_match('/onload\s*=/i', $val); // onload can be set on svg tag <svg/onload=alert(1)> or other tag like body <body onload=alert(1)>
//$inj += preg_match('/on[A-Z][a-z]+\*=/', $val); // To lock event handlers onAbort(), ...
$inj += preg_match('/&#58;|&#0000058|&#x3A/i', $val); // refused string ':' encoded (no reason to have it encoded) to lock 'javascript:...'
//if ($type == 1)
//{
$inj += preg_match('/javascript:/i', $val);
$inj += preg_match('/vbscript:/i', $val);
}
//}
// For XSS Injection done by adding javascript closing html tags like with onmousemove, etc... (closing a src or href tag with not cleaned param)
if ($type == 1) $inj += preg_match('/"/i', $val); // We refused " in GET parameters value
if ($type == 2) $inj += preg_match('/[;"]/', $val); // PHP_SELF is a file system path. It can contains spaces.

View File

@ -137,7 +137,7 @@ class CoreTest extends PHPUnit_Framework_TestCase
global $dolibarr_main_db_type;
global $dolibarr_main_db_prefix;
$testtodo=3;
$testtodo=0;
// Case 1:
// Test for subdir dolibarrnew (that point to htdocs) in root directory /var/www
@ -217,9 +217,12 @@ class CoreTest extends PHPUnit_Framework_TestCase
// Force to rerun filefunc.inc.php
include dirname(__FILE__).'/../../htdocs/filefunc.inc.php';
print __METHOD__." DOL_MAIN_URL_ROOT=".DOL_MAIN_URL_ROOT."\n";
print __METHOD__." DOL_URL_ROOT=".DOL_URL_ROOT."\n";
$this->assertEquals($expectedresult, DOL_URL_ROOT);
if ($testtodo != 0)
{
print __METHOD__." DOL_MAIN_URL_ROOT=".DOL_MAIN_URL_ROOT."\n";
print __METHOD__." DOL_URL_ROOT=".DOL_URL_ROOT."\n";
$this->assertEquals($expectedresult, DOL_URL_ROOT);
}
return true;
}
@ -256,59 +259,138 @@ class CoreTest extends PHPUnit_Framework_TestCase
*/
function test_sql_and_script_inject($val, $type)
{
$sql_inj = 0;
// For SQL Injection (only GET and POST are used to be included into bad escaped SQL requests)
if ($type != 2)
{
$sql_inj += preg_match('/delete\s+from/i', $val);
$sql_inj += preg_match('/create\s+table/i', $val);
$sql_inj += preg_match('/update.+set.+=/i', $val);
$sql_inj += preg_match('/insert\s+into/i', $val);
$sql_inj += preg_match('/select.+from/i', $val);
$sql_inj += preg_match('/union.+select/i', $val);
$sql_inj += preg_match('/into\s+(outfile|dumpfile)/i', $val);
$sql_inj += preg_match('/(\.\.%2f)+/i', $val);
}
// For XSS Injection done by adding javascript with script
// This is all cases a browser consider text is javascript:
// When it found '<script', 'javascript:', '<style', 'onload\s=' on body tag, '="&' on a tag size with old browsers
// All examples on page: http://ha.ckers.org/xss.html#XSScalc
$sql_inj += preg_match('/<script/i', $val);
if (! defined('NOSTYLECHECK')) $sql_inj += preg_match('/<style/i', $val);
$sql_inj += preg_match('/base[\s]+href/si', $val);
$sql_inj += preg_match('/<.*onmouse/si', $val); // onmousexxx can be set on img or any html tag like <img title='>' onmouseover=alert(1)>
$sql_inj += preg_match('/onerror\s*=/i', $val); // onerror can be set on img or any html tag like <img title='>' onerror = alert(1)>
if ($type == 1)
{
$sql_inj += preg_match('/javascript:/i', $val);
$sql_inj += preg_match('/vbscript:/i', $val);
}
// For XSS Injection done by adding javascript closing html tags like with onmousemove, etc... (closing a src or href tag with not cleaned param)
if ($type == 1) $sql_inj += preg_match('/"/i', $val); // We refused " in GET parameters value
if ($type == 2) $sql_inj += preg_match('/[;"]/', $val); // PHP_SELF is a file system path. It can contains spaces.
return $sql_inj;
$inj = 0;
// For SQL Injection (only GET and POST are used to be included into bad escaped SQL requests)
if ($type != 2)
{
$inj += preg_match('/delete\s+from/i', $val);
$inj += preg_match('/create\s+table/i', $val);
$inj += preg_match('/update.+set.+=/i', $val);
$inj += preg_match('/insert\s+into/i', $val);
$inj += preg_match('/select.+from/i', $val);
$inj += preg_match('/union.+select/i', $val);
$inj += preg_match('/into\s+(outfile|dumpfile)/i', $val);
$inj += preg_match('/(\.\.%2f)+/i', $val);
}
// For XSS Injection done by adding javascript with script
// This is all cases a browser consider text is javascript:
// When it found '<script', 'javascript:', '<style', 'onload\s=' on body tag, '="&' on a tag size with old browsers
// All examples on page: http://ha.ckers.org/xss.html#XSScalc
// More on https://www.owasp.org/index.php/XSS_Filter_Evasion_Cheat_Sheet
$inj += preg_match('/<script/i', $val);
$inj += preg_match('/<iframe/i', $val);
$inj += preg_match('/Set\.constructor/i', $val); // ECMA script 6
if (! defined('NOSTYLECHECK')) $inj += preg_match('/<style/i', $val);
$inj += preg_match('/base[\s]+href/si', $val);
$inj += preg_match('/<.*onmouse/si', $val); // onmousexxx can be set on img or any html tag like <img title='...' onmouseover=alert(1)>
$inj += preg_match('/onerror\s*=/i', $val); // onerror can be set on img or any html tag like <img title='...' onerror = alert(1)>
$inj += preg_match('/onfocus\s*=/i', $val); // onfocus can be set on input text html tag like <input type='text' value='...' onfocus = alert(1)>
$inj += preg_match('/onload\s*=/i', $val); // onload can be set on svg tag <svg/onload=alert(1)> or other tag like body <body onload=alert(1)>
//$inj += preg_match('/on[A-Z][a-z]+\*=/', $val); // To lock event handlers onAbort(), ...
$inj += preg_match('/&#58;|&#0000058|&#x3A/i', $val); // refused string ':' encoded (no reason to have it encoded) to lock 'javascript:...'
//if ($type == 1)
//{
$inj += preg_match('/javascript:/i', $val);
$inj += preg_match('/vbscript:/i', $val);
//}
// For XSS Injection done by adding javascript closing html tags like with onmousemove, etc... (closing a src or href tag with not cleaned param)
if ($type == 1) $inj += preg_match('/"/i', $val); // We refused " in GET parameters value
if ($type == 2) $inj += preg_match('/[;"]/', $val); // PHP_SELF is a file system path. It can contains spaces.
return $inj;
}
// Run tests
// More on https://www.owasp.org/index.php/XSS_Filter_Evasion_Cheat_Sheet
// Should be OK
$expectedresult=0;
$_SERVER["PHP_SELF"]='/DIR WITH SPACE/htdocs/admin/index.php?mainmenu=home&leftmenu=setup&username=weservices';
$result=test_sql_and_script_inject($_SERVER["PHP_SELF"], 2);
$expectedresult=0;
$this->assertEquals($expectedresult, $result, 'Error on test_sql_and_script_inject 1a');
// Should detect XSS
$expectedresult=1;
$_SERVER["PHP_SELF"]='/DIR WITH SPACE/htdocs/admin/index.php?mainmenu=home&leftmenu=setup&username=weservices;badaction';
$result=test_sql_and_script_inject($_SERVER["PHP_SELF"], 2);
$expectedresult=1;
$this->assertEquals($expectedresult, $result, 'Error on test_sql_and_script_inject 1b');
$_GET['aaa']="<img src='1.jpg' onerror =javascript:alert('XSS')>";
$result=test_sql_and_script_inject($_GET['aaa'], 0);
$expectedresult=1;
$this->assertEquals($expectedresult, $result, 'Error on test_sql_and_script_inject 2');
$_POST['bbb']="<img src='1.jpg' onerror =javascript:alert('XSS')>";
$result=test_sql_and_script_inject($_POST['bbb'], 2);
$expectedresult=1;
$this->assertEquals($expectedresult, $result, 'Error on test_sql_and_script_inject 3');
$this->assertGreaterThanOrEqual($expectedresult, $result, 'Error on test_sql_and_script_inject 1b');
$test="<img src='1.jpg' onerror =javascript:alert('XSS')>";
$result=test_sql_and_script_inject($test, 0);
$this->assertGreaterThanOrEqual($expectedresult, $result, 'Error on test_sql_and_script_inject aaa');
$test="<img src='1.jpg' onerror =javascript:alert('XSS')>";
$result=test_sql_and_script_inject($test, 2);
$this->assertGreaterThanOrEqual($expectedresult, $result, 'Error on test_sql_and_script_inject aaa2');
$test='<IMG SRC=# onmouseover="alert(1)">';
$result=test_sql_and_script_inject($test, 0);
$this->assertGreaterThanOrEqual($expectedresult, $result, 'Error on test_sql_and_script_inject aaa3');
$test='<IMG SRC onmouseover="alert(1)">';
$result=test_sql_and_script_inject($test, 0);
$this->assertGreaterThanOrEqual($expectedresult, $result, 'Error on test_sql_and_script_inject aaa4');
$test='<IMG onmouseover="alert(1)">';
$result=test_sql_and_script_inject($test, 0);
$this->assertGreaterThanOrEqual($expectedresult, $result, 'Error on test_sql_and_script_inject aaa5');
$test='<IMG SRC=/ onerror="alert(1)">';
$result=test_sql_and_script_inject($test, 0);
$this->assertGreaterThanOrEqual($expectedresult, $result, 'Error on test_sql_and_script_inject aaa6');
$test='<IMG SRC=" &#14; javascript:alert(1);">';
$result=test_sql_and_script_inject($test, 0);
$this->assertGreaterThanOrEqual($expectedresult, $result, 'Error on test_sql_and_script_inject aaa7');
$test='<IMG SRC=&#106;&#97;&#118;&#97;&#115;&#99;&#114;&#105;&#112;&#116;&#58;&#97;&#108;&#101;&#114;&#116;&#40;&#39;&#88;&#83;&#83;&#39;&#41;>';
$result=test_sql_and_script_inject($test, 0);
$this->assertGreaterThanOrEqual($expectedresult, $result, 'Error on test_sql_and_script_inject bbb');
$test='<SCRIPT SRC=http://xss.rocks/xss.js></SCRIPT>';
$result=test_sql_and_script_inject($test, 0);
$this->assertGreaterThanOrEqual($expectedresult, $result, 'Error on test_sql_and_script_inject ccc');
$test='<IMG SRC="javascript:alert(\'XSS\');">';
$result=test_sql_and_script_inject($test, 1);
$this->assertGreaterThanOrEqual($expectedresult, $result, 'Error on test_sql_and_script_inject ddd');
$test='<IMG """><SCRIPT>alert("XSS")</SCRIPT>">';
$result=test_sql_and_script_inject($test, 0);
$this->assertGreaterThanOrEqual($expectedresult, $result, 'Error on test_sql_and_script_inject eee');
$test='<!-- Google analytics -->
<script>
(function(i,s,o,g,r,a,m){i[\'GoogleAnalyticsObject\']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,\'script\',\'https://www.google-analytics.com/analytics.js\',\'ga\');
ga(\'create\',\'UA-99999999-9\', \'auto\');
ga(\'send\', \'pageview\');
</script>';
$result=test_sql_and_script_inject($test, 0);
$this->assertGreaterThanOrEqual($expectedresult, $result, 'Error on test_sql_and_script_inject eee');
$test="<IMG SRC=\"jav\tascript:alert('XSS');\">"; // Is locked by some brwoser like chrome because the default directive no-referrer-when-downgrade is sent when requesting the SRC and then refused because of browser protection on img src load without referrer.
$test="<IMG SRC=\"jav&#x0D;ascript:alert('XSS');\">"; // Same
$test='<SCRIPT/XSS SRC="http://xss.rocks/xss.js"></SCRIPT>';
$result=test_sql_and_script_inject($test, 0);
$this->assertGreaterThanOrEqual($expectedresult, $result, 'Error on test_sql_and_script_inject fff1');
$test='<SCRIPT/SRC="http://xss.rocks/xss.js"></SCRIPT>';
$result=test_sql_and_script_inject($test, 0);
$this->assertGreaterThanOrEqual($expectedresult, $result, 'Error on test_sql_and_script_inject fff2');
// This case seems to be filtered by browsers now.
$test='<BODY onload!#$%&()*~+-_.,:;?@[/|\]^`=alert(1)>';
//$result=test_sql_and_script_inject($test, 0);
//$this->assertGreaterThanOrEqual($expectedresult, $result, 'Error on test_sql_and_script_inject ggg');
$test='<iframe src=http://xss.rocks/scriptlet.html <';
$result=test_sql_and_script_inject($test, 0);
$this->assertGreaterThanOrEqual($expectedresult, $result, 'Error on test_sql_and_script_inject hhh');
$test='Set.constructor`alert\x281\x29```';
$result=test_sql_and_script_inject($test, 0);
$this->assertGreaterThanOrEqual($expectedresult, $result, 'Error on test_sql_and_script_inject iii');
}
}