86 private $tokens =
array();
87 private $variables =
array();
88 private $template =
'';
89 private $file_history =
array();
90 private $current_file =
'';
91 private $scan_functions =
array();
92 private $tokens_type =
array();
93 private $vuln_func =
array();
94 private $sec_func =
array();
95 private $v_userinput =
array();
96 private $mp_mode =
false;
97 private $color =
array();
98 private $securing_list =
array();
99 private $tainted_vars =
array();
100 private $comment =
'';
102 private $dependency =
array();
103 private $last_dependency =
array();
104 private $dependencies =
array();
105 private $dependency_line = 0;
106 private $scanning_file =
'';
107 private $init_functions =
array();
108 private $search_xss =
true;
109 private $global_xss_ignore =
false;
113 $this->scanning_file = $file_name;
114 $this->source_functions =
array();
115 $this->tokens_type =
$arParams[
'TOKENS_TYPES'];
116 $this->vuln_func =
$arParams[
'VULN_FUNCTIONS'];
117 $this->sec_func =
$arParams[
'SECURING_FUNCTIONS'];
118 $this->v_userinput =
$arParams[
'USER_INPUTS'];
119 $this->init_functions =
$arParams[
'INIT_FUNCTIONS'];
121 $this->securing_list =
array();
122 $this->variables =
array();
126 $this->arResult =
array();
127 $this->tainted_vars =
array();
129 $this->
template = $template;
131 $this->dependency =
array();
132 $this->last_dependency =
array();
133 $this->dependencies =
array();
134 $this->dependency_line =
'syntax_error';
137 $this->scan_functions = array_merge(
138 $this->vuln_func[
'XSS'],
139 $this->vuln_func[
'CODE'],
140 $this->vuln_func[
'FILE_INCLUDE'],
141 $this->vuln_func[
'EXEC'],
142 $this->vuln_func[
'DATABASE'],
143 $this->vuln_func[
'OTHER']
147 $this->file_history[] = $file_name;
148 $this->current_file = end($this->file_history);
149 $this->tokens = $this->
tokenize(file_get_contents($file_name), $component_template);
150 $this->vuln_count = 0;
151 $this->search_xss =
true;
152 $this->global_xss_ignore =
false;
155 private function getTokensInfo($tokens, $var_declare =
true, $function =
'')
159 $this->securing_list =
array();
161 if ($function ===
'unserialize')
163 foreach ($tokens as $token)
165 if (is_array($token) && isset($token[1]) && $token[1] ===
"'allowed_classes'")
181 if(is_array($tokens[
$i]))
183 $token = $tokens[
$i][0];
184 $token_value = $tokens[
$i][1];
185 if($token === T_DOUBLE_COLON || $token === T_OBJECT_OPERATOR)
188 elseif($token === T_VARIABLE)
190 if($var_declare || $this->scan_functions[$function][0] === 0 || in_array($c_params, $this->scan_functions[$function][0]))
194 isset($tokens[
$i - 1])
195 && is_array($tokens[
$i - 1])
196 && in_array($tokens[
$i - 1][0], $this->tokens_type[
'CASTS'])
198 || (isset($tokens[
$i + 1]) && in_array($tokens[
$i + 1], $this->tokens_type[
'ARITHMETIC_STR']))
199 || (isset($tokens[
$i - 1]) && in_array($tokens[
$i - 1], $this->tokens_type[
'ARITHMETIC_STR']))
201 isset($tokens[
$i + 1])
202 && is_array($tokens[
$i + 1])
203 && (in_array($tokens[
$i + 1][0], $this->tokens_type[
'ARITHMETIC'])
204 || in_array($tokens[
$i + 1][0], $this->tokens_type[
'OPERATOR'])
205 || in_array($tokens[
$i + 1][0], $this->tokens_type[
'LOGICAL'])
209 isset($tokens[
$i - 1])
210 && is_array($tokens[
$i - 1])
212 in_array($tokens[
$i - 1][0], $this->tokens_type[
'ARITHMETIC'])
213 || in_array($tokens[
$i - 1][0], $this->tokens_type[
'OPERATOR'])
214 || in_array($tokens[
$i - 1][0], $this->tokens_type[
'LOGICAL'])
223 if(!in_array($token_value, array_keys(
$arResult)))
227 if(in_array($token_value, $this->v_userinput) && ($var_declare || !$secure || $unsecure))
230 $arResult[$token_value][
'have_user_input'] =
true;
231 $arResult[$token_value][
'secure'] = $secure;
232 $arResult[$token_value][
'var_name'] = $token_value;
233 $arResult[$token_value][
'requestInitialization'] =
true;
235 elseif(isset($this->variables[
$val = $this->getVarName($tokens[
$i])]))
237 if($this->variables[
$val]->have_user_input && ($var_declare || !$this->variables[
$val]->secure || $unsecure))
239 $arResult[$token_value][
'have_user_input'] =
true;
240 $arResult[$token_value][
'secure'] = ($this->variables[
$val]->secure && !$unsecure) ?
true : $secure;
242 $arResult[$token_value][
'requestInitialization'] = $this->variables[
$val]->requestInitialization;
246 elseif((isset($this->variables[$token_value]) && $this->variables[$token_value]->have_user_input)
247 && ($var_declare || !$this->variables[$token_value]->secure || $unsecure))
249 $arResult[$token_value][
'have_user_input'] =
true;
250 $arResult[$token_value][
'secure'] = ($this->variables[$token_value]->secure && !$unsecure) ?
true : $secure;
251 $arResult[$token_value][
'var_name'] = $token_value;
252 $arResult[$token_value][
'requestInitialization'] = $this->variables[$token_value]->requestInitialization;
269 elseif($cur_brace === -1 && $token === T_STRING
270 && in_array($token_value, $this->sec_func[
'INSTRING'])
275 $cur_brace = $braces;
277 elseif(!$unsecure && ($token === T_STRING
279 in_array($token_value, $this->sec_func[
'SECURES_ALL'])
280 || in_array($token_value, $this->sec_func[
'STRING'])
282 isset($this->scan_functions[$function][1])
283 && is_array($this->scan_functions[$function][1])
284 && in_array($token_value, $this->scan_functions[$function][1])
287 || (in_array($token, $this->tokens_type[
'CASTS']) && $tokens[
$i + 1] ===
'(')
290 $this->securing_list[] = $token_value;
293 $cur_brace = $braces;
297 elseif($token === T_ISSET || ($token === T_STRING && str_starts_with($token_value,
'is_')))
302 elseif($braces === 1 && $tokens[
$i] ===
', ')
314 if($cur_brace === $braces)
324 while ((
$i + 1 <
$count) && !($tokens[
$i + 1] ===
', '))
326 if($tokens[
$i + 1] ===
')')
339 if(
$res[
'secure'] ===
false)
346 $requestInitialization =
false;
349 if(
$res[
'requestInitialization'] ===
true)
351 $requestInitialization =
true;
362 private function dependencyHave($tokens,
$type)
364 if (!is_array($tokens))
368 for (
$i = 1, $tokens_count =
count($tokens) - 1;
$i < $tokens_count;
$i++)
370 if(is_array($tokens[
$i]))
375 if($tokens[
$i][0] === T_STRING && $tokens[
$i - 1] !==
'!' && $tokens[
$i][1] ===
'check_bitrix_sessid')
379 if($tokens[
$i][0] === T_STRING && $tokens[
$i - 1] ===
'!' && $tokens[
$i][1] ===
'check_bitrix_sessid')
390 $this->objects =
array();
391 for (
$i = 0, $tokens_count =
count($this->tokens);
$i < $tokens_count;
$i++)
394 if((time() - $this->arParams[
'time_start']) >= $this->arParams[
'time_out'])
397 if(is_array($this->tokens[
$i]))
399 $token = $this->tokens[
$i][0];
400 $token_value = $this->tokens[
$i][1];
401 $cur_line = $this->tokens[
$i][2];
403 if($token === T_VARIABLE)
405 if($this->tokens[
$i + 1] ===
'=' || (is_array($this->tokens[
$i + 1]) && in_array($this->tokens[
$i + 1][0], $this->tokens_type[
'ASSIGNMENT'])))
408 is_array($this->tokens[
$i + 2]) && ($this->tokens[
$i + 2][0] === T_NEW)
409 && ($className = $this->getClassName(
$i + 3))
412 $this->objects[$token_value] = ltrim(strtoupper($className),
'\\');
413 $i += $this->getBraceEnd($this->tokens,
$i);
415 if(!(isset($this->tokens[
$i + 2]) && is_array($this->tokens[
$i + 2]) && $this->tokens[
$i + 2][0] === T_ARRAY))
416 $this->addVariable($this->tokens[
$i],
$i, $cur_line,
$i, $this->getBraceEnd($this->tokens,
$i),
'');
418 $i += $this->getBraceEnd($this->tokens,
$i);
421 elseif($token === T_STRING && in_array($token_value, $this->init_functions))
423 if($this->tokens[
$i + 1] ===
'(' && is_array($this->tokens[
$i + 2]) && $this->tokens[
$i + 3] ===
')')
424 if(isset($this->variables[
$val = $this->getVarName($this->tokens[
$i + 2])]))
425 unset($this->variables[
$val]);
428 in_array($token, $this->tokens_type[
'FUNCTIONS'])
429 || ($this->search_xss && !$this->global_xss_ignore && in_array($token, $this->tokens_type[
'XSS']))
430 || in_array($token, $this->tokens_type[
'INCLUDES'])
433 if(in_array($token, $this->tokens_type[
'INCLUDES']))
435 $component_template =
'';
437 if($token == T_INCLUDE_COMPONENT)
441 $component_name =
'';
442 if($this->tokens[
$i + 1] ===
'(' && $this->tokens[
$i + 2][0] === T_CONSTANT_ENCAPSED_STRING)
445 $component_name = substr($this->tokens[
$i + 2][1], 1, -1);
447 $component_name = strtolower($component_name);
448 if(empty($component_name))
451 $component_name =
"/".str_replace(
":",
"/", $component_name);
453 if(is_file($this->arParams[
'doc_root_path'].
'/bitrix/components'.$component_name.
'/component.php'))
454 $inc_file = $this->arParams[
'doc_root_path'].
'/bitrix/components'.$component_name.
'/component.php';
459 $this->current_file === $inc_file
460 || in_array($inc_file, $this->file_history)
467 if($this->tokens[
$i + 1] ===
'(' && $this->tokens[
$i + 4][0] === T_CONSTANT_ENCAPSED_STRING)
468 $component_template = substr($this->tokens[
$i + 4][1], 1, -1);
471 $scanner =
new CVulnScanner($inc_file, $this->arParams, $this->
template, $component_template);
475 if(!empty($scanner->arResult))
476 $this->arResult = array_merge($this->arResult, $scanner->arResult);
477 $this->vuln_count += $scanner->vuln_count;
493 elseif($token == T_INCLUDE_RESULT_MODIFIER)
498 $component_path = array_pop(explode(
'bitrix/components', dirname($this->current_file)));
499 $component_template = (!empty($this->tokens[
$i][3]) ? $this->tokens[
$i][3] :
'.default');
500 if(is_file($this->arParams[
'doc_root_path'].
'/bitrix/templates/'.$this->
template.
'/components'.$component_path.
'/'.$component_template.
'/result_modifier.php'))
501 $inc_file = $this->arParams[
'doc_root_path'].
'/bitrix/templates/'.$this->
template.
'/components'.$component_path.
'/'.$component_template.
'/result_modifier.php';
502 elseif(is_file($this->arParams[
'doc_root_path'].
'/bitrix/templates/'.$component_template.
'/components'.$component_path.
'/.default/result_modifier.php'))
503 $inc_file = $this->arParams[
'doc_root_path'].
'/bitrix/templates/'.$component_template.
'/components'.$component_path.
'/.default/result_modifier.php';
505 $inc_file = dirname($this->current_file).
'/templates/'.$component_template.
'/result_modifier.php';
507 unset($component_path);
515 elseif($token == T_INCLUDE_COMPONENTTEMPLATE)
519 $template_name =
'template';
520 $component_template = (!empty($this->tokens[
$i][3]) ? $this->tokens[
$i][3] :
'.default');
522 if($this->tokens[
$i + 1] ===
'(' && $this->tokens[
$i + 2][0] === T_CONSTANT_ENCAPSED_STRING)
524 $tmp = substr($this->tokens[
$i + 2][1], 1, -1);
526 $template_name =
$tmp;
529 elseif($this->tokens[
$i + 1] ===
'(' && $this->tokens[
$i + 2] ===
')')
533 $component_path = array_pop(explode(
'bitrix/components', dirname($this->current_file)));
534 if(is_file($this->arParams[
'doc_root_path'].
'/bitrix/templates/'.$this->
template.
'/components'.$component_path.
'/'.$component_template.
'/'.$template_name.
'.php'))
535 $inc_file = $this->arParams[
'doc_root_path'].
'/bitrix/templates/'.$this->
template.
'/components'.$component_path.
'/'.$component_template.
'/'.$template_name.
'.php';
536 elseif(is_file($this->arParams[
'doc_root_path'].
'/bitrix/templates/.default/components'.$component_path.
'/'.$component_template.
'/'.$template_name.
'.php'))
537 $inc_file = $this->arParams[
'doc_root_path'].
'/bitrix/templates/.default/components'.$component_path.
'/'.$component_template.
'/'.$template_name.
'.php';
539 $inc_file = dirname($this->current_file).
'/templates/'.$component_template.
'/'.$template_name.
'.php';
542 unset($component_path);
550 elseif((($this->tokens[
$i + 1] ===
'('
551 && $this->tokens[
$i + 2][0] === T_CONSTANT_ENCAPSED_STRING
552 && $this->tokens[
$i + 3] ===
')')
554 || (is_array($this->tokens[
$i + 1])
555 && $this->tokens[
$i + 1][0] === T_CONSTANT_ENCAPSED_STRING
556 && $this->tokens[
$i + 2] ===
';'))
559 if($this->tokens[
$i + 1] ===
'(')
561 $inc_file = substr($this->tokens[
$i + 2][1], 1, -1);
566 $inc_file = substr($this->tokens[
$i + 1][1], 1, -1);
572 $inc_file = $this->getTokensValue(
573 $this->current_file, array_slice($this->tokens,
$i + 1, $c = $this->getBraceEnd($this->tokens,
$i + 1) + 1));
578 $try_file = $inc_file;
579 if(!is_file($try_file))
581 $try_file = dirname($this->current_file).
'/'.$inc_file;
582 $try_file = str_replace(
'//',
'/', $try_file);
586 if(is_file($try_file) && !preg_match($this->arParams[
'PREG_FOR_SKIP_INCLUDE'], $inc_file))
589 $this->current_file !== realpath($try_file)
590 && !in_array(realpath($try_file), $this->file_history)
593 if($file = file_get_contents($try_file))
595 $inc_tokens = $this->
tokenize($file, $component_template);
596 $this->tokens = array_merge(array_slice($this->tokens, 0,
$i + $skip), $inc_tokens,
array(
array(T_INCLUDE_END, 0, $inc_file)), array_slice($this->tokens,
$i + $skip));
598 $tokens_count =
count($this->tokens);
599 $this->current_file = & realpath($try_file);
600 $this->file_history[] = $try_file;
602 $this->comment = str_replace(realpath(trim($this->arParams[
'path'])),
'', realpath(trim($try_file))).
' ';
609 if(isset($this->scan_functions[$token_value])
610 && !(($this->tokens[
$i + 1] ===
'(' && $this->tokens[
$i + 2] ===
')') || $this->tokens[
$i + 1] ===
';')
615 $token_value ===
'query'
616 && (is_array($this->tokens[
$i-2]) && $this->tokens[
$i-2][0] === T_VARIABLE)
617 && isset($this->objects[$this->tokens[
$i-2][1]])
618 && $this->objects[$this->tokens[
$i-2][1]] ===
'CHTTP'
623 elseif($token_value !==
'query' && is_array($this->tokens[
$i-1]) && in_array($this->tokens[
$i-1][0], [T_PAAMAYIM_NEKUDOTAYIM, T_OBJECT_OPERATOR],
true))
627 elseif($this->tokens[
$i + 1] ===
'(')
629 $result = $this->getTokensInfo(array_slice($this->tokens,
$i + 2, $this->getBraceEnd($this->tokens,
$i + 2) - 1),
false, $token_value);
633 $result = $this->getTokensInfo(array_slice($this->tokens,
$i + 1, $this->getBraceEnd($this->tokens,
$i + 1)),
false, $token_value);
638 $tainted_vars =
array();
641 if(!
$res[
'secure'] && !isset($tainted_vars[
$res[
'var_name']]))
643 if(
$res[
'requestInitialization'] || !array_key_exists($token_value, $this->vuln_func[
'XSS']))
645 $tainted_vars[
$res[
'var_name']] =
'<div class="checklist-vulnscan-code">';
646 $tainted_vars[
$res[
'var_name']].= $this->traverseVar(
$res[
'var_name'],
$i);
647 $tainted_vars[
$res[
'var_name']].=
'</div>';
653 if(!empty($tainted_vars))
656 if($token_value ===
'query')
661 $this->scanning_file,
664 array_slice($this->tokens, $pos, $this->getBraceEnd($this->tokens, $pos)),
670 $this->arResult[] = $vuln;
676 elseif(in_array($token, $this->tokens_type[
'FLOW_CONTROL']))
679 while ((
$i + $c) <
count($this->tokens) && $this->tokens[
$i + $c] !==
'{')
682 $this->dependency = array_slice($this->tokens,
$i, $c);
683 $this->dependency_line = $cur_line;
685 elseif($token === T_INCLUDE_END)
687 array_pop($this->file_history);
688 $this->current_file = & end($this->file_history);
689 $this->comment = basename($this->current_file) == basename($this->scanning_file) ?
'' : basename($this->current_file);
693 if($token === T_EXIT &&
count($this->dependencies) === 1 && $this->dependencyHave(end($this->dependencies),
'!XSS'))
694 $this->global_xss_ignore =
true;
700 if($this->tokens[
$i] ===
'{'
701 && ($this->tokens[
$i - 1] ===
')' || $this->tokens[
$i - 1] ===
':'
702 || (is_array($this->tokens[
$i - 1]) && $this->tokens[
$i - 1][0] === T_ELSE))
705 if(
count($this->dependency) > 2
706 && $this->dependency[0][0] === T_ELSE && $this->dependency[1][0] !== T_IF
709 $this->dependency = $this->last_dependency;
710 $this->dependency[] =
array(T_ELSE,
'else', $this->dependency[0][2]);
712 $this->dependencies[$this->dependency_line] = $this->dependency;
714 if($this->dependencyHave($this->dependency,
'XSS'))
715 $this->search_xss =
false;
717 $this->dependency =
array();
718 $this->dependency_line =
'syntax_error';
722 && ($this->tokens[
$i - 1] ===
';' || $this->tokens[
$i - 1] ===
'}' || $this->tokens[
$i - 1] ===
'{')
727 $this->last_dependency = array_pop($this->dependencies);
729 if($this->dependencyHave($this->last_dependency,
'XSS'))
730 $this->search_xss =
true;
732 $this->dependency =
array();
739 private static function tokenToString($token)
744 if(is_array($token[
$i]))
745 $result .= self::tokenToString($token[
$i]);
752 private function getClassName($token)
756 is_array($this->tokens[$token])
758 ($this->tokens[$token][0] === T_STRING)
759 || ($this->tokens[$token][0] === T_NS_SEPARATOR)
763 $className .= $this->tokens[$token][1];
769 private function getVarName($token, $level = -1)
771 $var_name = $token[1] ??
null;
772 if (isset($token[3]) && is_array($token[3]))
776 if(is_array($token[3][
$i]))
787 $var_name .=
'['.$token[3][
$i].
']';
794 private function clearVariables(
$var)
797 if(!empty($this->variables))
799 foreach (array_keys($this->variables) as
$key)
801 if(preg_match(
'/'.preg_quote(
$var).
'\[/is',
$key))
802 unset($this->variables[
$key]);
808 private function addVariable(
$var, $id, $line,
$start, $end, $comment =
'', $customTokens =
array())
811 $tokens = !empty($customTokens) ? $customTokens : array_slice($this->tokens,
$start, $end);
812 $tokensForScan = !empty($customTokens) ? $customTokens : array_slice($this->tokens,
$start + 2, $end - 2);
813 $tokensInfo = $this->getTokensInfo($tokensForScan);
815 $dependencies =
array();
823 $varName = self::getVarName(
$var);
824 $this->clearVariables($varName);
825 if($tokensInfo !==
false)
827 $taintedVars =
array();
828 foreach ($tokensInfo[1] as
$res)
829 $taintedVars[] =
$res[
'var_name'] ??
null;
831 if(!isset($this->variables[$varName]))
832 $var =
new CVariable($varName);
834 $var = $this->variables[$varName];
836 $var->have_user_input =
true;
837 $var->secure = $tokensInfo[0];
838 $var->requestInitialization = $tokensInfo[2];
839 if (!$this->search_xss)
840 $var->requestInitialization =
false;
841 $var->newDeclare($id, $line,
$start, $end, $tokens, $this->comment.$comment, $dependencies, $taintedVars);
842 $this->variables[$varName] =
$var;
844 elseif(isset($this->variables[$varName]))
846 unset($this->variables[$varName]);
852 if(preg_match_all(
'/\$GLOBALS\[\'[_0-9]*\'\]/',
$code, $mat) > 20)
854 $tokens = token_get_all(
$code);
855 $tokens = $this->prepareTokens($tokens);
856 $tokens = $this->reconstructArray($tokens);
857 $tokens = $this->fixTokens($tokens, $component_template);
858 $tokens = $this->removeTernary($tokens);
864 private function prepareTokens($tokens)
868 if(is_array($tokens[
$i]))
870 if(in_array($tokens[
$i][0], $this->tokens_type[
'IGNORE']))
872 elseif($tokens[
$i][0] === T_CLOSE_TAG)
873 if(!isset($tokens[
$i - 1]) || ($tokens[
$i - 1] !==
'{' && $tokens[
$i - 1] !==
';'))
874 $tokens[
$i] =
';';
else
876 elseif($tokens[
$i][0] === T_OPEN_TAG_WITH_ECHO)
877 $tokens[
$i][1] =
'echo';
883 while ($tokens[
$i +
$f] !==
'{' && (
$i +
$f) < $c)
885 unset($tokens[
$i +
$f]);
890 while ($braces !== 0 && (
$i +
$f) < $c)
892 if($tokens[
$i +
$f] ===
'{')
896 unset($tokens[
$i +
$f]);
904 elseif($tokens[
$i][0] == T_FUNCTION)
908 if(is_array($tokens[
$i + 1]) && $tokens[
$i + 1][0] === T_STRING)
910 $this->sec_func[
'STRING'][] = strtolower($tokens[
$i + 1][1]);
915 while ($tokens[
$i +
$f] !==
'(' && (
$i +
$f) < $c)
919 if(isset($tokens[
$i +
$f - 1]) && is_array($tokens[
$i +
$f - 1]) && $tokens[
$i +
$f - 1][0] === T_STRING)
921 $this->sec_func[
'STRING'][] = strtolower($tokens[
$i +
$f - 1][1]);
927 while ((
$i +
$f) < $c && $tokens[
$i +
$f] !==
'{')
929 unset($tokens[
$i +
$f]);
933 while ($braces !== 0 && (
$i +
$f) < $c)
935 if(isset($tokens[
$i +
$f]) && $tokens[
$i +
$f] ===
'{')
939 unset($tokens[
$i +
$f]);
947 elseif(isset($tokens[
$i]) && $tokens[
$i] ===
'@')
953 return array_values($tokens);
956 private function wrapBraces($tokens,
$start, $between, $end)
959 $tokens = array_merge(
960 array_slice($tokens, 0,
$start),
962 array_slice($tokens,
$start, $between),
964 array_slice($tokens, $end)
970 private function fixTokens($tokens, $component_template =
'')
974 if($tokens[
$i] ===
'`')
977 while ($tokens[
$i +
$f] !==
'`')
979 if(is_array($tokens[
$i +
$f]))
980 $line = $tokens[
$i +
$f][2];
983 if(!isset($tokens[
$i +
$f]) || $tokens[
$i +
$f] ===
';')
990 $tokens[
$i +
$f] =
')';
991 $tokens[
$i] =
array(T_STRING,
'backticks', $line);
993 $tokens = array_merge(
994 array_slice($tokens, 0,
$i + 1),
array(
'('), array_slice($tokens,
$i + 1)
1000 if(strtolower($tokens[
$i][1]) ===
'includecomponenttemplate' || strtolower($tokens[
$i][1]) ===
'initcomponenttemplate')
1002 $tokens[
$i][3] = $component_template;
1003 $tokens[
$i][1] = strtolower($tokens[
$i][1]);
1004 $tokens[
$i][0] = T_INCLUDE_COMPONENTTEMPLATE;
1005 $tmp =
array(
array(T_INCLUDE_RESULT_MODIFIER,
'include_result_modifier', $tokens[
$i][2], $component_template));
1006 array_splice($tokens,
$i - 1, 0,
$tmp);
1009 elseif(strtolower($tokens[
$i][1]) ==
'includecomponent')
1011 $tokens[
$i][1] = strtolower($tokens[
$i][1]);
1012 $tokens[
$i][0] = T_INCLUDE_COMPONENT;
1014 elseif(($tokens[
$i][0] === T_IF || $tokens[
$i][0] === T_ELSEIF || $tokens[
$i][0] === T_FOR
1015 || $tokens[
$i][0] === T_FOREACH || $tokens[
$i][0] === T_WHILE) && $tokens[
$i + 1] ===
'('
1020 while ($braceopen !== 0 && (
$i +
$f) <
$max)
1022 if($tokens[
$i +
$f] ===
'(')
1028 if(!isset($tokens[
$i +
$f]))
1034 if($tokens[
$i +
$f] ===
':')
1036 switch ($tokens[
$i][0])
1040 $endtoken = T_ENDIF;
1043 $endtoken = T_ENDFOR;
1046 $endtoken = T_ENDFOREACH;
1049 $endtoken = T_ENDWHILE;
1056 while ($tokens[
$i +
$f + $c][0] !== $endtoken)
1059 if(!isset($tokens[
$i +
$f + $c]))
1064 $tokens = $this->wrapBraces($tokens,
$i +
$f + 1, $c + 1,
$i +
$f + $c + 2);
1069 while ($tokens[
$i +
$f + $c] !==
';' && $c <
$max)
1073 $tokens = $this->wrapBraces($tokens,
$i +
$f, $c + 1,
$i +
$f + $c + 1);
1077 && $tokens[
$i + 1][0] !== T_IF
1078 && $tokens[
$i + 1] !==
'{'
1082 while ($tokens[
$i +
$f] !==
';' &&
$f <
$max)
1086 $tokens = $this->wrapBraces($tokens,
$i + 1,
$f,
$i +
$f + 1);
1088 elseif($tokens[
$i][0] === T_SWITCH && $tokens[
$i + 1] ===
'(')
1092 while ($braces !== 0)
1094 if($tokens[
$i + $c] ===
'(')
1102 elseif(!isset($tokens[
$i + $c]) || $tokens[
$i + $c] ===
';')
1108 if($tokens[
$i + $c] ===
':')
1111 while ($tokens[
$i + $c +
$f][0] !== T_ENDSWITCH)
1114 if(!isset($tokens[
$i + $c +
$f]))
1117 $tokens = $this->wrapBraces($tokens,
$i + $c + 1,
$f + 1,
$i + $c +
$f + 2);
1123 while ($tokens[
$i + $e] !==
':' && $tokens[
$i + $e] !==
';')
1127 if(!isset($tokens[
$i + $e]))
1131 if(($tokens[
$i + $e] ===
':' || $tokens[
$i + $e] ===
';')
1132 && $tokens[
$i +
$f] !==
'{'
1133 && $tokens[
$i +
$f][0] !== T_CASE && $tokens[
$i +
$f][0] !== T_DEFAULT
1137 while ($braces || (isset($tokens[
$i +
$f]) && $tokens[
$i +
$f] !==
'}'
1138 && !(is_array($tokens[
$i +
$f])
1139 && ($tokens[
$i +
$f][0] === T_BREAK || $tokens[
$i +
$f][0] === T_CASE
1140 || $tokens[
$i +
$f][0] === T_DEFAULT || $tokens[
$i +
$f][0] === T_ENDSWITCH
1145 if($tokens[
$i +
$f] ===
'{')
1151 if(!isset($tokens[
$i +
$f]))
1154 if($tokens[
$i +
$f][0] === T_BREAK)
1156 if($tokens[
$i +
$f + 1] ===
';')
1157 $tokens = $this->wrapBraces($tokens,
$i + $e + 1,
$f - $e + 1,
$i +
$f + 2);
1159 $tokens = $this->wrapBraces($tokens,
$i + $e + 1,
$f - $e + 2,
$i +
$f + 3);
1163 $tokens = $this->wrapBraces($tokens,
$i + $e + 1,
$f - $e - 1,
$i +
$f);
1168 elseif($tokens[
$i][0] === T_DEFAULT
1169 && $tokens[
$i + 2] !==
'{'
1174 while ($tokens[
$i +
$f] !==
';' && $tokens[
$i +
$f] !==
'}' || $braces)
1176 if($tokens[
$i +
$f] ===
'{')
1182 if(!isset($tokens[
$i +
$f]))
1185 $tokens = $this->wrapBraces($tokens,
$i + 2,
$f - 1,
$i +
$f + 1);
1187 elseif($tokens[
$i][0] === T_FUNCTION)
1189 $tokens[
$i + 1][1] = strtolower($tokens[
$i + 1][1]);
1191 elseif($tokens[
$i][0] === T_STRING && $tokens[
$i + 1] ===
'(')
1193 $tokens[
$i][1] = strtolower($tokens[
$i][1]);
1199 while ($tokens[
$i +
$f][0] !== T_WHILE || $otherDOs)
1201 if($tokens[
$i +
$f][0] === T_DO)
1207 if(!isset($tokens[
$i +
$f]))
1211 if($tokens[
$i + 1] !==
'{')
1213 $tokens = $this->wrapBraces($tokens,
$i + 1,
$f - 1,
$i +
$f);
1218 while ($tokens[
$i +
$f + $d] !==
';' && $d <
$max)
1223 $tokens = array_merge(
1224 array_slice($tokens, 0,
$i),
1225 array_slice($tokens,
$i +
$f, $d),
1226 array_slice($tokens,
$i + 1,
$f - 1),
1227 array_slice($tokens,
$i +
$f + $d + 1,
count($tokens))
1232 return array_values($tokens);
1235 private function reconstructArray($tokens)
1239 if(is_array($tokens[
$i]) && $tokens[
$i][0] === T_VARIABLE && $tokens[
$i + 1] ===
'[')
1242 $has_more_keys =
true;
1246 while ($has_more_keys && $index < 20)
1249 if(($tokens[
$i + $c][0] === T_CONSTANT_ENCAPSED_STRING || $tokens[
$i + $c][0] === T_LNUMBER || $tokens[
$i + $c][0] === T_NUM_STRING) && $tokens[
$i + $c + 1] ===
']')
1251 unset($tokens[
$i + $c - 1]);
1252 $tokens[
$i][3][$index] = str_replace(
array(
'"',
"'"),
'', $tokens[
$i + $c][1]);
1253 unset($tokens[
$i + $c]);
1254 unset($tokens[
$i + $c + 1]);
1259 $tokens[
$i][3][$index] =
array();
1261 unset($tokens[
$i + $c - 1]);
1262 while ($braces !== 0 && $c < 100)
1264 if($tokens[
$i + $c] ===
'[')
1274 $tokens[
$i][3][$index][] = $tokens[
$i + $c];
1276 unset($tokens[
$i + $c]);
1279 unset($tokens[
$i + $c - 1]);
1281 if($tokens[
$i + $c] !==
'[')
1282 $has_more_keys =
false;
1290 return array_values($tokens);
1293 private function removeTernary($tokens)
1300 if($tokens[
$i] ===
'?')
1306 while (!(isset($tokens[
$i -
$k]) && ($tokens[
$i -
$k] ===
';' || $tokens[
$i -
$k] ===
', ' || $tokens[
$i -
$k] ===
'.' || $tokens[
$i -
$k] ===
'{' || $tokens[
$i -
$k] ===
'}') && $braces <= 0) && (
$i -
$k) > 0)
1308 if(isset($tokens[
$i -
$k]) && $tokens[
$i -
$k] ===
')')
1312 unset($tokens[
$i -
$k]);
1318 while (!(isset($tokens[
$i +
$k]) && ($tokens[
$i +
$k] ===
';' || $tokens[
$i +
$k] === ', ' || $tokens[
$i +
$k] ===
'.' || $tokens[
$i +
$k] ===
'}') && $braces <= 0) && (
$i +
$k) <
$max)
1320 if(isset($tokens[
$i +
$k]) && $tokens[
$i +
$k] ===
'(')
1324 unset($tokens[
$i +
$k]);
1332 return array_values($tokens);
1335 private function getTokensValue($file_name, $tokens,
$start = 0, $stop = 0)
1339 $stop =
count($tokens);
1342 if(is_array($tokens[
$i]))
1344 if($tokens[
$i][0] === T_VARIABLE
1345 || ($tokens[
$i][0] === T_STRING
1346 && (
$i + 1) < $stop && $tokens[
$i + 1] !==
'(')
1349 if(!in_array($tokens[
$i][1], $this->v_userinput))
1351 if($tokens[
$i][1] ===
'DIRECTORY_SEPARATOR' || $tokens[
$i][1] ===
'PATH_SEPARATOR')
1353 elseif(strtolower($tokens[
$i][1]) ===
'$componentpath')
1354 $value = dirname($file_name);
1356 $value .= $this->arParams['doc_root_path'];
1359 elseif($tokens[
$i][0] === T_CONSTANT_ENCAPSED_STRING
1363 $value .= substr($tokens[
$i][1], 1, -1);
1365 elseif($tokens[
$i][0] === T_ENCAPSED_AND_WHITESPACE)
1370 && (
$i > 2 && $tokens[
$i - 2][0] === T_STRING && $tokens[
$i - 2][1] ===
'dirname')
1373 $value = dirname($file_name).
'/';
1375 elseif($tokens[
$i][0] === T_LNUMBER || $tokens[
$i][0] === T_DNUMBER || $tokens[
$i][0] === T_NUM_STRING)
1389 private function getBraceEnd($tokens,
$i)
1394 while (!($braces === 0 || $tokens[
$i + $c] ===
';'))
1396 if($tokens[
$i + $c] ===
'(')
1404 if($c > 50 || $c >
$max)
1411 private function getColor($token)
1413 if(array_key_exists($token, $this->
color))
1414 return $this->
color[$token];
1419 private function highlightArray($token)
1422 foreach ($token as
$key)
1426 $result .=
'<span style="color: #007700;">[</span>';
1429 if(is_numeric(
$key))
1430 $result .=
'<span style="color: #0000BB;">'.$key.
'</span>';
1432 $result .=
'<span style="color: #DD0000;">\''.htmlentities(
$key, ENT_QUOTES,
'utf-8').
'\'</span>
';
1436 foreach ($key as $token)
1438 if(is_array($token))
1440 if(isset($token[3]))
1441 $result .= $this->highlightArray($token[3]);
1443 $result .= '<span
style=
"color: '.$this->getColor($token[0]).';">
'.htmlentities($token[1], ENT_QUOTES, 'utf-8
').'</span>
';
1446 $result .= "<span style=\"color: #007700;\">{$token}</span>";
1449 $result .= '<span
style=
"color: #007700;">]</span>
';
1455 private function highlightLine($line, $tokens = array(), $tainted_vars = array(), $comment = '')
1458 for ($i = 0, $count = count($tainted_vars); $i < $count; $i++)
1460 if($pos = strpos($tainted_vars[$i], '[
'))
1461 $tainted_vars[$i] = substr($tainted_vars[$i], 0, $pos);
1464 $output .= "<span>$line:</span> ";
1466 for ($i = 0, $count = count($tokens); $i < $count; $i++)
1468 $token = $tokens[$i];
1469 if(is_string($token))
1471 if($token === ',
' || $token === ';
')
1472 $output .= "<span style=\"color: #007700;\">$token </span>";
1473 elseif(in_array($token, $this->tokens_type['SPACE_WRAP_STR
']) || in_array($token, $this->tokens_type['ARITHMETIC_STR
']))
1474 $output .= '<span
style=
"color: #007700;">&
nbsp;
'.$token.'&
nbsp;</span>
';
1476 $output .= '<span
style=
"color: #007700;">
'.htmlentities($token, ENT_QUOTES, 'utf-8
').'</span>
';
1478 elseif(is_array($token)
1479 && $token[0] !== T_OPEN_TAG
1480 && $token[0] !== T_CLOSE_TAG
1484 if(in_array($token[0], $this->tokens_type['SPACE_WRAP
']) || in_array($token[0], $this->tokens_type['OPERATOR
']) || in_array($token[0], $this->tokens_type['ASSIGNMENT
']))
1486 $output .= '&
nbsp;<span
style=
"color: '.$this->getColor($token[0]).";\
">{$token[1]}</span> ";
1490 $text = htmlentities($token[1], ENT_QUOTES,
'utf-8');
1493 if($token[0] === T_FUNCTION)
1498 if($token[0] === T_VARIABLE && is_array($tainted_vars) && in_array($token[1], $tainted_vars))
1499 $span .=
"style=\"color: #0000BB;\"><b>".$text.
"</b></span>";
1501 $span .=
"style=\"color: ".$this->getColor($token[0]).
";\">$text</span>";
1505 if(isset($token[3]))
1507 $text .= $this->highlightArray($token[3]);
1511 if(in_array($token[0], $this->tokens_type[
'INCLUDES']) || in_array($token[0], $this->tokens_type[
'XSS']) || $token[0] ===
'T_EVAL')
1519 if(!empty($comment))
1521 $output .=
' <span style="color: #808080;">// '.htmlentities($comment, ENT_QUOTES,
'utf-8').
'</span>';
1524 return '<div style="clear:both;">'.$output.
'</div>';
1527 private function getVulnNodeTitle($func_name)
1529 if(isset($this->vuln_func[
'XSS'][$func_name]))
1531 elseif(isset($this->vuln_func[
'HTTP_HEADER'][$func_name]))
1532 $vulnname =
GetMessage(
'VULNSCAN_HEADER_NAME');
1533 elseif(isset($this->vuln_func[
'DATABASE'][$func_name]))
1534 $vulnname =
GetMessage(
'VULNSCAN_DATABASE_NAME');
1535 elseif(isset($this->vuln_func[
'FILE_INCLUDE'][$func_name]))
1536 $vulnname =
GetMessage(
'VULNSCAN_INCLUDE_NAME');
1537 elseif(isset($this->vuln_func[
'EXEC'][$func_name]))
1538 $vulnname =
GetMessage(
'VULNSCAN_EXEC_NAME');
1539 elseif(isset($this->vuln_func[
'CODE'][$func_name]))
1540 $vulnname =
GetMessage(
'VULNSCAN_CODE_NAME');
1541 elseif(isset($this->vuln_func[
'POP'][$func_name]))
1543 elseif(isset($this->vuln_func[
'OTHER'][$func_name]))
1544 $vulnname =
GetMessage(
'VULNSCAN_OTHER_NAME');
1551 private function getVulnNodeDescription($func_name)
1553 if(isset($this->vuln_func[
'XSS'][$func_name]))
1555 elseif(isset($this->vuln_func[
'HTTP_HEADER'][$func_name]))
1556 $vulnhelp =
GetMessage(
'VULNSCAN_HEADER_HELP');
1557 elseif(isset($this->vuln_func[
'DATABASE'][$func_name]))
1558 $vulnhelp =
GetMessage(
'VULNSCAN_DATABASE_HELP');
1559 elseif(isset($this->vuln_func[
'FILE_INCLUDE'][$func_name]))
1560 $vulnhelp =
GetMessage(
'VULNSCAN_INCLUDE_HELP');
1561 elseif(isset($this->vuln_func[
'EXEC'][$func_name]))
1562 $vulnhelp =
GetMessage(
'VULNSCAN_EXEC_HELP');
1563 elseif(isset($this->vuln_func[
'CODE'][$func_name]))
1564 $vulnhelp =
GetMessage(
'VULNSCAN_CODE_HELP');
1565 elseif(isset($this->vuln_func[
'POP'][$func_name]))
1567 elseif(isset($this->vuln_func[
'OTHER'][$func_name]))
1568 $vulnhelp =
GetMessage(
'VULNSCAN_OTHER_HELP');
1570 $vulnhelp =
GetMessage(
'VULNSCAN_UNKNOWN_HELP');
1575 private function getVulnName($func_name)
1577 if (isset($this->vuln_func[
'XSS'][$func_name]))
1579 elseif (isset($this->vuln_func[
'HTTP_HEADER'][$func_name]))
1581 elseif (isset($this->vuln_func[
'DATABASE'][$func_name]))
1583 elseif (isset($this->vuln_func[
'FILE_INCLUDE'][$func_name]))
1585 elseif (isset($this->vuln_func[
'EXEC'][$func_name]))
1587 elseif (isset($this->vuln_func[
'CODE'][$func_name]))
1589 elseif (isset($this->vuln_func[
'POP'][$func_name]))
1591 elseif (isset($this->vuln_func[
'OTHER'][$func_name]))
1597 private function traverseVar(
$var, $id = -1)
1600 if(isset($this->variables[
$var]))
1602 $cur_var = $this->variables[
$var];
1603 foreach ($cur_var->declares as $var_declare)
1605 if($var_declare->id < $id || $id === -1)
1607 foreach ($var_declare->tainted_vars as $taint_var)
1609 $res = $this->traverseVar($taint_var, $var_declare->id);
1614 $result .=
'<div class="checklist-vulnscan-code-line">';
1615 $result .= $this->highlightLine($var_declare->line, $var_declare->tokens, $var_declare->tainted_vars, $var_declare->comment);
1623 private function dependenciesTraverse($dependencies =
array())
1626 if(!empty($dependencies))
1630 foreach ($dependencies as $line => $dependency)
1632 if(!empty($dependency))
1634 $result .= $this->highlightLine($line, $dependency);
1641 private static function searchSimilarVuln(
$output,
$max)
1651 private function prepareOutput(
$output)
1656 if(($find = self::searchSimilarVuln(
$output,
$i)) !==
false)
1658 $output[$find]->additional_text .=
'<div class="checklist-vulnscan-dangerous-is-here">';
1660 $output[$find]->additional_text .=
'</div>';
1667 private function getHelp($category)
1687 $result .=
'<div class="checklist-vulnscan-helpbox-description">';
1690 $result .=
'<div class="checklist-vulnscan-helpbox-safe-title">';
1693 $result .=
'<div class="checklist-vulnscan-helpbox-safe-description">';
1702 $output = $this->prepareOutput($this->arResult);
1709 $filename =
htmlspecialcharsbx(str_replace(realpath(trim($this->arParams[
'doc_root_path'])),
'',str_replace(realpath(trim($this->arParams[
'path'])),
'', realpath(trim($vuln->filename)))));
1711 foreach ($vuln->tainted_vars as $tainted_var_name => $tainted_var)
1713 $result .=
'<div class="checklist-dot-line"></div><div class="checklist-vulnscan-files">'.
'<span class="checklist-vulnscan-filename">'.
GetMessage(
'VULNSCAN_FILE').
': '.
$filename.
'</span>'.
'<div id="'.$filename.
'">';
1714 $result .=
'<div class="checklist-vulnscan-vulnblock">'.
'<div class="checklist-vulnscan-vulnscan-blocktitle">'.
GetMessage(
'VULNSCAN_'.$this->getVulnName($vuln->name).
'_NAME').
'</div>';
1715 $result .=
'<div style="visibility: hidden; display:none;" class="checklist-vulnscan-helpbox" data-help="'.$filename.
'">'.$this->getHelp($vuln->name).
'</div>';
1718 $result .=
'<div class="checklist-vulnscan-dangerous-is-here">';
1719 $result .= $this->highlightLine($vuln->line, $vuln->tokens,
array($tainted_var_name), $vuln->comment);
1722 $result .=
'<div class="checklist-vulnscan-dependecies">';
1723 $result .= $this->dependenciesTraverse($vuln->dependencies);
1726 if(!empty($vuln->additional_text))
1727 $result .=
"\n".
'<div><div class="checklist-vulnscan-vulnblocktitle">'.
GetMessage(
'VULNSCAN_SIMILAR').
':</div><div class="checklist-vulnscan-codebox"><div class="checklist-vulnscan-code">'.$vuln->additional_text.
'</div></div></div>';
1730 $result .=
'</div></div></div>';
1740 static private function getFiles(
$path, $skip_preg, $file_types, $doc_root, &$files, &$dirs)
1745 while (($file = readdir(
$handle)) !==
false)
1747 if($file ===
'.' || $file ===
'..')
1750 $name =
$path.
'/'.str_replace(
"\\",
"/", $file);
1751 if (preg_match($skip_preg, str_replace($doc_root,
"",
$name)))
1769 static private function defineScanParams()
1771 if(!defined(
'T_INCLUDE_RESULT_MODIFIER'))
1772 define(
'T_INCLUDE_RESULT_MODIFIER', 10001);
1773 if(!defined(
'T_INCLUDE_COMPONENTTEMPLATE'))
1774 define(
'T_INCLUDE_COMPONENTTEMPLATE', 10002);
1775 if(!defined(
'T_INCLUDE_COMPONENT'))
1776 define(
'T_INCLUDE_COMPONENT', 10003);
1777 if(!defined(
'T_INCLUDE_END'))
1778 define(
'T_INCLUDE_END', 10004);
1793 '\.description\.php',
1794 '\.parameters\.php',
1795 'install\/[\w]*\.php',
1799 'FILE_TYPES' => Array(
1803 'PREG_FOR_SKIP_INCLUDE' =>
'/\/modules\/(bitrix\.)?[^\W\.]+\//is',
1804 'PREG_FOR_SKIP_SCAN' =>
'/(\/bitrix\/modules\/)|(\/bitrix\/components\/bitrix\/)|('.implode(
'$)|(', $SKIPDIR).
'$)|('.implode(
'$)|(', $SKIPFILE).
'$)/is',
1807 'MAX_ARRAY_ELEMENTS' => 50,
1809 'production_mode' =>
false,
1810 'path' =>
$_SERVER[
'DOCUMENT_ROOT'],
1811 'doc_root_path' =>
$_SERVER[
'DOCUMENT_ROOT']
1823 'LOOP_CONTROL' => Array(
1828 'FLOW_CONTROL' => Array(
1835 'ASSIGNMENT' => Array(
1848 'ASSIGNMENT_SECURE' => Array(
1859 'OPERATOR' => Array(
1861 T_IS_GREATER_OR_EQUAL,
1865 T_IS_SMALLER_OR_EQUAL
1867 'FUNCTIONS' => Array(
1871 'INCLUDES' => Array(
1876 T_INCLUDE_COMPONENT,
1877 T_INCLUDE_COMPONENTTEMPLATE,
1878 T_INCLUDE_RESULT_MODIFIER
1883 T_OPEN_TAG_WITH_ECHO,
1900 'SPACE_WRAP' => Array(
1914 'ARITHMETIC' => Array(
1918 'ARITHMETIC_STR' => Array(
1925 'SPACE_WRAP_STR' => Array(
1934 $arResult[
'SECURING_FUNCTIONS'] = Array(
1989 'phpformatdatetime',
1993 'INSTRING' => Array(
1997 'html_entity_decode',
2000 'htmlspecialcharsback',
2005 'htmlspecialcharsex',
2006 'htmlspecialcharsbx',
2017 'selectboxfromarray',
2026 'mysql_real_escape_string',
2044 $arResult[
'SECURING_FUNCTIONS'][
'QUOTE_ANALYSIS'] = Array(
$arResult[
'SECURING_FUNCTIONS'][
'SQL']);
2045 $arResult[
'SECURING_FUNCTIONS'][
'SECURES_ALL'] = array_merge(
2048 $arResult[
'SECURING_FUNCTIONS'][
'PREG'],
2049 $arResult[
'SECURING_FUNCTIONS'][
'FILE'],
2050 $arResult[
'SECURING_FUNCTIONS'][
'SYSTEM'],
2051 $arResult[
'SECURING_FUNCTIONS'][
'XPATH']
2061 'HTTP_HEADER' => Array(
2065 'assert' => Array(Array(1), Array()),
2066 'call_user_func' => Array(Array(1), Array()),
2067 'call_user_func_Array' => Array(Array(1), Array()),
2068 'create_function' => Array(Array(1, 2), Array()),
2069 'eval' => Array(Array(1), Array()),
2070 'mb_ereg_replace' => Array(Array(1, 2),
$arResult[
'SECURING_FUNCTIONS'][
'PREG']),
2071 'mb_eregi_replace' => Array(Array(1, 2),
$arResult[
'SECURING_FUNCTIONS'][
'PREG']),
2072 'ob_start' => Array(Array(1), Array()),
2076 'FILE_INCLUDE' => Array(
2077 'include' => Array(Array(1),
$arResult[
'SECURING_FUNCTIONS'][
'FILE']),
2078 'include_once' => Array(Array(1),
$arResult[
'SECURING_FUNCTIONS'][
'FILE']),
2079 'require' => Array(Array(1),
$arResult[
'SECURING_FUNCTIONS'][
'FILE']),
2080 'require_once' => Array(Array(1),
$arResult[
'SECURING_FUNCTIONS'][
'FILE']),
2081 'set_include_path' => Array(Array(1),
$arResult[
'SECURING_FUNCTIONS'][
'FILE']),
2084 'backticks' => Array(Array(1), Array()),
2085 'exec' => Array(Array(1), Array()),
2086 'passthru' => Array(Array(1), Array()),
2087 'pcntl_exec' => Array(Array(1),
$arResult[
'SECURING_FUNCTIONS'][
'SYSTEM']),
2088 'popen' => Array(Array(1),
$arResult[
'SECURING_FUNCTIONS'][
'SYSTEM']),
2089 'proc_open' => Array(Array(1),
$arResult[
'SECURING_FUNCTIONS'][
'SYSTEM']),
2090 'shell_exec' => Array(Array(1), Array()),
2091 'system' => Array(Array(1), Array()),
2092 'mail' => Array(Array(5), Array()),
2093 'bxmail' => Array(Array(5), Array())
2095 'DATABASE' => Array(
2096 'query' => Array(Array(1),
$arResult[
'SECURING_FUNCTIONS'][
'SQL']),
2097 'mysql_query' => Array(Array(1),
$arResult[
'SECURING_FUNCTIONS'][
'SQL'])
2100 'dl' => Array(Array(1), Array()),
2101 'ereg' => Array(Array(2), Array()),
2102 'eregi' => Array(Array(2), Array()),
2103 'sleep' => Array(Array(1), Array()),
2105 'unserialize' => Array(Array(1), Array()),
2112 'unserialize' => Array(Array(1), Array()),
2113 'is_a' => Array(Array(1), Array())
2126 '$HTTP_COOKIE_VARS',
2127 '$HTTP_REQUEST_VARS',
2129 '$HTTP_SERVER_VARS',
2131 '$HTTP_RAW_POST_DATA',
2142 T_DOLLAR_OPEN_CURLY_BRACES =>
'#007700',
2143 T_CURLY_OPEN =>
'#007700',
2144 T_OPEN_TAG =>
'#007700',
2145 T_CLOSE_TAG =>
'#007700',
2146 T_AND_EQUAL =>
'#007700',
2147 T_CONCAT_EQUAL =>
'#007700',
2148 T_DIV_EQUAL =>
'#007700',
2149 T_MINUS_EQUAL =>
'#007700',
2150 T_MOD_EQUAL =>
'#007700',
2151 T_MUL_EQUAL =>
'#007700',
2152 T_OR_EQUAL =>
'#007700',
2153 T_PLUS_EQUAL =>
'#007700',
2154 T_SL_EQUAL =>
'#007700',
2155 T_SR_EQUAL =>
'#007700',
2156 T_XOR_EQUAL =>
'#007700',
2157 T_IS_EQUAL =>
'#007700',
2158 T_IS_GREATER_OR_EQUAL =>
'#007700',
2159 T_IS_IDENTICAL =>
'#007700',
2160 T_IS_NOT_EQUAL =>
'#007700',
2161 T_IS_NOT_IDENTICAL =>
'#007700',
2164 T_OBJECT_OPERATOR =>
'#007700',
2166 T_SWITCH =>
'#007700',
2167 T_WHILE =>
'#007700',
2169 T_EXIT =>
'#007700',
2171 T_CATCH =>
'#007700',
2172 T_ISSET =>
'#007700',
2174 T_FOREACH =>
'#007700',
2175 T_RETURN =>
'#007700',
2176 T_DOUBLE_ARROW =>
'#007700',
2178 T_CASE =>
'#007700',
2179 T_DEFAULT =>
'#007700',
2180 T_BREAK =>
'#007700',
2181 T_CONTINUE =>
'#007700',
2182 T_GOTO =>
'#007700',
2183 T_GLOBAL =>
'#007700',
2184 T_LOGICAL_AND =>
'#007700',
2185 T_LOGICAL_OR =>
'#007700',
2186 T_EMPTY =>
'#007700',
2187 T_UNSET =>
'#007700',
2188 T_ELSE =>
'#007700',
2189 T_ELSEIF =>
'#007700',
2190 T_LIST =>
'#007700',
2191 T_ARRAY =>
'#007700',
2192 T_ECHO =>
'#007700',
2193 T_START_HEREDOC =>
'#007700',
2194 T_END_HEREDOC =>
'#007700',
2195 T_FUNCTION =>
'#007700',
2196 T_PUBLIC =>
'#007700',
2197 T_PRIVATE =>
'#007700',
2198 T_PROTECTED =>
'#007700',
2199 T_STATIC =>
'#007700',
2200 T_CLASS =>
'#007700',
2202 T_PRINT =>
'#007700',
2203 T_INCLUDE =>
'#007700',
2204 T_INCLUDE_ONCE =>
'#007700',
2205 T_REQUIRE =>
'#007700',
2206 T_REQUIRE_ONCE =>
'#007700',
2209 T_BOOL_CAST =>
'#007700',
2210 T_DOUBLE_CAST =>
'#007700',
2211 T_INT_CAST =>
'#007700',
2212 T_UNSET_CAST =>
'#007700',
2213 T_BOOLEAN_OR =>
'#007700',
2214 T_BOOLEAN_AND =>
'#007700',
2215 T_FILE =>
'#007700',
2216 T_LINE =>
'#007700',
2218 T_FUNC_C =>
'#007700',
2219 T_CLASS_C =>
'#007700',
2220 T_METHOD_C =>
'#007700',
2221 T_NS_C =>
'#007700',
2222 T_CONST =>
'#0000BB',
2223 T_VARIABLE =>
'#0000BB',
2224 T_STRING_VARNAME =>
'#0000BB',
2225 T_STRING =>
'#0000BB',
2226 T_EVAL =>
'#0000BB',
2227 T_LNUMBER =>
'#0000BB',
2228 T_ENCAPSED_AND_WHITESPACE =>
'#DD0000;',
2229 T_CONSTANT_ENCAPSED_STRING =>
'#DD0000;',
2230 T_INLINE_HTML =>
'#000000;',
2231 T_COMMENT =>
'#FF8000;',
2232 T_DOC_COMMENT =>
'#FF8000;'
2234 ini_set(
'auto_detect_line_endings', 1);
2235 ini_set(
'short_open_tag', 1);
2240 static private function getCurTemplate(
$path, $mp_mode=
false)
2244 $dbSiteRes=CSite::GetTemplateList(CSite::GetSiteByFullPath(
$path,
true));
2245 if(($arSiteRes = $dbSiteRes->Fetch()) !==
false)
2246 return $arSiteRes[
'TEMPLATE'];
2252 if(extension_loaded(
'tokenizer') ===
true)
2254 if(empty(\
Bitrix\Main\Application::getInstance()->getSession()[
'BX_CHECKLIST'][
$arParams[
'TEST_ID']]))
2258 $arScanParams = self::defineScanParams();
2259 $phpMaxExecutionTime = ini_get(
"max_execution_time");
2260 $arScanParams[
'time_out'] = $phpMaxExecutionTime > 0 ? $phpMaxExecutionTime - 2: 30;
2261 $arScanParams[
'time_start'] = time();
2262 $arScanParams[
'MP_mode'] =
false;
2268 $NS[
'CUR_FILE_ID'] = 0;
2272 $arScanParams[
'path'],
2273 $arScanParams[
'PREG_FOR_SKIP_SCAN'],
2274 $arScanParams[
'FILE_TYPES'],
2275 $arScanParams[
'path'],
2279 $NS[
'VULN_COUNT'] = 0;
2280 $NS[
'STUCK_FILE'] = -1;
2281 $NS[
'MESSAGE'] = Array();
2284 $time_end = $arScanParams[
'time_start'] + $arScanParams[
'time_out'];
2285 while (
$NS[
'DIR_LIST'] && $time_end > time())
2287 $dir = array_shift(
$NS[
'DIR_LIST']);
2290 $arScanParams[
'PREG_FOR_SKIP_SCAN'],
2291 $arScanParams[
'FILE_TYPES'],
2292 $arScanParams[
'path'],
2298 if (
$NS[
'DIR_LIST'])
2301 'IN_PROGRESS' =>
'Y',
2309 if(is_file($file =
$NS[
'FILE_LIST'][
$NS[
'CUR_FILE_ID']]))
2316 $scan =
new CVulnScanner($file, $arScanParams, self::getCurTemplate($file, $arScanParams[
'MP_mode']));
2320 if($scan->vuln_count > 0)
2322 $NS[
'MESSAGE'][
$NS[
'CUR_FILE_ID']][
'VULN_COUNT'] = $scan->vuln_count;
2323 $NS[
'MESSAGE'][
$NS[
'CUR_FILE_ID']][
'OUTPUT'] = $scan->getOutput();
2325 $NS[
'CUR_FILE_ID']++;
2329 if(
$NS[
'STUCK_FILE'] ===
$NS[
'CUR_FILE_ID'])
2331 $NS[
'CUR_FILE_ID']++;
2332 $NS[
'STUCK_FILE'] = -1;
2335 $NS[
'STUCK_FILE'] =
$NS[
'CUR_FILE_ID'];
2340 $NS[
'CUR_FILE_ID']++;
2345 if(!(
$NS[
'CUR_FILE_ID'] <
count(
$NS[
'FILE_LIST'])))
2347 $arDetailReport =
'';
2349 foreach (
$NS[
'MESSAGE'] as $file_output)
2350 if (!empty($file_output))
2351 if (!str_contains($arDetailReport, $file_output[
'OUTPUT']))
2353 $arDetailReport .= $file_output[
'OUTPUT'];
2354 $vulnCount += $file_output[
'VULN_COUNT'];
2357 unset(\
Bitrix\Main\Application::getInstance()->getSession()[
'BX_CHECKLIST'][
$arParams[
'TEST_ID']]);
2362 'PROBLEM_COUNT' => $vulnCount,
2363 'DETAIL' => $arDetailReport
2365 'STATUS' => ($vulnCount > 0 ?
false :
true)
2370 $percent = round((
$NS[
'CUR_FILE_ID']) / (
count(
$NS[
'FILE_LIST']) * 0.01), 0);
2372 'IN_PROGRESS' =>
'Y',
2373 'PERCENT' => number_format($percent, 2),
2381 'PREVIEW' =>
GetMessage(
'VULNSCAN_TOKENIZER_NOT_INSTALLED'),
return[Dependency::CONTAINER=> Container::class, Dependency::IBLOCK_INFO=> IblockInfo::class, Dependency::PRODUCT_CONVERTER=> ProductConverter::class, Dependency::REPOSITORY_FACADE=> Repository::class, Dependency::PRODUCT_FACTORY=> ProductFactory::class, Dependency::PRODUCT_REPOSITORY=> ProductRepository::class, ProductFactory::PRODUCT=> Product::class, Dependency::SECTION_FACTORY=> SectionFactory::class, Dependency::SECTION_REPOSITORY=> SectionRepository::class, SectionFactory::SECTION=> Section::class, SectionFactory::SECTION_COLLECTION=> SectionCollection::class, Dependency::SKU_FACTORY=> SkuFactory::class, Dependency::SKU_REPOSITORY=> SkuRepository::class, SkuFactory::SIMPLE_SKU=> SimpleSku::class, SkuFactory::SKU=> Sku::class, SkuFactory::SKU_COLLECTION=> SkuCollection::class, Dependency::PROPERTY_FACTORY=> PropertyFactory::class, Dependency::PROPERTY_REPOSITORY=> PropertyRepository::class, PropertyFactory::PROPERTY=> Property::class, PropertyFactory::PROPERTY_COLLECTION=> PropertyCollection::class, Dependency::PROPERTY_VALUE_FACTORY=> PropertyValueFactory::class, PropertyValueFactory::PROPERTY_VALUE=> PropertyValue::class, PropertyValueFactory::PROPERTY_VALUE_COLLECTION=> PropertyValueCollection::class, Dependency::PROPERTY_FEATURE_FACTORY=> PropertyFeatureFactory::class, Dependency::PROPERTY_FEATURE_REPOSITORY=> PropertyFeatureRepository::class, PropertyFeatureFactory::PROPERTY_FEATURE=> PropertyFeature::class, PropertyFeatureFactory::PROPERTY_FEATURE_COLLECTION=> PropertyFeatureCollection::class, Dependency::PRICE_FACTORY=> PriceFactory::class, Dependency::PRICE_REPOSITORY=> PriceRepository::class, PriceFactory::SIMPLE_PRICE=> SimplePrice::class, PriceFactory::QUANTITY_DEPENDENT_PRICE=> QuantityDependentPrice::class, PriceFactory::PRICE_COLLECTION=> PriceCollection::class, Dependency::IMAGE_FACTORY=> ImageFactory::class, Dependency::IMAGE_REPOSITORY=> ImageRepository::class, ImageFactory::DETAIL_IMAGE=> DetailImage::class, ImageFactory::PREVIEW_IMAGE=> PreviewImage::class, ImageFactory::MORE_PHOTO_IMAGE=> MorePhotoImage::class, ImageFactory::IMAGE_COLLECTION=> ImageCollection::class, Dependency::MEASURE_RATIO_FACTORY=> MeasureRatioFactory::class, Dependency::MEASURE_RATIO_REPOSITORY=> MeasureRatioRepository::class, MeasureRatioFactory::SIMPLE_MEASURE_RATIO=> SimpleMeasureRatio::class, MeasureRatioFactory::MEASURE_RATIO_COLLECTION=> MeasureRatioCollection::class, Dependency::BARCODE_FACTORY=> BarcodeFactory::class, Dependency::BARCODE_REPOSITORY=> BarcodeRepository::class, BarcodeFactory::BARCODE=> Barcode::class, BarcodeFactory::BARCODE_COLLECTION=> BarcodeCollection::class, Dependency::STORE_PRODUCT_FACTORY=> StoreProductFactory::class, Dependency::STORE_PRODUCT_REPOSITORY=> StoreProductRepository::class, StoreProductFactory::STORE_PRODUCT=> StoreProduct::class, StoreProductFactory::STORE_PRODUCT_COLLECTION=> StoreProductCollection::class, 'sku.tree'=> SkuTree::class, 'integration.seo.facebook.facade'=> FacebookFacade::class, 'integration.seo.facebook.product.processor'=> FacebookProductProcessor::class, 'integration.seo.facebook.product.repository'=> FacebookProductRepository::class,]