Harden invitee input and contact names
Security audit found two gaps. Sabre only quotes ICS parameter values containing space, newline, quote, colon, semicolon, caret, comma or plus, so a bare carriage return in a contact name would be written into the serialized event unquoted and break the line structure; names with control characters are now dropped. The raw attendee input and the search query had no length bound, a huge POST field was fully split, iterated and echoed back on re-render, a cheap CPU sink; both are now capped, the query at the longest possible email fragment.
This commit is contained in:
1 parent
97cea7e90b
commit
6312c18a91
5 files changed
+83
-4
No files matched your search
@@ -476,6 +476,17 @@ class CalendarController extends Controller
|
||||
*/
|
||||
private function parseAttendees(string $input): array
|
||||
{
|
||||
/*
|
||||
* Bound the raw input: splitting an arbitrarily large
|
||||
* string is a cheap CPU sink and the value is echoed
|
||||
* back into the page on a re-render.
|
||||
*/
|
||||
$this->assertBoundedLength(
|
||||
$input,
|
||||
self::MAX_ATTENDEES * (self::MAX_EMAIL_LENGTH + 1),
|
||||
$this->l10n->t('Invitee list is too long.')
|
||||
);
|
||||
|
||||
$attendees = [];
|
||||
$seen = [];
|
||||
|
||||
@@ -522,11 +533,28 @@ class CalendarController extends Controller
|
||||
{
|
||||
$contacts = [];
|
||||
|
||||
$results = $this->contactsManager->search(trim($query), ['FN', 'EMAIL']);
|
||||
/*
|
||||
* The query is the fragment being typed, a full email
|
||||
* address is the longest useful input.
|
||||
*/
|
||||
$query = mb_substr(trim($query), 0, self::MAX_EMAIL_LENGTH);
|
||||
|
||||
$results = $this->contactsManager->search($query, ['FN', 'EMAIL']);
|
||||
|
||||
foreach ($results ?? [] as $result) {
|
||||
$name = (string)($result['FN'] ?? '');
|
||||
|
||||
/*
|
||||
* Contact names become the CN parameter of the ICS
|
||||
* ATTENDEE. Sabre escapes most special characters on
|
||||
* serialization, but a bare carriage return bypasses
|
||||
* its quoting, so names with control characters are
|
||||
* dropped.
|
||||
*/
|
||||
if (preg_match('/[\x00-\x1F\x7F]/u', $name) === 1) {
|
||||
$name = '';
|
||||
}
|
||||
|
||||
$emails = $result['EMAIL'] ?? [];
|
||||
$emails = is_array($emails) ? $emails : [$emails];
|
||||
|
||||
|
||||
Reference in new issue
Block a user