source: branches/1.2/workflow/inc/class.utils.security.php @ 1349

Revision 1349, 8.9 KB checked in by niltonneto, 15 years ago (diff)

Ticket #561 - Inclusão do módulo Workflow faltante nessa versão.

  • Property svn:executable set to *
Line 
1<?php
2require_once('class.utils.php');
3 /**
4  * Filters input of stray or malicious PHP, Javascript or HTML tags.
5  * It can be used to prevent cross-site scripting (XSS) attacks.
6  * It should be used to filter input supplied by the user, such as an HTML code
7  * entered in form fields. You would create the filter object, configure it with your
8  * own settings, then call its process method to clean the form input values.
9  *
10  * @author: Daniel Morris
11  * @version: 1.2.2_php4/php5
12  * @package Workflow
13  * @license http://www.gnu.org/copyleft/gpl.html GPL
14  */
15class SecurityUtils extends Utils {
16
17        /**
18         * @var array $tagsArray default = empty array
19         * @access public
20         */
21        var $tagsArray;
22
23        /**
24         * @var array $attrArray  default = empty array
25         * @access public
26         */
27        var $attrArray;
28
29        /**
30         * @var $tagsMethod  default = 0
31         * @access public
32         */
33        var $tagsMethod;
34
35        /**
36         * @var $attrMethod  default = 0
37         * @access public
38         */
39        var $attrMethod;
40
41        /**
42         * @var $xssAuto  default = 1
43         * @access public
44         */
45        var $xssAuto;
46
47        /**
48         * @var array $tagBlacklist
49         * @access public
50         */
51        var $tagBlacklist = array('applet', 'body', 'bgsound', 'base', 'basefont', 'embed', 'frame', 'frameset', 'head', 'html', 'id', 'iframe', 'ilayer', 'layer', 'link', 'meta', 'name', 'object', 'script', 'style', 'title', 'xml');
52
53        /**
54         * @var array $attrBlackList
55         * @access public
56         */
57        var $attrBlacklist = array('action', 'background', 'codebase', 'dynsrc', 'lowsrc');  // also will strip ALL event handlers
58
59        /**
60          * Constructor for inputFilter class. Only first parameter is required.
61          * @access constructor
62          * @param Array $tagsArray - list of user-defined tags
63          * @param Array $attrArray - list of user-defined attributes
64          * @param int $tagsMethod - 0= allow just user-defined, 1= allow all but user-defined
65          * @param int $attrMethod - 0= allow just user-defined, 1= allow all but user-defined
66          * @param int $xssAuto - 0= only auto clean essentials, 1= allow clean blacklisted tags/attr
67          */
68        function SecurityUtils($tagsArray = array(), $attrArray = array(), $tagsMethod = 0, $attrMethod = 0, $xssAuto = 1) {
69                // make sure user defined arrays are in lowercase
70                for ($i = 0; $i < count($tagsArray); $i++) $tagsArray[$i] = strtolower($tagsArray[$i]);
71                for ($i = 0; $i < count($attrArray); $i++) $attrArray[$i] = strtolower($attrArray[$i]);
72                // assign to member vars
73                $this->tagsArray = (array) $tagsArray;
74                $this->attrArray = (array) $attrArray;
75                $this->tagsMethod = $tagsMethod;
76                $this->attrMethod = $attrMethod;
77                $this->xssAuto = $xssAuto;
78        }
79
80        /**
81          * Method to be called by another php script. Processes for XSS and specified bad code.
82          * @access public
83          * @param Mixed $source - input string/array-of-string to be 'cleaned'
84          * @return String $source - 'cleaned' version of input parameter
85          */
86        function process($source) {
87                // clean all elements in this array
88                if (is_array($source)) {
89                        foreach($source as $key => $value)
90                                // filter element for XSS and other 'bad' code etc.
91                                if (is_string($value)) $source[$key] = $this->remove($this->decode($value));
92                        return $source;
93                // clean this string
94                } else if (is_string($source)) {
95                        // filter source for XSS and other 'bad' code etc.
96                        return $this->remove($this->decode($source));
97                // return parameter as given
98                } else return $source;
99        }
100
101        /**
102          * Internal method to iteratively remove all unwanted tags and attributes
103          * @access protected
104          * @param String $source - input string to be 'cleaned'
105          * @return String $source - 'cleaned' version of input parameter
106          */
107        function remove($source) {
108                $loopCounter=0;
109                // provides nested-tag protection
110                while($source != $this->filterTags($source)) {
111                        $source = $this->filterTags($source);
112                        $loopCounter++;
113                }
114                return $source;
115        }
116
117        /**
118          * Internal method to strip a string of certain tags
119          * @access protected
120          * @param String $source - input string to be 'cleaned'
121          * @return String $source - 'cleaned' version of input parameter
122          */
123        function filterTags($source)
124        {
125                return strip_tags($source);
126        }
127
128        /**
129          * Internal method to strip a tag of certain attributes
130          * @access protected
131          * @param Array $attrSet
132          * @return Array $newSet
133          */
134        function filterAttr($attrSet) {
135                $newSet = array();
136                // process attributes
137                for ($i = 0; $i <count($attrSet); $i++) {
138                        // skip blank spaces in tag
139                        if (!$attrSet[$i]) continue;
140                        // split into attr name and value
141                        $attrSubSet = explode('=', trim($attrSet[$i]));
142                        list($attrSubSet[0]) = explode(' ', $attrSubSet[0]);
143                        // removes all "non-regular" attr names AND also attr blacklisted
144                        if ((!eregi("^[a-z]*$",$attrSubSet[0])) || (($this->xssAuto) && ((in_array(strtolower($attrSubSet[0]), $this->attrBlacklist)) || (substr($attrSubSet[0], 0, 2) == 'on'))))
145                                continue;
146                        // xss attr value filtering
147                        if ($attrSubSet[1]) {
148                                // strips unicode, hex, etc
149                                $attrSubSet[1] = str_replace('&#', '', $attrSubSet[1]);
150                                // strip normal newline within attr value
151                                $attrSubSet[1] = preg_replace('/\s+/', '', $attrSubSet[1]);
152                                // strip double quotes
153                                $attrSubSet[1] = str_replace('"', '', $attrSubSet[1]);
154                                // [requested feature] convert single quotes from either side to doubles (Single quotes shouldn't be used to pad attr value)
155                                if ((substr($attrSubSet[1], 0, 1) == "'") && (substr($attrSubSet[1], (strlen($attrSubSet[1]) - 1), 1) == "'"))
156                                        $attrSubSet[1] = substr($attrSubSet[1], 1, (strlen($attrSubSet[1]) - 2));
157                                // strip slashes
158                                $attrSubSet[1] = stripslashes($attrSubSet[1]);
159                        }
160                        // auto strip attr's with "javascript:
161                        if (    ((strpos(strtolower($attrSubSet[1]), 'expression') !== false) &&        (strtolower($attrSubSet[0]) == 'style')) ||
162                                        (strpos(strtolower($attrSubSet[1]), 'javascript:') !== false) ||
163                                        (strpos(strtolower($attrSubSet[1]), 'behaviour:') !== false) ||
164                                        (strpos(strtolower($attrSubSet[1]), 'vbscript:') !== false) ||
165                                        (strpos(strtolower($attrSubSet[1]), 'mocha:') !== false) ||
166                                        (strpos(strtolower($attrSubSet[1]), 'livescript:') !== false)
167                        ) continue;
168
169                        // if matches user defined array
170                        $attrFound = in_array(strtolower($attrSubSet[0]), $this->attrArray);
171                        // keep this attr on condition
172                        if ((!$attrFound && $this->attrMethod) || ($attrFound && !$this->attrMethod)) {
173                                // attr has value
174                                if ($attrSubSet[1]) $newSet[] = $attrSubSet[0] . '="' . $attrSubSet[1] . '"';
175                                // attr has decimal zero as value
176                                else if ($attrSubSet[1] == "0") $newSet[] = $attrSubSet[0] . '="0"';
177                                // reformat single attributes to XHTML
178                                else $newSet[] = $attrSubSet[0] . '="' . $attrSubSet[0] . '"';
179                        }
180                }
181                return $newSet;
182        }
183
184        /**
185          * Try to convert to plaintext
186          * @access protected
187          * @param String $source
188          * @return String $source
189          */
190        function decode($source) {
191                // url decode
192                $source = html_entity_decode($source, ENT_QUOTES, "ISO-8859-1");
193                // convert decimal
194                $source = preg_replace('/&#(\d+);/me',"chr(\\1)", $source);                             // decimal notation
195                // convert hex
196                $source = preg_replace('/&#x([a-f0-9]+);/mei',"chr(0x\\1)", $source);   // hex notation
197                return $source;
198        }
199
200        /**
201          * Method to be called by another php script. Processes for SQL injection
202          * @access public
203          * @param Mixed $source - input string/array-of-string to be 'cleaned'
204          * @return String $source - 'cleaned' version of input parameter
205          */
206        function safeSQL($source) {
207                // clean all elements in this array
208                if (is_array($source)) {
209                        foreach($source as $key => $value)
210                                // filter element for SQL injection
211                                if (is_string($value)) $source[$key] = $this->quoteSmart($this->decode($value));
212                        return $source;
213                // clean this string
214                } else if (is_string($source)) {
215                        // filter source for SQL injection
216                        if (is_string($source)) return $this->quoteSmart($this->decode($source));
217                // return parameter as given
218                } else return $source;
219        }
220
221        /**
222          * @author Chris Tobin
223          * @author Daniel Morris
224          * @access protected
225          * @param String $source
226          * @return String $source
227          */
228        function quoteSmart($source) {
229                // strip slashes
230                if (get_magic_quotes_gpc()) $source = stripslashes($source);
231                // quote both numeric and text
232                $source = $this->escapeString($source);
233                return $source;
234        }
235
236        /**
237          * @author Chris Tobin
238          * @author Daniel Morris
239          * @access protected
240          * @param String $source
241          * @return String $source
242          */
243        function escapeString($string) {
244                // depreciated function
245                if (version_compare(phpversion(),"4.3.0", "<")) mysql_escape_string($string);
246                // current function
247                else mysql_real_escape_string($string);
248                return $string;
249        }
250
251        /**
252         * @author Sidnei Augusto Drovetto Jr. - drovetto@gmail.com
253         * @param mixed $source A string or array of strings to be escaped
254         * @return mixed $source An object of the same type of the input, only escaped
255         * @access public
256         */
257        function escapeHTML($source)
258        {
259                $output = $source;
260                if (is_string($output))
261                        $output = htmlentities($output, ENT_QUOTES, 'ISO-8859-1');
262                else
263                        if (is_array($output))
264                                foreach ($output as &$element)
265                                        $element = $this->escapeHTML($element);
266
267                return $output;
268        }
269}
270
271?>
Note: See TracBrowser for help on using the repository browser.