1
0
Fork 0
mirror of synced 2024-06-29 19:50:26 +12:00

Path validator + tests

This commit is contained in:
Matej Baco 2022-01-31 16:04:30 +01:00
parent 22290c21dd
commit 4161a65e0b
4 changed files with 119 additions and 3 deletions

View file

@ -2,6 +2,7 @@
require_once __DIR__.'/../init.php';
use Appwrite\Storage\Validator\Path;
use Utopia\App;
use Utopia\Logger\Log;
use Utopia\Logger\Log\User;
@ -525,8 +526,15 @@ App::get('/.well-known/acme-challenge')
->inject('request')
->inject('response')
->action(function ($request, $response) {
$filePath = $request->getURI();
$validator = new Path();
if (!$validator->isValid($filePath)) {
throw new Exception('Invalid file path. Please use relative path without \'../\'', 400);
}
$base = \realpath(APP_STORAGE_CERTIFICATES);
$path = \str_replace('/.well-known/acme-challenge/', '', $request->getURI());
$path = \str_replace('/.well-known/acme-challenge/', '', $filePath);
$absolute = \realpath($base.'/.well-known/acme-challenge/'.$path);
if (!$base) {

View file

@ -0,0 +1,78 @@
<?php
namespace Appwrite\Network\Validator;
use Utopia\Validator;
/**
* Domain
*
* Validate that an variable is a valid domain address
*
* @package Utopia\Validator
*/
class Path extends Validator
{
/**
* Get Description
*
* Returns validator description
*
* @return string
*/
public function getDescription(): string
{
return 'Value must be a relative path without \'../\'';
}
/**
* Is valid
*
* Validation will pass when $value is valid domain.
*
* Validates domain names against RFC 1034, RFC 1035, RFC 952, RFC 1123, RFC 2732, RFC 2181, and RFC 1123.
*
* @param mixed $value
* @return bool
*/
public function isValid($value): bool
{
if (empty($value)) {
return false;
}
if (!is_string($value)) {
return false;
}
if(\str_contains($value, '..')) {
return false;
}
return true;
}
/**
* Is array
*
* Function will return true if object is array.
*
* @return bool
*/
public function isArray(): bool
{
return false;
}
/**
* Get Type
*
* Returns validator type.
*
* @return string
*/
public function getType(): string
{
return self::TYPE_STRING;
}
}

View file

@ -3,6 +3,10 @@
namespace Tests\E2E;
use Exception;
use function curl_setopt;
use function http_build_query;
use const CURLOPT_PATH_AS_IS;
use const CURLOPT_TIMEOUT;
class Client
{
@ -119,7 +123,7 @@ class Client
}
/**
* @param mixed $endpoint
* @param string $endpoint
* @return self $this
*/
public function setEndpoint($endpoint): self
@ -129,6 +133,14 @@ class Client
return $this;
}
/**
* @return string
*/
public function getEndpoint(): string
{
return $this->endpoint;
}
/**
* @param string $key
* @param string $value
@ -183,12 +195,13 @@ class Client
unset($headers[$i]);
}
curl_setopt($ch, CURLOPT_PATH_AS_IS, 1);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $method);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.77 Safari/537.36');
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 0);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 0);
curl_setopt($ch, CURLOPT_TIMEOUT, 15);
curl_setopt($ch, CURLOPT_HEADERFUNCTION, function ($curl, $header) use (&$responseHeaders) {
$len = strlen($header);

View file

@ -94,6 +94,23 @@ class HTTPTest extends Scope
$this->assertStringContainsString('# robotstxt.org/', $response['body']);
}
public function testAcmeChallenge()
{
$previousEndpoint = $this->client->getEndpoint();
$this->client->setEndpoint("http://localhost");
/**
* Test for FAILURE
*/
$response = $this->client->call(Client::METHOD_GET, '/.well-known/acme-challenge/../../../../../../../etc/passwd', \array_merge([
'origin' => 'http://localhost',
]), []);
$this->client->setEndpoint($previousEndpoint);
$this->assertEquals(400, $response['headers']['status-code']);
}
// public function testSpecSwagger2()
// {
// $response = $this->client->call(Client::METHOD_GET, '/specs/swagger2?platform=client', [