Bitrix-D7 23.9
 
Загрузка...
Поиск...
Не найдено
xss.php
1<?php
9
17class Xss
18 extends Base
19{
20 protected $name = 'XSS';
21
22 private $whiteList = array();
23
38 public function process($value)
39 {
40 if (!preg_match('#[(){}\[\]=+&%<>]?#', $value))
41 return false;
42
43 $this->initializeFilters();
44 $this->setFilteredValue('');
45 $found = false;
46
47 $targetValue = $this->processWhiteList($value, 'store');
48
49 $last = '';
50 $current = $targetValue;
51 while ($last != $current)
52 {
53 $last = $current;
54 foreach ($this->filters as $searchChar => $filters)
55 {
56 if ($searchChar && mb_strpos($current, $searchChar) === false)
57 continue;
58
59 $current = preg_replace($filters['search'], $filters['replace'], $current);
60 }
61 }
62
63 if ($last != $targetValue)
64 {
65 $last = $this->processWhiteList($last, 'restore');
66 $this->setFilteredValue($last);
67 $found = true;
68 }
69
70 return $found;
71 }
72
73 protected function initializeWhiteList()
74 {
75 if (!$this->whiteList)
76 {
77 $this->whiteList = $this->getWhiteList();
78 }
79 }
80
81 protected function getFilters()
82 {
83 $_M = '(?:[\x09\x0a\x0d\\\\]*)';
84 $_M3 = '(?:[\x09\x0a\x0d\\\\\s]*)';
85 $_M2 = '(?:(?:[\x09\x0a\x0d\\\\\s]|(?:\/\*.*?\*\/))*)';
86
87 $_Al = '(?<![a-z0-9&_?-])';
88
89 $_Jj = '(?:j|%[64]a|\\\\x[64]a|(?:\\\\0*[64]a))';
90 $_Ja = '(?:a|%[64]1|\\\\x[64]1|(?:\\\\0*[64]1))';
91 $_Jb = '(?:b|%[64]2|\\\\x[64]2|(?:\\\\0*[64]2))';
92
93 $_Jv = '(?:v|%[75]6|\\\\x[75]6|(?:\\\\0*[75]6))';
94 $_Js = '(?:s|%[75]3|\\\\x[75]3|(?:\\\\0*[75]3))';
95 $_Jc = '(?:c|%[64]3|\\\\x[64]3|(?:\\\\0*[64]3))';
96 $_Jr = '(?:r|%[75]2|\\\\x[75]2|(?:\\\\0*[75]2))';
97 $_Ji = '(?:i|%[64]9|\\\\x[64]9|(?:\\\\0*[64]9))';
98 $_Jp = '(?:p|%[75]0|\\\\x[75]0|(?:\\\\0*[75]0))';
99 $_Jt = '(?:t|%[75]4|\\\\x[75]4|(?:\\\\0*[75]4))';
100
101 $_Je = '(?:e|%[64]5|\\\\x[64]5|(?:\\\\0*[64]5))';
102 $_Jx = '(?:x|%[75]8|\\\\x[75]8|(?:\\\\0*[75]8))';
103 $_Jo = '(?:o|%[64]f|\\\\x[64]f|(?:\\\\0*[64]f))';
104 $_Jn = '(?:n|%[64]e|\\\\x[64]e|(?:\\\\0*[64]e))';
105
106 $_Jh = '(?:h|%[64]8|\\\\x[64]8|(?:\\\\0*[64]8))';
107
108 $_Jdd = '(?:\\:|=|%3a|%3d|\\\\x3a|\\\\x3d|(?:\\\\0*3a)|(?:\\\\0*3d))';
109 $_Jss = '(?:\\(|%28|\\\\x28|(?:\\\\0*28))';
110
111 $_WS_OPT = '(?:[\\x00\\x09\\x0A\\x0B\\x0C\\x0D\\s\\\\]|\\xE2\\x80\\xA9)*'; //not modified
112 $replacePattern = $this->getSplittingString(2);
113 $filters = array(
114 0 => array(
115 'search' => array(
116 "/$_Al({$_Jb}{$_M}{$_Je}{$_M}{$_Jh}{$_M})({$_Ja}{$_M}{$_Jv}{$_M}{$_Ji}{$_M}{$_Jo}{$_M}{$_Jr}{$_WS_OPT}{$_Jdd})/is",
117 "/({$_Jj}{$_M3}{$_Ja}{$_M3}{$_Jv}{$_M3})({$_Ja}{$_M3}{$_Js}{$_M3}{$_Jc}{$_M3}{$_Jr}{$_M3}{$_Ji}{$_M3}{$_Jp}{$_M3}{$_Jt}{$_M3}{$_Jdd})/is",
118 "/({$_Jv}{$_M3}{$_Jb}{$_M3})({$_Js}{$_M3}{$_Jc}{$_M3}{$_Jr}{$_M3}{$_Ji}{$_M3}{$_Jp}{$_M3}{$_Jt}{$_M3}{$_Jdd})/is",
119 "/({$_Je}{$_M2}{$_Jx}{$_M2})({$_Jp}{$_M2}{$_Jr}{$_M2}{$_Je}{$_M2}{$_Js}{$_M2}{$_Js}{$_M2}{$_Ji}{$_M2}{$_Jo}{$_M2}{$_Jn}{$_M2}{$_Jss})/is",
120 ),
121 'replace' => $this->getSplittingString(2, " * ")
122 ),
123
124 "<" => array(
125 'search' => array(
126 "/(<{$_M}!{$_M}D{$_M}O{$_M})(C{$_M}T{$_M}Y{$_M}P{$_M}E)/is",
127 "/(<{$_M}!{$_M}E{$_M}N{$_M})(T{$_M}I{$_M}T{$_M}Y)/is",
128 "/(<{$_M}s{$_M}c{$_M})(r{$_M}i{$_M}p{$_M}t)(?!\\w)/is",
129 "/(<{$_M}\\/{$_M}s{$_M}c{$_M})(r{$_M}i{$_M}p{$_M}t)/is",
130 "/(<{$_M}x{$_M}:{$_M}s{$_M}c{$_M})(r{$_M}i{$_M}p{$_M}t)(?!\\w)/is",
131 "/(<{$_M}a{$_M}p{$_M}p{$_M})(l{$_M}e{$_M}t)(?!\\w)/is",
132 "/(<{$_M}e{$_M}m{$_M}b)(e{$_M}d)(?!\\w)/is",
133 "/(<{$_M}s{$_M}t{$_M})(y{$_M}l{$_M}e)(?!\\w)/is",
134 "/(<{$_M}f{$_M}r{$_M}a{$_M})(m{$_M}e)(?!\\w)/is",
135 "/(<{$_M}i{$_M}f{$_M}r{$_M})(a{$_M}m{$_M}e)(?!\\w)/is",
136 "/(<{$_M}f{$_M}o{$_M})(r{$_M}m)(?!\\w)/is",
137 "/(<{$_M}o{$_M}b{$_M})(j{$_M}e{$_M}c{$_M}t)(?!\\w)/is",
138 "/(<{$_M}l{$_M}i{$_M})(n{$_M}k)(?!\\w)/is",
139 "/(<{$_M}m{$_M}e{$_M}t)({$_M}a)(?!\\w)/is",
140 "/(<{$_M}L{$_M}A{$_M}Y{$_M})(E{$_M}R)(?!\\w)/is",
141 "/(<{$_M}h{$_M}t{$_M})(m{$_M}l)(?!\\w)/is",
142 "/(<{$_M}x{$_M}m{$_M})(l)(?!\\w)/is",
143 "/(<{$_M}b{$_M}a{$_M})(s{$_M}e)(?!\\w)/is",
144 "/(<{$_M}s{$_M}v{$_M})(g)(?!\\w)/is",
145 "/(<{$_M}i{$_M}s{$_M}i{$_M})(n{$_M}d{$_M}e{$_M}x)(?!\\w)/is",
146 "/(<{$_M}m{$_M}a)({$_M}t{$_M}h)(?!\\w)/is",
147 "/(<!--'start_frame)(_cache_)/is",
148 "/(<!--'end_frame)(_cache_)/is"
149 ),
150 'replace' => $replacePattern
151 ),
152
153 "=" => array(
154 'search' => array(
155 /*"/{$_Al}(s{$_M}t{$_M})(y{$_M}l{$_M}e{$_WS_OPT}\=)
156 (?!\\s*
157 (?P<quot>\"|&quot;|'|\"|\\\\\"|\\\\')
158 (
159 \\s*[a-z-]+\\s*:\\s*([0-9a-z\\s%,.#!\-'\"\\/]
160 |&quot;
161 |(?:rgb|hsl)a?\\s*\\‍([0-9a-z%.\\/,\\s]+\\‍))*\\s*(?:!important)?;?
162 |background-image\\s*\\:\\s*url\\s*\\‍([^)]+\\‍);?
163 |background\\s*\\:(?:\\s*url\\s*\\‍([^)]+\\‍)|\s\\#[0-9a-fA-F]+|\s[a-zA-Z-]+)+;?
164 )*
165 \\s*
166 (?P=quot)
167 )
168 (?!\\s*
169 [a-z]+;
170 )
171 /xis", */
172 "/{$_Al}(f{$_M}o{$_M}r{$_M})(m{$_M}a{$_M}c{$_M}t{$_M}i{$_M}o{$_M}n{$_WS_OPT}=)/is",
173 "/{$_Al}(o{$_M}n{$_M}(?:[a-z]{$_M})*?)(([a-z]{$_M}){3}{$_WS_OPT}=)/is",
174 "/{$_Al}(s{$_M}e{$_M}e{$_M})(k{$_M}S{$_M}e{$_M}g{$_M}m{$_M}e{$_M}n{$_M}t{$_M}T{$_M}i{$_M}m{$_M}e{$_WS_OPT}=)/is",
175 "/{$_Al}(F{$_M}S{$_M}C{$_M})(o{$_M}m{$_M}m{$_M}a{$_M}n{$_M}d{$_WS_OPT}=)/is",
176 ),
177 'replace' => $replacePattern
178 ),
179
180 ":" => array(
181 'search' => array(
182 "/(u{$_M}r{$_M}n{$_M2}:{$_M2}s{$_M})(c{$_M}h{$_M}e{$_M}m{$_M}a{$_M}s{$_M}-{$_M}m{$_M}i{$_M}c{$_M}r{$_M}o{$_M}s{$_M}o{$_M}f{$_M}t{$_M}-{$_M}c{$_M}o{$_M}m{$_M2}:)/",
183 "/((?:'|\"|=|:|;){$_M3}d{$_M}a{$_M}t{$_M})(a{$_M}:)(?![0-9]|image)/is",
184 ),
185 'replace' => $replacePattern
186 ),
187
188 "-" => array(
189 'search' => array(
190 "/(-{$_M}m{$_M}o{$_M}z{$_M}-{$_M}b{$_M}i{$_M})(n{$_M}d{$_M}i{$_M}n{$_M}g{$_M}{$_WS_OPT}:{$_WS_OPT}{$_M}u{$_M}r{$_M}l)/is",
191 ),
192 'replace' => $replacePattern
193 ),
194
195 );
196
197 return $filters;
198 }
199
200
204 protected function getWhiteList()
205 {
206 $safeReplacement = md5(mt_rand());
207 return array(
208 'store' => array(
209 'match' => array(
210 //video player insertion
211 '#(<script)(\\s+type="text/javascript"\\s+)(src)(="/bitrix/components/bitrix/player/wmvplayer/(:?silverlight|wmvplayer).js"[\\s/]*>)(</script>)#s',
212 '#(<script)(\\s+type\\s*=\\s*"text/javascript"\\s*>\\s*new\\s+jeroenwijering\\.Player\\(\\s*document\\.getElementById\\(\\s*"[a-zA-Z0-9_]+"\\s*\\)\\s*,\\s*"/bitrix/components/bitrix/player/wmvplayer/wmvplayer.xaml"\\s*,\\s*{\\s*(?:[a-zA-Z0-9_]+:\\s+"[a-zA-Z0-9/.]*?"[,\\s]*)*}\\s*\\);\\s*)(</script>)#s',
213 ),
214 'replacement' => array(
215 $safeReplacement.'11\\2'.$safeReplacement.'12\\4'.$safeReplacement.'13',
216 $safeReplacement.'21\\2'.$safeReplacement.'22',
217 ),
218 ),
219 'restore' => array(
220 'match' => array(
221 '#'.$safeReplacement.'11(.*?)'.$safeReplacement.'12(.*?)'.$safeReplacement.'13#',
222 '#'.$safeReplacement.'21(.*?)'.$safeReplacement.'22#',
223 ),
224 'replacement' => array(
225 '<script\\1src\\2</script>',
226 '<script\\1</script>',
227 ),
228 ),
229 );
230 }
231
237 protected function processWhiteList($value, $action = 'store')
238 {
239 if (!is_string($value) || !$value)
240 return '';
241
242 $this->initializeWhiteList();
243 if (!isset($this->whiteList[$action]))
244 return $value;
245
246 $result = preg_replace($this->whiteList[$action]['match'], $this->whiteList[$action]['replacement'], $value);
247
248 return $result;
249 }
250
251}
getSplittingString($splitItemsCount=2, $customSplitChar='')
Definition base.php:137
processWhiteList($value, $action='store')
Definition xss.php:237