mirror of
https://github.com/danog/psalm.git
synced 2024-11-26 20:34:47 +01:00
Improve taint protection for exec-related commands
This commit is contained in:
parent
2b2988b072
commit
c3949e3194
@ -957,6 +957,10 @@ class PropertyAssignmentAnalyzer
|
||||
new CodeLocation($statements_analyzer->getSource(), $stmt)
|
||||
);
|
||||
|
||||
if ($assignment_value_type->tainted) {
|
||||
$method_source->taint = $assignment_value_type->tainted;
|
||||
}
|
||||
|
||||
if ($codebase->taint->hasPreviousSink($method_source)) {
|
||||
if ($assignment_value_type->sources) {
|
||||
$codebase->taint->addSinks(
|
||||
@ -970,9 +974,13 @@ class PropertyAssignmentAnalyzer
|
||||
|
||||
if ($assignment_value_type->sources) {
|
||||
foreach ($assignment_value_type->sources as $type_source) {
|
||||
if ($codebase->taint->hasPreviousSource($type_source)
|
||||
if (($previous_source = $codebase->taint->hasPreviousSource($type_source))
|
||||
|| $assignment_value_type->tainted
|
||||
) {
|
||||
if ($previous_source) {
|
||||
$method_source->taint = $previous_source->taint;
|
||||
}
|
||||
|
||||
$codebase->taint->addSources(
|
||||
$statements_analyzer,
|
||||
[$method_source],
|
||||
|
@ -161,7 +161,7 @@ class ArrayFetchAnalyzer
|
||||
null
|
||||
);
|
||||
|
||||
if ($array_var_id === '$_GET' || $array_var_id === '$_POST') {
|
||||
if ($array_var_id === '$_GET' || $array_var_id === '$_POST' || $array_var_id === '$_COOKIE') {
|
||||
$stmt->inferredType->tainted = (int) Type\Union::TAINTED_INPUT;
|
||||
$stmt->inferredType->sources = [
|
||||
new TypeSource(
|
||||
|
@ -859,6 +859,7 @@ class PropertyFetchAnalyzer
|
||||
|
||||
if ($tainted_source = $codebase->taint->hasPreviousSource($method_source)) {
|
||||
$type->tainted = $tainted_source->taint;
|
||||
$method_source->taint = $type->tainted;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -209,6 +209,8 @@ class CallMap
|
||||
|
||||
$function_params = [];
|
||||
|
||||
$arg_offset = 0;
|
||||
|
||||
/** @var string $arg_name - key type changed with above array_shift */
|
||||
foreach ($call_map_function_args as $arg_name => $arg_type) {
|
||||
$by_reference = false;
|
||||
@ -245,9 +247,23 @@ class CallMap
|
||||
$variadic
|
||||
);
|
||||
|
||||
if ($arg_offset === 0
|
||||
&& ($function_id === 'exec'
|
||||
|| $function_id === 'shell_exec'
|
||||
|| $function_id === 'passthru'
|
||||
|| $function_id === 'system'
|
||||
|| $function_id === 'pcntl_exec'
|
||||
|| $function_id === 'file_put_contents'
|
||||
|| $function_id === 'fopen')
|
||||
) {
|
||||
$function_param->sink = Type\Union::TAINTED_INPUT_SHELL;
|
||||
}
|
||||
|
||||
$function_param->signature_type = null;
|
||||
|
||||
$function_params[] = $function_param;
|
||||
|
||||
$arg_offset++;
|
||||
}
|
||||
|
||||
$possible_callables[] = new TCallable('callable', $function_params, $return_type);
|
||||
|
@ -305,7 +305,7 @@ class Functions
|
||||
'newrelic_set_appname',
|
||||
|
||||
// execution
|
||||
'shell_exec', 'exec', 'system', 'passthru',
|
||||
'shell_exec', 'exec', 'system', 'passthru', 'pcntl_exec',
|
||||
|
||||
// well-known functions
|
||||
'libxml_use_internal_errors', 'array_map', 'curl_exec',
|
||||
|
@ -751,4 +751,23 @@ class TaintTest extends TestCase
|
||||
|
||||
$this->analyzeFile('somefile.php', new Context());
|
||||
}
|
||||
|
||||
public function testTaintIntoExec() : void
|
||||
{
|
||||
$this->expectException(\Psalm\Exception\CodeException::class);
|
||||
$this->expectExceptionMessage('TaintedInput');
|
||||
|
||||
$this->project_analyzer->trackTaintedInputs();
|
||||
|
||||
$this->addFile(
|
||||
'somefile.php',
|
||||
'<?php
|
||||
function foo() : void {
|
||||
$a = (string) $_GET["bad"];
|
||||
exec($a);
|
||||
}'
|
||||
);
|
||||
|
||||
$this->analyzeFile('somefile.php', new Context());
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user