Skip to content

Commit

Permalink
Wrap lfi functions
Browse files Browse the repository at this point in the history
  • Loading branch information
estringana committed Jul 23, 2024
1 parent fd59f83 commit d027f9d
Show file tree
Hide file tree
Showing 7 changed files with 181 additions and 0 deletions.
2 changes: 2 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -1169,6 +1169,8 @@ test_integrations_amqp35: global_test_run_dependencies
test_integrations_deferred_loading: global_test_run_dependencies
$(MAKE) test_scenario_predis1
$(call run_tests_debug,tests/Integrations/DeferredLoading)
test_integrations_filesystem: global_test_run_dependencies
$(call run_tests_debug,tests/Integrations/Filesystem)
test_integrations_curl: global_test_run_dependencies
$(call run_tests_debug,tests/Integrations/Curl)
test_integrations_elasticsearch1: global_test_run_dependencies
Expand Down
9 changes: 9 additions & 0 deletions ext/integrations/integrations.c
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,15 @@ void ddtrace_integrations_minit(void) {
DD_SET_UP_DEFERRED_LOADING_BY_FUNCTION(DDTRACE_INTEGRATION_EXEC, "proc_open",
"DDTrace\\Integrations\\Exec\\ExecIntegration");

DD_SET_UP_DEFERRED_LOADING_BY_FUNCTION(DDTRACE_INTEGRATION_FILESYSTEM, "file_get_contents",
"DDTrace\\Integrations\\Filesystem\\FilesystemIntegration");
DD_SET_UP_DEFERRED_LOADING_BY_FUNCTION(DDTRACE_INTEGRATION_FILESYSTEM, "file_put_contents",
"DDTrace\\Integrations\\Filesystem\\FilesystemIntegration");
DD_SET_UP_DEFERRED_LOADING_BY_FUNCTION(DDTRACE_INTEGRATION_FILESYSTEM, "fopen", "DDTrace\\Integrations\\Filesystem\\FilesystemIntegration");
DD_SET_UP_DEFERRED_LOADING_BY_FUNCTION(DDTRACE_INTEGRATION_FILESYSTEM, "readfile", "DDTrace\\Integrations\\Filesystem\\FilesystemIntegration");
DD_SET_UP_DEFERRED_LOADING_BY_FUNCTION(DDTRACE_INTEGRATION_FILESYSTEM, "stat", "DDTrace\\Integrations\\Filesystem\\FilesystemIntegration");
DD_SET_UP_DEFERRED_LOADING_BY_FUNCTION(DDTRACE_INTEGRATION_FILESYSTEM, "lstat", "DDTrace\\Integrations\\Filesystem\\FilesystemIntegration");

DD_SET_UP_DEFERRED_LOADING_BY_FUNCTION(DDTRACE_INTEGRATION_CURL, "curl_exec",
"DDTrace\\Integrations\\Curl\\CurlIntegration");
DD_SET_UP_DEFERRED_LOADING_BY_FUNCTION(DDTRACE_INTEGRATION_CURL, "curl_multi_exec",
Expand Down
1 change: 1 addition & 0 deletions ext/integrations/integrations.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
INTEGRATION(CAKEPHP, "cakephp") \
INTEGRATION(CODEIGNITER, "codeigniter") \
INTEGRATION(EXEC, "exec") \
INTEGRATION(FILESYSTEM, "filesystem") \
INTEGRATION(CURL, "curl") \
INTEGRATION(DRUPAL, "drupal") \
INTEGRATION(ELASTICSEARCH, "elasticsearch") \
Expand Down
68 changes: 68 additions & 0 deletions src/DDTrace/Integrations/Filesystem/FilesystemIntegration.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
<?php

namespace DDTrace\Integrations\Filesystem;

use DDTrace\HookData;
use DDTrace\Integrations\Integration;

class FilesystemIntegration extends Integration
{
const NAME = "filesystem";

public function init(): int
{
\DDTrace\install_hook(
'file_get_contents',
self::preHook('file_get_contents'),
null
);

\DDTrace\install_hook(
'file_put_contents',
self::preHook('file_put_contents'),
null
);

\DDTrace\install_hook(
'fopen',
self::preHook('fopen'),
null
);

\DDTrace\install_hook(
'readfile',
self::preHook('readfile'),
null
);

\DDTrace\install_hook(
'stat',
self::preHook('stat'),
null
);


\DDTrace\install_hook(
'lstat',
self::preHook('lstat'),
null
);

return Integration::LOADED;
}

private static function preHook($variant)
{
return static function (HookData $hook) use ($variant) {
if (count($hook->args) == 0 || !is_string($hook->args[0])) {
return;
}

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

}
80 changes: 80 additions & 0 deletions tests/Integrations/Filesystem/FilesystemTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
<?php

namespace DDTrace\Tests\Integrations\DeferredLoading;

use DDTrace\Tests\Common\SpanAssertion;
use DDTrace\Tests\Common\AppsecTestCase;
use DDTrace\Tests\Frameworks\Util\Request\GetSpec;
use PHPUnit\Framework\TestCase;
use datadog\appsec\AppsecStatus;

final class FilesystemTest extends AppsecTestCase
{
protected static function getAppIndexScript()
{
return __DIR__ . '/index.php';
}

protected function assertEvent(string $value)
{
$events = AppsecStatus::getInstance()->getEvents();
$this->assertEquals(1, count($events));
$this->assertEquals($value, $events[0]["server.io.fs.file"]);
$this->assertEquals('push_address', $events[0]['eventName']);
}

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

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

public function testFilePutContents()
{
$traces = $this->tracesFromWebRequest(function () {
$response = $this->call(GetSpec::create('Root', '/?function=file_put_contents&path=./somefile'));
TestCase::assertSame('OK', $response);
});
$this->assertEvent('./somefile');
}

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

public function testReadFile()
{
$traces = $this->tracesFromWebRequest(function () {
$response = $this->call(GetSpec::create('Root', '/?function=readfile&path=./dummy'));
TestCase::assertSame("Dummy file content\nOK", $response);
});
$this->assertEvent('./dummy');
}

public function testStat()
{
$traces = $this->tracesFromWebRequest(function () {
$response = $this->call(GetSpec::create('Root', '/?function=stat&path=./dummy'));
TestCase::assertSame("OK", $response);
});
$this->assertEvent('./dummy');
}

public function testLstat()
{
$traces = $this->tracesFromWebRequest(function () {
$response = $this->call(GetSpec::create('Root', '/?function=lstat&path=./dummy'));
TestCase::assertSame("OK", $response);
});
$this->assertEvent('./dummy');
}
}
1 change: 1 addition & 0 deletions tests/Integrations/Filesystem/dummy
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Dummy file content
20 changes: 20 additions & 0 deletions tests/Integrations/Filesystem/index.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<?php

require __DIR__ . '/../../vendor/autoload.php';

$function = $_GET['function'];
$path = $_GET['path'];

switch ($function) {
case 'file_put_contents':
file_put_contents($path, 'some content');
break;
case 'fopen':
fopen($path, 'r');
break;
default:
$function($path);
break;
}

echo "OK";

0 comments on commit d027f9d

Please sign in to comment.