Skip to content

Commit

Permalink
Implement SSRF
Browse files Browse the repository at this point in the history
  • Loading branch information
estringana committed Jan 3, 2025
1 parent c69df0a commit 97358f8
Show file tree
Hide file tree
Showing 2 changed files with 53 additions and 17 deletions.
25 changes: 13 additions & 12 deletions src/DDTrace/Integrations/Filesystem/FilesystemIntegration.php
Original file line number Diff line number Diff line change
Expand Up @@ -51,20 +51,21 @@ public function init(): int
private static function preHook($variant)
{
return static function (HookData $hook) use ($variant) {
if (count($hook->args) == 0 || !is_string($hook->args[0])) {
return;
}
if (count($hook->args) == 0 || !is_string($hook->args[0])) {
return;
}

$protocol = [];
if (
preg_match('/^[a-z]+\:\/\//', $hook->args[0], $protocol) &&
isset($protocol[0]) &&
$protocol[0] !== 'file')
{
return;
}
$protocol = [];
$uri_parsed = preg_match('/^([a-z]+)\:\/\//', $hook->args[0], $protocol);
$protocol = isset($protocol[1]) ? $protocol[1]: "";

\datadog\appsec\push_address("server.io.fs.file", $hook->args[0], true);
if (empty($protocol) || $protocol === 'file') {
\datadog\appsec\push_address("server.io.fs.file", $hook->args[0], true);
}

if (in_array($variant, ['file_get_contents', 'fopen']) && (empty($protocol) || $protocol === 'http')) {
\datadog\appsec\push_address("server.io.net.url", $hook->args[0], true);
}
};
}

Expand Down
45 changes: 40 additions & 5 deletions tests/Integrations/Filesystem/FilesystemTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,23 @@ protected static function getAppIndexScript()
return __DIR__ . '/index.php';
}

protected function assertEvent(string $value, $traces)
protected static function getEnvs()
{
return array_merge(parent::getEnvs(), [
'DD_APPSEC_RASP_ENABLED' => true
]);
}

protected function assertEvent(string $value, $traces, $also_ssrf = false)
{
$events = AppsecStatus::getInstance()->getEvents();
$this->assertEquals(1, count($events));
$this->assertEquals($also_ssrf ? 2 : 1, count($events));
$this->assertEquals($value, $events[0]["server.io.fs.file"]);
if ($also_ssrf) {
$this->assertEquals($value, $events[1]["server.io.net.url"]);
}
$this->assertEquals('push_address', $events[0]['eventName']);
$this->assertTrue($events[0]['rasp']);
$this->assertGreaterThanOrEqual(0.0, $traces[0][0]['metrics']['_dd.appsec.rasp.duration_ext']);
}

public function testFileGetContents()
Expand All @@ -32,7 +41,33 @@ public function testFileGetContents()
TestCase::assertSame('OK', $response);
});

$this->assertEvent('./index.php', $traces);
$this->assertEvent('./index.php', $traces, true);
}

public function testFileProtocol()
{
$file = __DIR__ . '/index.php';
$traces = $this->tracesFromWebRequest(function () use ($file) {
$response = $this->call(GetSpec::create('Root', '/?function=fopen&path=file://'.$file));
TestCase::assertSame('OK', $response);
});

$this->assertEvent('file://'. $file, $traces);
}

public function testHttpProtocol()
{
$file = 'http://example.com';
$traces = $this->tracesFromWebRequest(function () use ($file) {
$response = $this->call(GetSpec::create('Root', '/?function=fopen&path='.$file));
TestCase::assertSame('OK', $response);
});

$events = AppsecStatus::getInstance()->getEvents();
$this->assertEquals(1, count($events));
$this->assertEquals($file, $events[0]["server.io.net.url"]);
$this->assertEquals('push_address', $events[0]['eventName']);
$this->assertTrue($events[0]['rasp']);
}

public function testFilePutContents()
Expand All @@ -50,7 +85,7 @@ public function testFopen()
$response = $this->call(GetSpec::create('Root', '/?function=fopen&path=./index.php'));
TestCase::assertSame('OK', $response);
});
$this->assertEvent('./index.php', $traces);
$this->assertEvent('./index.php', $traces, true);
}

public function testReadFile()
Expand Down

0 comments on commit 97358f8

Please sign in to comment.