Skip to content

Commit ad2a1a5

Browse files
Merge pull request #55854 from nextcloud/backport/55851/stable29
[stable29] fix(dav): Restrict properties allowed object classes
2 parents ae98530 + 36ce316 commit ad2a1a5

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
@@ -531,6 +531,18 @@ private function formatPath(string $path): string {
531531
return $path;
532532
}
533533

534+
private static function checkIsArrayOfScalar(string $name, array $array): void {
535+
foreach ($array as $item) {
536+
if (is_array($item)) {
537+
self::checkIsArrayOfScalar($name, $item);
538+
} elseif ($item !== null && !is_scalar($item)) {
539+
throw new DavException(
540+
"Property \"$name\" has an invalid value of array containing " . gettype($item),
541+
);
542+
}
543+
}
544+
}
545+
534546
/**
535547
* @throws ParseException If parsing a \Sabre\DAV\Xml\Property\Complex value fails
536548
* @throws DavException If the property value is invalid
@@ -565,6 +577,23 @@ private function encodeValueForDatabase(string $path, string $name, mixed $value
565577
$valueType = self::PROPERTY_TYPE_HREF;
566578
$value = $value->getHref();
567579
} else {
580+
if (is_array($value)) {
581+
// For array only allow scalar values
582+
self::checkIsArrayOfScalar($name, $value);
583+
} elseif (!is_object($value)) {
584+
throw new DavException(
585+
"Property \"$name\" has an invalid value of type " . gettype($value),
586+
);
587+
} else {
588+
if (!str_starts_with($value::class, 'Sabre\\DAV\\Xml\\Property\\')
589+
&& !str_starts_with($value::class, 'Sabre\\CalDAV\\Xml\\Property\\')
590+
&& !str_starts_with($value::class, 'Sabre\\CardDAV\\Xml\\Property\\')
591+
&& !str_starts_with($value::class, 'OCA\\DAV\\')) {
592+
throw new DavException(
593+
"Property \"$name\" has an invalid value of class " . $value::class,
594+
);
595+
}
596+
}
568597
$valueType = self::PROPERTY_TYPE_OBJECT;
569598
// serialize produces null character
570599
// these can not be properly stored in some databases and need to be replaced
@@ -576,20 +605,26 @@ private function encodeValueForDatabase(string $path, string $name, mixed $value
576605
/**
577606
* @return mixed|Complex|string
578607
*/
579-
private function decodeValueFromDatabase(string $value, int $valueType) {
608+
private function decodeValueFromDatabase(string $value, int $valueType): mixed {
580609
switch ($valueType) {
581610
case self::PROPERTY_TYPE_XML:
582611
return new Complex($value);
583612
case self::PROPERTY_TYPE_HREF:
584613
return new Href($value);
585614
case self::PROPERTY_TYPE_OBJECT:
615+
if (preg_match('/^a:/', $value)) {
616+
// Array, unserialize only scalar values
617+
return unserialize(str_replace('\x00', chr(0), $value), ['allowed_classes' => false]);
618+
}
619+
if (!preg_match('/^O\:\d+\:\"(OCA\\\\DAV\\\\|Sabre\\\\(Cal|Card)?DAV\\\\Xml\\\\Property\\\\)/', $value)) {
620+
throw new \LogicException('Found an object class serialized in DB that is not allowed');
621+
}
586622
// some databases can not handel null characters, these are custom encoded during serialization
587623
// this custom encoding needs to be first reversed before unserializing
588624
return unserialize(str_replace('\x00', chr(0), $value));
589-
case self::PROPERTY_TYPE_STRING:
590625
default:
591626
return $value;
592-
}
627+
};
593628
}
594629

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

0 commit comments

Comments
 (0)