Skip to content

Commit bf8db31

Browse files
Merge pull request #55852 from nextcloud/backport/55851/stable31
[stable31] fix(dav): Restrict properties allowed object classes
2 parents 5e005e6 + e400db4 commit bf8db31

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
@@ -480,6 +480,18 @@ private function formatPath(string $path): string {
480480
return $path;
481481
}
482482

483+
private static function checkIsArrayOfScalar(string $name, array $array): void {
484+
foreach ($array as $item) {
485+
if (is_array($item)) {
486+
self::checkIsArrayOfScalar($name, $item);
487+
} elseif ($item !== null && !is_scalar($item)) {
488+
throw new DavException(
489+
"Property \"$name\" has an invalid value of array containing " . gettype($item),
490+
);
491+
}
492+
}
493+
}
494+
483495
/**
484496
* @throws ParseException If parsing a \Sabre\DAV\Xml\Property\Complex value fails
485497
* @throws DavException If the property value is invalid
@@ -514,6 +526,23 @@ private function encodeValueForDatabase(string $path, string $name, mixed $value
514526
$valueType = self::PROPERTY_TYPE_HREF;
515527
$value = $value->getHref();
516528
} else {
529+
if (is_array($value)) {
530+
// For array only allow scalar values
531+
self::checkIsArrayOfScalar($name, $value);
532+
} elseif (!is_object($value)) {
533+
throw new DavException(
534+
"Property \"$name\" has an invalid value of type " . gettype($value),
535+
);
536+
} else {
537+
if (!str_starts_with($value::class, 'Sabre\\DAV\\Xml\\Property\\')
538+
&& !str_starts_with($value::class, 'Sabre\\CalDAV\\Xml\\Property\\')
539+
&& !str_starts_with($value::class, 'Sabre\\CardDAV\\Xml\\Property\\')
540+
&& !str_starts_with($value::class, 'OCA\\DAV\\')) {
541+
throw new DavException(
542+
"Property \"$name\" has an invalid value of class " . $value::class,
543+
);
544+
}
545+
}
517546
$valueType = self::PROPERTY_TYPE_OBJECT;
518547
// serialize produces null character
519548
// these can not be properly stored in some databases and need to be replaced
@@ -525,20 +554,26 @@ private function encodeValueForDatabase(string $path, string $name, mixed $value
525554
/**
526555
* @return mixed|Complex|string
527556
*/
528-
private function decodeValueFromDatabase(string $value, int $valueType) {
557+
private function decodeValueFromDatabase(string $value, int $valueType): mixed {
529558
switch ($valueType) {
530559
case self::PROPERTY_TYPE_XML:
531560
return new Complex($value);
532561
case self::PROPERTY_TYPE_HREF:
533562
return new Href($value);
534563
case self::PROPERTY_TYPE_OBJECT:
564+
if (preg_match('/^a:/', $value)) {
565+
// Array, unserialize only scalar values
566+
return unserialize(str_replace('\x00', chr(0), $value), ['allowed_classes' => false]);
567+
}
568+
if (!preg_match('/^O\:\d+\:\"(OCA\\\\DAV\\\\|Sabre\\\\(Cal|Card)?DAV\\\\Xml\\\\Property\\\\)/', $value)) {
569+
throw new \LogicException('Found an object class serialized in DB that is not allowed');
570+
}
535571
// some databases can not handel null characters, these are custom encoded during serialization
536572
// this custom encoding needs to be first reversed before unserializing
537573
return unserialize(str_replace('\x00', chr(0), $value));
538-
case self::PROPERTY_TYPE_STRING:
539574
default:
540575
return $value;
541-
}
576+
};
542577
}
543578

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

0 commit comments

Comments
 (0)