From d32fd7aa116ee016c6a1bda7979d3f396151013c Mon Sep 17 00:00:00 2001
From: Laurent Destailleur <eldy@destailleur.fr>
Date: Thu, 15 Dec 2016 10:25:06 +0100
Subject: [PATCH] FIX javascript xss injection and a translation

---
 .../install/mysql/data/llx_c_payment_term.sql |  2 +-
 htdocs/langs/en_US/bills.lang                 |  4 +-
 htdocs/main.inc.php                           |  4 +-
 test/phpunit/CoreTest.php                     | 54 +++++++++++++------
 4 files changed, 42 insertions(+), 22 deletions(-)

diff --git a/htdocs/install/mysql/data/llx_c_payment_term.sql b/htdocs/install/mysql/data/llx_c_payment_term.sql
index 68aae57ff4f..083c4419277 100644
--- a/htdocs/install/mysql/data/llx_c_payment_term.sql
+++ b/htdocs/install/mysql/data/llx_c_payment_term.sql
@@ -27,7 +27,7 @@
 -- de l'install et tous les sigles '--' sont supprimés.
 --
 
-insert into llx_c_payment_term(rowid, code, sortorder, active, libelle, libelle_facture, fdm, nbjour) values (1,'RECEP',       1,1, 'A réception de facture','Réception de facture',0,1);
+insert into llx_c_payment_term(rowid, code, sortorder, active, libelle, libelle_facture, fdm, nbjour) values (1,'RECEP',       1,1, 'Due Upon Receipt','Due Upon Receipt',0,1);
 insert into llx_c_payment_term(rowid, code, sortorder, active, libelle, libelle_facture, fdm, nbjour) values (2,'30D',         2,1, '30 jours','Réglement à 30 jours',0,30);
 insert into llx_c_payment_term(rowid, code, sortorder, active, libelle, libelle_facture, fdm, nbjour) values (3,'30DENDMONTH', 3,1, '30 jours fin de mois','Réglement à 30 jours fin de mois',1,30);
 insert into llx_c_payment_term(rowid, code, sortorder, active, libelle, libelle_facture, fdm, nbjour) values (4,'60D',         4,1, '60 jours','Réglement à 60 jours',0,60);
diff --git a/htdocs/langs/en_US/bills.lang b/htdocs/langs/en_US/bills.lang
index 65a93b573e3..9636b18d09c 100644
--- a/htdocs/langs/en_US/bills.lang
+++ b/htdocs/langs/en_US/bills.lang
@@ -329,8 +329,8 @@ GeneratedFromRecurringInvoice=Generated from template recurring invoice %s
 DateIsNotEnough=Date not reached yet
 InvoiceGeneratedFromTemplate=Invoice %s generated from recurring template invoice %s
 # PaymentConditions
-PaymentConditionShortRECEP=Immediate
-PaymentConditionRECEP=Immediate
+PaymentConditionShortRECEP=Due Upon Receipt
+PaymentConditionRECEP=Due Upon Receipt
 PaymentConditionShort30D=30 days
 PaymentCondition30D=30 days
 PaymentConditionShort30DENDMONTH=30 days of month-end
diff --git a/htdocs/main.inc.php b/htdocs/main.inc.php
index 5e83b1e6cf8..5105a8eef32 100644
--- a/htdocs/main.inc.php
+++ b/htdocs/main.inc.php
@@ -89,7 +89,6 @@ function test_sql_and_script_inject($val, $type)
         $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);
-        $sql_inj += preg_match('/onerror=/i', 	     $val);
     }
     // For XSS Injection done by adding javascript with script
     // This is all cases a browser consider text is javascript:
@@ -98,7 +97,8 @@ function test_sql_and_script_inject($val, $type)
     $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);       // onmouseover can be set on img or any html tag like <img title='>' onmouseover=alert(1)>
+    $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);
diff --git a/test/phpunit/CoreTest.php b/test/phpunit/CoreTest.php
index 01f06e41af7..3a158260e96 100644
--- a/test/phpunit/CoreTest.php
+++ b/test/phpunit/CoreTest.php
@@ -219,7 +219,7 @@ class CoreTest extends PHPUnit_Framework_TestCase
 
         print __METHOD__." DOL_MAIN_URL_ROOT=".DOL_MAIN_URL_ROOT."\n";
         print __METHOD__." DOL_URL_ROOT=".DOL_URL_ROOT."\n";
-        $this->assertEquals(DOL_URL_ROOT,$expectedresult);
+        $this->assertEquals($expectedresult, DOL_URL_ROOT);
 
         return true;
     }
@@ -245,7 +245,7 @@ class CoreTest extends PHPUnit_Framework_TestCase
         global $dolibarr_main_db_prefix;
 
 
-        // This is code copied from main.inc.php
+        // This is code copied from main.inc.php !!!!!!!!!!!!!!!
 
         /**
          * Security: SQL Injection and XSS Injection (scripts) protection (Filters on GET, POST, PHP_SELF).
@@ -258,14 +258,16 @@ class CoreTest extends PHPUnit_Framework_TestCase
         {
             $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('/(\.\.%2f)+/i', $val);
+            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:
@@ -273,22 +275,40 @@ class CoreTest extends PHPUnit_Framework_TestCase
             // 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/i', $val);
-            if ($type == 1) {
+            $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('/[\s;"]/', $val);	// PHP_SELF is an url and must match url syntax
+            if ($type == 2) $sql_inj += preg_match('/[;"]/', $val);		// PHP_SELF is a file system path. It can contains spaces.
             return $sql_inj;
         }
 
-        //type=2 key=0 value=/DIR WITH SPACE/htdocs/admin/index.php?mainmenu=home&leftmenu=setup&username=weservices
+        // Run tests
+        
         $_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);
+        $result=test_sql_and_script_inject($_SERVER["PHP_SELF"], 2);
+        $expectedresult=0;
+        $this->assertEquals($expectedresult, $result, 'Error on test_sql_and_script_inject 1a');
+        
+        $_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($result,$expectedresult);
+        $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');
     }
 }
-- 
GitLab