Overview
Comment:Prevent XSS by only allowing admins to create HTML/JS files
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | dev
Files: files | file ages | folders
SHA3-256: e857b5255e688ec93701634fac076284c24f5af911fa6e560f08457a4989d2b7
User & Date: bohwaz on 2022-09-13 17:07:48
Other Links: branch diff | manifest | tags
Context
2022-09-13
17:09
Merge with trunk check-in: 3f0ce8655e user: bohwaz tags: dev
17:07
Prevent XSS by only allowing admins to create HTML/JS files check-in: e857b5255e user: bohwaz tags: dev
16:29
Try to get around pixel flood attacks on image upload check-in: 6ebeabd74f user: bohwaz tags: dev
Changes

Modified src/include/lib/Garradin/Entities/Files/File.php from [1a62dab99f] to [8728998647].

122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
		'image/webp',
		'image/svg+xml',
		'text/plain',
		'text/html',
	];

	// https://book.hacktricks.xyz/pentesting-web/file-upload
	const FORBIDDEN_EXTENSIONS = '!^(?:cgi|exe|sh|bash|com|pif|jspx?|js[wxv]|action|do|php(?:s|\d+)?|pht|phtml?|shtml|phar|htaccess|inc|cfml?|cfc|dbm|swf|pl|perl|py|pyc|asp|so)$!i';

	static public function getColumns(): array
	{
		return array_keys((new self)->_types);
	}

	public function selfCheck(): void







|







122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
		'image/webp',
		'image/svg+xml',
		'text/plain',
		'text/html',
	];

	// https://book.hacktricks.xyz/pentesting-web/file-upload
	const FORBIDDEN_EXTENSIONS = '!^(?:cgi|exe|sh|bash|com|pif|jspx?|jar|js[wxv]|action|do|php(?:s|\d+)?|pht|phtml?|shtml|phar|htaccess|inc|cfml?|cfc|dbm|swf|pl|perl|py|pyc|asp|so)$!i';

	static public function getColumns(): array
	{
		return array_keys((new self)->_types);
	}

	public function selfCheck(): void
215
216
217
218
219
220
221


222
223

224
225
226
227
228
229
230
	/**
	 * Rename a file, this can include moving it (the UNIX way)
	 * @param  string $new_path Target path
	 * @return bool
	 */
	public function rename(string $new_path): bool
	{


		self::validatePath($new_path);
		self::validateFileName(Utils::basename($new_path));


		if ($new_path == $this->path) {
			throw new UserException(sprintf('Impossible de renommer "%s" lui-même', $this->path));
		}

		if (0 === strpos($new_path . '/', $this->path . '/')) {
			if ($this->type != self::TYPE_DIRECTORY) {







>
>

|
>







215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
	/**
	 * Rename a file, this can include moving it (the UNIX way)
	 * @param  string $new_path Target path
	 * @return bool
	 */
	public function rename(string $new_path): bool
	{
		$name = Utils::basename($new_path);

		self::validatePath($new_path);
		self::validateFileName($name);
		self::validateCanHTML($name, $new_path);

		if ($new_path == $this->path) {
			throw new UserException(sprintf('Impossible de renommer "%s" lui-même', $this->path));
		}

		if (0 === strpos($new_path . '/', $this->path . '/')) {
			if ($this->type != self::TYPE_DIRECTORY) {
885
886
887
888
889
890
891












892
893
894
895
896
897
898
			}
		}

		$name = array_pop($parts);
		$ref = implode('/', $parts);
		return [$context, $ref ?: null, $name];
	}













	public function renderFormat(): ?string
	{
		if (substr($this->name, -6) == '.skriv') {
			$format = Render::FORMAT_SKRIV;
		}
		elseif (substr($this->name, -3) == '.md') {







>
>
>
>
>
>
>
>
>
>
>
>







888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
			}
		}

		$name = array_pop($parts);
		$ref = implode('/', $parts);
		return [$context, $ref ?: null, $name];
	}

	/**
	 * Only admins can create or rename files to .html / .js
	 * This is to avoid XSS attacks from a non-admin user
	 */
	static public function validateCanHTML(string $name, string $path, ?Session $session = null): void
	{
		if (preg_match('/\.(?:htm|js|xhtm)/', $name)
			&& !File::checkSkeletonWriteAccess($path, $session ?? Session::getInstance())) {
			throw new ValidationException('Seuls les administrateurs peuvent créer des fichiers de ce type.');
		}
	}

	public function renderFormat(): ?string
	{
		if (substr($this->name, -6) == '.skriv') {
			$format = Render::FORMAT_SKRIV;
		}
		elseif (substr($this->name, -3) == '.md') {

Modified src/include/lib/Garradin/Files/Files.php from [7673bca1fd] to [09aaebfa21].

420
421
422
423
424
425
426



427
428
429
430
431
432
433
		}

		$pointer = $path = $content = null;
		extract($source);

		File::validateFileName($name);
		File::validatePath($parent);



		self::ensureDirectoryExists($parent);

		$name = File::filterName($name);

		$finfo = \finfo_open(\FILEINFO_MIME_TYPE);

		$target = $parent . '/' . $name;







>
>
>







420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
		}

		$pointer = $path = $content = null;
		extract($source);

		File::validateFileName($name);
		File::validatePath($parent);

		File::validateCanHTML($parent, $name);

		self::ensureDirectoryExists($parent);

		$name = File::filterName($name);

		$finfo = \finfo_open(\FILEINFO_MIME_TYPE);

		$target = $parent . '/' . $name;