1C-Bitrix 25.700.0
Загрузка...
Поиск...
Не найдено
post_filter.php
См. документацию.
1<?php
2
4
6{
7 const SCRIPT_MARK = '<!-- deleted by bitrix WAF -->';
8 private $quotes = array();
9
10 private $action = "filter";
11 private $doLog = false;
12
14 private $variables = null;
15
17 private $searches = null;
19 private $quotedSearches = null;
20
22 {
23 if(isset($options["action"]))
24 {
25 $this->setAction($options["action"]);
26 }
27 else
28 {
29 $this->setAction(COption::GetOptionString("security", "filter_action"));
30 }
31
32 if(isset($options["log"]))
33 {
34 $this->setLog($options["log"]);
35 }
36 else
37 {
38 $this->setLog(COption::GetOptionString("security", "filter_log"));
39 }
40 }
41
45 public static function OnEndBufferContent(&$content)
46 {
47 if (CSecuritySystemInformation::isCliMode())
48 return;
49
50 if (CSecurityFilterMask::Check(SITE_ID, $_SERVER["REQUEST_URI"]))
51 return;
52
53 if (!preg_match('#</script#', $content)) // Probably does not include the scripts
54 return;
55
57 $filter->process($content);
58 }
59
64 public function process(&$content)
65 {
66 $this->variables = new CSecurityXSSDetectVariables();
67 $this->extractVariablesFromArray("\$_GET", $_GET);
68 $this->extractVariablesFromArray("\$_POST", $_POST);
69 $this->extractVariablesFromArray("\$_SERVER[REQUEST_URI]", explode("/",$_SERVER['REQUEST_URI']));
70
71 if(!$this->variables->isEmpty())
72 {
73 $this->searches = $this->variables->getSearchValues();
74 $this->quotedSearches = $this->variables->getQuoteSearchValues();
75 $content = $this->filter($content);
76 }
77
78 }
79
83 public function getQuotes()
84 {
85 return $this->quotes;
86 }
87
93 public function removeQuotedStrings($string, $isSaveQuotes = true)
94 {
95 // http://stackoverflow.com/questions/5695240/php-regex-to-ignore-escaped-quotes-within-quotes
96 // ToDo: R&D, what about JS comments?
97 static $regexp = '/(
98 "[^"\\\\]*(?:\\\\.[^"\\\\]*)*" # match double quoted string
99 |
100 \'[^\'\\\\]*(?:\\\\.[^\'\\\\]*)*\' # match single quoted string
101 )/xs';
102
103 if ($isSaveQuotes)
104 {
105 $this->quotes = array();
106 return preg_replace_callback($regexp, array($this, "pushQuote"), $string);
107 }
108
109 return preg_replace($regexp, '', $string);
110 }
111
115 protected function setAction($action)
116 {
117 $this->action = $action;
118 }
119
123 protected function setLog($log)
124 {
125 if(is_string($log) && $log == "Y")
126 {
127 $this->doLog = true;
128 }
129 else
130 {
131 $this->doLog = false;
132 }
133 }
134
141 protected function logVariable($name, $value, $sourceScript)
142 {
143 if(defined("ANTIVIRUS_CREATE_TRACE"))
144 $this->CreateTrace($name, $value, $sourceScript);
145
146 return CSecurityEvent::getInstance()->doLog("SECURITY", "SECURITY_FILTER_XSS2", $name, $value);
147 }
148
154 protected function CreateTrace($var_name, $str, $script)
155 {
156 $cache_id = md5($var_name.'|'.$str);
157 $fn = $_SERVER["DOCUMENT_ROOT"]."/bitrix/cache/virus.db/".$cache_id.".flt";
158 if(!file_exists($fn))
159 {
160 CheckDirPath($fn);
161 $f = fopen($fn, "wb");
162
163 fwrite($f, $var_name.": ".$str);
164 fwrite($f, "\n------------\n".$script);
165 fwrite($f, "\n------------------------------\n\$_SERVER:\n");
166 foreach($_SERVER as $k=>$v)
167 fwrite($f, $k." = ".$v."\n");
168
169 fclose($f);
170 @chmod($fn, BX_FILE_PERMISSIONS);
171 }
172 }
173
178 protected function pushQuote($quote)
179 {
180 $this->quotes[] = $quote[0];
181 return "";
182 }
183
189 protected function findInArray($string, $searches)
190 {
191 foreach($searches as $i => $search)
192 {
193 $pos = strpos($string, $search["value"]);
194 if ($pos !== false)
195 {
196 $prevChar = substr($string, $pos - 1, 1);
197 $isFound = ($prevChar !== '\\');
198 if ($isFound && preg_match("/^[a-zA-Z_]/", $search["value"]))
199 {
200 $isFound = preg_match("/^[a-zA-Z_]/", $prevChar) <= 0;
201 }
202
203 if ($isFound)
204 return $i;
205 }
206 }
207 return null;
208 }
209
214 protected function isDangerBody($body)
215 {
216 $search = $this->findInArray($body, $this->quotedSearches);
217 if ($search !== null)
218 {
219 return $this->quotedSearches[$search];
220 }
221 else if (!empty($this->searches))
222 {
223 $bodyWithoutQuotes = $this->removeQuotedStrings($body, false);
224 $search = $this->findInArray($bodyWithoutQuotes, $this->searches);
225 if ($search !== null)
226 {
227 return $this->searches[$search];
228 }
229 }
230
231 return false;
232 }
233
238 protected function getFilteredScriptBody($body)
239 {
240 if($var = $this->isDangerBody($body))
241 {
242 if($this->doLog)
243 {
244 $this->logVariable($var["name"], $var["value"], $_SERVER["SCRIPT_NAME"]);
245 }
246
247 if($this->action !== "none")
248 {
249 $body = self::SCRIPT_MARK;
250 }
251 }
252
253 return $body;
254 }
255
260 protected function getFilteredScript($strs)
261 {
262 if(preg_match('#\btype="text/html"#', $strs[1]))
263 return $strs[0];
264
265 if(trim($strs[2]) === "")
266 return $strs[0];
267 else
268 return $strs[1].$this->getFilteredScriptBody($strs[2]).$strs[3];
269 }
270
275 protected function filter($string)
276 {
277 $stringLen = strlen($string) * 2;
278 Ini::adjustPcreBacktrackLimit($stringLen);
279
280 return preg_replace_callback("/(<script[^>]*>)(.*?)(<\\/script[^>]*>)/is", array($this, "getFilteredScript"), $string);
281 }
282
287 protected function addVariable($name, $value)
288 {
289 if(!is_string($value))
290 return;
291 if(mb_strlen($value) <= 2)
292 return; //too short
293 if(preg_match("/^(?P<quot>[\"']?)[^`,;+\-*\/\{\}\[\]\‍(\‍)&\\|=\\\\]*(?P=quot)\$/D", $value))
294 return; //there is no potantially dangerous code
295 if(preg_match("/^[,0-9_-]*\$/D", $value))
296 return; //there is no potantially dangerous code
297 if(preg_match("/^[0-9 \n\r\t\\[\\]]*\$/D", $value))
298 return; //there is no potantially dangerous code
299
300 $this->variables->addVariable($name, $value);
301 }
302
307 protected function extractVariablesFromArray($name, $array)
308 {
309 if(!is_array($array))
310 return;
311
312 foreach($array as $key => $value)
313 {
314 $variableName = sprintf('%s[%s]', $name, $key);
315 if (is_array($value))
316 $this->extractVariablesFromArray($variableName, $value);
317 else
318 $this->addVariable($variableName, $value);
319 }
320 }
321}
Определения ini.php:6
static getInstance()
Определения event.php:41
static Check($siteId, $uri)
Определения filter_mask.php:69
setAction($action)
Определения post_filter.php:115
isDangerBody($body)
Определения post_filter.php:214
filter($string)
Определения post_filter.php:275
const SCRIPT_MARK
Определения post_filter.php:7
logVariable($name, $value, $sourceScript)
Определения post_filter.php:141
getFilteredScript($strs)
Определения post_filter.php:260
getQuotes()
Определения post_filter.php:83
getFilteredScriptBody($body)
Определения post_filter.php:238
process(&$content)
Определения post_filter.php:64
removeQuotedStrings($string, $isSaveQuotes=true)
Определения post_filter.php:93
setLog($log)
Определения post_filter.php:123
__construct($options=array())
Определения post_filter.php:21
CreateTrace($var_name, $str, $script)
Определения post_filter.php:154
addVariable($name, $value)
Определения post_filter.php:287
static OnEndBufferContent(&$content)
Определения post_filter.php:45
findInArray($string, $searches)
Определения post_filter.php:189
extractVariablesFromArray($name, $array)
Определения post_filter.php:307
pushQuote($quote)
Определения post_filter.php:178
$options
Определения commerceml2.php:49
$str
Определения commerceml2.php:63
$content
Определения commerceml.php:144
$f
Определения component_props.php:52
</td ></tr ></table ></td ></tr >< tr >< td class="bx-popup-label bx-width30"><?=GetMessage("PAGE_NEW_TAGS")?> array( $site)
Определения file_new.php:804
$filter
Определения iblock_catalog_list.php:54
$_SERVER["DOCUMENT_ROOT"]
Определения cron_frame.php:9
CheckDirPath($path)
Определения tools.php:2707
$name
Определения menu_edit.php:35
$var
Определения payment.php:63
if(empty($signedUserToken)) $key
Определения quickway.php:257
$i
Определения factura.php:643
const SITE_ID
Определения sonet_set_content_view.php:12
$k
Определения template_pdf.php:567