Skip to content

Commit f77712f

Browse files
Merge pull request nextcloud#55851 from nextcloud/backport/55751/stable32
[stable32] fix(dav): Restrict properties allowed object classes
2 parents 572997a + eeb1dc8 commit f77712f

File tree

1 file changed

+38
-3
lines changed

1 file changed

+38
-3
lines changed

apps/dav/lib/DAV/CustomPropertiesBackend.php

Lines changed: 38 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -571,6 +571,18 @@ private function formatPath(string $path): string {
571571
return $path;
572572
}
573573

574+
private static function checkIsArrayOfScalar(string $name, array $array): void {
575+
foreach ($array as $item) {
576+
if (is_array($item)) {
577+
self::checkIsArrayOfScalar($name, $item);
578+
} elseif ($item !== null && !is_scalar($item)) {
579+
throw new DavException(
580+
"Property \"$name\" has an invalid value of array containing " . gettype($item),
581+
);
582+
}
583+
}
584+
}
585+
574586
/**
575587
* @throws ParseException If parsing a \Sabre\DAV\Xml\Property\Complex value fails
576588
* @throws DavException If the property value is invalid
@@ -605,6 +617,23 @@ private function encodeValueForDatabase(string $path, string $name, mixed $value
605617
$valueType = self::PROPERTY_TYPE_HREF;
606618
$value = $value->getHref();
607619
} else {
620+
if (is_array($value)) {
621+
// For array only allow scalar values
622+
self::checkIsArrayOfScalar($name, $value);
623+
} elseif (!is_object($value)) {
624+
throw new DavException(
625+
"Property \"$name\" has an invalid value of type " . gettype($value),
626+
);
627+
} else {
628+
if (!str_starts_with($value::class, 'Sabre\\DAV\\Xml\\Property\\')
629+
&& !str_starts_with($value::class, 'Sabre\\CalDAV\\Xml\\Property\\')
630+
&& !str_starts_with($value::class, 'Sabre\\CardDAV\\Xml\\Property\\')
631+
&& !str_starts_with($value::class, 'OCA\\DAV\\')) {
632+
throw new DavException(
633+
"Property \"$name\" has an invalid value of class " . $value::class,
634+
);
635+
}
636+
}
608637
$valueType = self::PROPERTY_TYPE_OBJECT;
609638
// serialize produces null character
610639
// these can not be properly stored in some databases and need to be replaced
@@ -616,20 +645,26 @@ private function encodeValueForDatabase(string $path, string $name, mixed $value
616645
/**
617646
* @return mixed|Complex|string
618647
*/
619-
private function decodeValueFromDatabase(string $value, int $valueType) {
648+
private function decodeValueFromDatabase(string $value, int $valueType): mixed {
620649
switch ($valueType) {
621650
case self::PROPERTY_TYPE_XML:
622651
return new Complex($value);
623652
case self::PROPERTY_TYPE_HREF:
624653
return new Href($value);
625654
case self::PROPERTY_TYPE_OBJECT:
655+
if (preg_match('/^a:/', $value)) {
656+
// Array, unserialize only scalar values
657+
return unserialize(str_replace('\x00', chr(0), $value), ['allowed_classes' => false]);
658+
}
659+
if (!preg_match('/^O\:\d+\:\"(OCA\\\\DAV\\\\|Sabre\\\\(Cal|Card)?DAV\\\\Xml\\\\Property\\\\)/', $value)) {
660+
throw new \LogicException('Found an object class serialized in DB that is not allowed');
661+
}
626662
// some databases can not handel null characters, these are custom encoded during serialization
627663
// this custom encoding needs to be first reversed before unserializing
628664
return unserialize(str_replace('\x00', chr(0), $value));
629-
case self::PROPERTY_TYPE_STRING:
630665
default:
631666
return $value;
632-
}
667+
};
633668
}
634669

635670
private function encodeDefaultCalendarUrl(Href $value): Href {

0 commit comments

Comments
 (0)