Skip to content

Commit

Permalink
Merge pull request #10183 from cgocast/master
Browse files Browse the repository at this point in the history
Detect DoS by sleep #10178
  • Loading branch information
orklah authored Sep 29, 2023
2 parents 4746f83 + b706d38 commit 1b12255
Show file tree
Hide file tree
Showing 11 changed files with 91 additions and 2 deletions.
2 changes: 1 addition & 1 deletion UPGRADING.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@

- [BC] The `TDependentListKey` type was removed and replaced with an optional property of the `TIntRange` type.

- [BC] Value of constant `Psalm\Type\TaintKindGroup::ALL_INPUT` changed to reflect a new `TaintKind::INPUT_XPATH` have been added. Accordingly, default values for `$taint` parameters of `Psalm\Codebase::addTaintSource()` and `Psalm\Codebase::addTaintSink()` have been changed as well.
- [BC] Value of constant `Psalm\Type\TaintKindGroup::ALL_INPUT` changed to reflect new `TaintKind::INPUT_SLEEP` and `TaintKind::INPUT_XPATH` have been added. Accordingly, default values for `$taint` parameters of `Psalm\Codebase::addTaintSource()` and `Psalm\Codebase::addTaintSink()` have been changed as well.

- [BC] Property `Config::$shepherd_host` was replaced with `Config::$shepherd_endpoint`

Expand Down
1 change: 1 addition & 0 deletions config.xsd
Original file line number Diff line number Diff line change
Expand Up @@ -439,6 +439,7 @@
<xs:element name="TaintedInput" type="IssueHandlerType" minOccurs="0" />
<xs:element name="TaintedLdap" type="IssueHandlerType" minOccurs="0" />
<xs:element name="TaintedShell" type="IssueHandlerType" minOccurs="0" />
<xs:element name="TaintedSleep" type="IssueHandlerType" minOccurs="0" />
<xs:element name="TaintedSql" type="IssueHandlerType" minOccurs="0" />
<xs:element name="TaintedSSRF" type="IssueHandlerType" minOccurs="0" />
<xs:element name="TaintedSystemSecret" type="IssueHandlerType" minOccurs="0" />
Expand Down
1 change: 1 addition & 0 deletions docs/running_psalm/error_levels.md
Original file line number Diff line number Diff line change
Expand Up @@ -293,6 +293,7 @@ Level 5 and above allows a more non-verifiable code, and higher levels are even
- [TaintedInput](issues/TaintedInput.md)
- [TaintedLdap](issues/TaintedLdap.md)
- [TaintedShell](issues/TaintedShell.md)
- [TaintedSleep](issues/TaintedSleep.md)
- [TaintedSql](issues/TaintedSql.md)
- [TaintedSSRF](issues/TaintedSSRF.md)
- [TaintedSystemSecret](issues/TaintedSystemSecret.md)
Expand Down
1 change: 1 addition & 0 deletions docs/running_psalm/issues.md
Original file line number Diff line number Diff line change
Expand Up @@ -241,6 +241,7 @@
- [TaintedInput](issues/TaintedInput.md)
- [TaintedLdap](issues/TaintedLdap.md)
- [TaintedShell](issues/TaintedShell.md)
- [TaintedSleep](issues/TaintedSleep.md)
- [TaintedSql](issues/TaintedSql.md)
- [TaintedSSRF](issues/TaintedSSRF.md)
- [TaintedSystemSecret](issues/TaintedSystemSecret.md)
Expand Down
9 changes: 9 additions & 0 deletions docs/running_psalm/issues/TaintedSleep.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# TaintedSleep

Emitted when user-controlled input can be passed into a `sleep` call or similar.

```php
<?php

sleep($_GET["seconds"]);
```
10 changes: 10 additions & 0 deletions src/Psalm/Internal/Codebase/TaintFlowGraph.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
use Psalm\Issue\TaintedLdap;
use Psalm\Issue\TaintedSSRF;
use Psalm\Issue\TaintedShell;
use Psalm\Issue\TaintedSleep;
use Psalm\Issue\TaintedSql;
use Psalm\Issue\TaintedSystemSecret;
use Psalm\Issue\TaintedTextWithQuotes;
Expand Down Expand Up @@ -459,6 +460,15 @@ private function getChildNodes(
);
break;

case TaintKind::INPUT_SLEEP:
$issue = new TaintedSleep(
'Detected tainted sleep',
$issue_location,
$issue_trace,
$path,
);
break;

default:
$issue = new TaintedCustom(
'Detected tainted ' . $matching_taint,
Expand Down
8 changes: 8 additions & 0 deletions src/Psalm/Issue/TaintedSleep.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?php

namespace Psalm\Issue;

final class TaintedSleep extends TaintedInput
{
public const SHORTCODE = 324;
}
1 change: 1 addition & 0 deletions src/Psalm/Type/TaintKind.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ final class TaintKind
public const INPUT_COOKIE = 'cookie';
public const INPUT_HEADER = 'header';
public const INPUT_XPATH = 'xpath';
public const INPUT_SLEEP = 'sleep';
public const USER_SECRET = 'user_secret';
public const SYSTEM_SECRET = 'system_secret';
}
1 change: 1 addition & 0 deletions src/Psalm/Type/TaintKindGroup.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,5 +22,6 @@ final class TaintKindGroup
TaintKind::INPUT_HEADER,
TaintKind::INPUT_COOKIE,
TaintKind::INPUT_XPATH,
TaintKind::INPUT_SLEEP,
];
}
22 changes: 22 additions & 0 deletions stubs/CoreGenericFunctions.phpstub
Original file line number Diff line number Diff line change
Expand Up @@ -1797,3 +1797,25 @@ if (defined('GLOB_BRACE')) {
* @psalm-taint-sink shell $command
*/
function exec(string $command, &$output = null, int &$result_code = null): string|false {}

/**
* @psalm-taint-specialize
* @psalm-taint-sink sleep $seconds
*/
function sleep(int $seconds): int {}

/**
* @psalm-taint-sink sleep $microseconds
*/
function usleep(int $microseconds): void {}

/**
* @psalm-taint-sink sleep $seconds
* @psalm-taint-sink sleep $nanoseconds
*/
function time_nanosleep(int $seconds, int $nanoseconds): array|bool {}

/**
* @psalm-taint-sink sleep $timestamp
*/
function time_sleep_until(float $timestamp): bool {}
37 changes: 36 additions & 1 deletion tests/TaintTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -755,14 +755,24 @@ function bar(array $arr): void {
/**
* @psalm-taint-escape xpath
*/
function my_escaping_function_for_xpath(string input) : string {};
function my_escaping_function_for_xpath(string $input) : string {};
function queryExpression(SimpleXMLElement $xml) : array|false|null {
$expression = $_GET["expression"];
$expression = my_escaping_function_for_xpath($expression);
return $xml->xpath($expression);
}',
],
'escapeSeconds' => [
'code' => '<?php
/**
* @psalm-taint-escape sleep
*/
function my_escaping_function_for_seconds(mixed $input) : int {};
$seconds = my_escaping_function_for_seconds($_GET["seconds"]);
sleep($seconds);',
],
];
}

Expand Down Expand Up @@ -2540,6 +2550,31 @@ function evaluateExpression(DOMXPath $xpath) : mixed {
}',
'error_message' => 'TaintedXpath',
],
'taintedSleep' => [
'code' => '<?php
sleep($_GET["seconds"]);',
'error_message' => 'TaintedSleep',
],
'taintedUsleep' => [
'code' => '<?php
usleep($_GET["microseconds"]);',
'error_message' => 'TaintedSleep',
],
'taintedTimeNanosleepSeconds' => [
'code' => '<?php
time_nanosleep($_GET["seconds"], 42);',
'error_message' => 'TaintedSleep',
],
'taintedTimeNanosleepNanoseconds' => [
'code' => '<?php
time_nanosleep(42, $_GET["nanoseconds"]);',
'error_message' => 'TaintedSleep',
],
'taintedTimeSleepUntil' => [
'code' => '<?php
time_sleep_until($_GET["timestamp"]);',
'error_message' => 'TaintedSleep',
],
];
}

Expand Down

0 comments on commit 1b12255

Please sign in to comment.