Skip to content

Commit 05556e9

Browse files
authored
Merge pull request #1037 from nextcloud/fix/login-post-escape
Fix HTML injection in SAML POST login
2 parents 223c479 + 2c92f18 commit 05556e9

File tree

2 files changed

+72
-6
lines changed

2 files changed

+72
-6
lines changed

templates/login_post.php

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,19 +15,19 @@
1515
p($l->t('Please wait while you are redirected to the SSO server.'));
1616
?>
1717

18-
<form action="<?= $_['ssoUrl'] ?>" method="post">
19-
<input type="hidden" name="SAMLRequest" value="<?= $_['samlRequest'] ?>" />
20-
<input type="hidden" name="RelayState" value="<?= $_['relayState'] ?>" />
21-
<input type="hidden" name="SigAlg" value="<?= $_['sigAlg'] ?>" />
22-
<input type="hidden" name="Signature" value="<?= $_['signature'] ?>" />
18+
<form action="<?php p($_['ssoUrl']); ?>" method="post">
19+
<input type="hidden" name="SAMLRequest" value="<?php p($_['samlRequest']); ?>" />
20+
<input type="hidden" name="RelayState" value="<?php p($_['relayState']); ?>" />
21+
<input type="hidden" name="SigAlg" value="<?php p($_['sigAlg']); ?>" />
22+
<input type="hidden" name="Signature" value="<?php p($_['signature']); ?>" />
2323
<noscript>
2424
<p>
2525
<?php p($l->t('JavaScript is disabled in your browser. Please enable it to continue.')) ?>
2626
</p>
2727
<input type="submit" value="Continue" />
2828
</noscript>
2929
</form>
30-
<script nonce="<?= $_['nonce'] ?>">
30+
<script nonce="<?php p($_['nonce']); ?>">
3131
document.addEventListener('DOMContentLoaded', function() {
3232
document.forms[0].submit()
3333
})
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
<?php
2+
3+
/**
4+
* SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors
5+
* SPDX-License-Identifier: AGPL-3.0-or-later
6+
*/
7+
8+
namespace {
9+
if (!function_exists('p')) {
10+
function p($string): void {
11+
print(htmlspecialchars((string)$string, ENT_QUOTES, 'UTF-8'));
12+
}
13+
}
14+
}
15+
16+
namespace OCA\User_SAML\Tests\Template {
17+
use OCP\IL10N;
18+
use OCP\Util;
19+
use Test\TestCase;
20+
21+
class LoginPostTemplateTest extends TestCase {
22+
public function testLoginPostTemplateEscapesValues(): void {
23+
$l = $this->createMock(IL10N::class);
24+
$l->method('t')->willReturnCallback(static fn (string $text): string => $text);
25+
26+
$_ = [
27+
'ssoUrl' => 'https://example.com/" onmouseover="alert(1)',
28+
'samlRequest' => '"><input name="submit">',
29+
'relayState' => '"><img src=x onerror=alert(1)>',
30+
'sigAlg' => '"><svg onload=alert(1)>',
31+
'signature' => '"><div>sig</div>',
32+
'nonce' => '" onload="alert(1)',
33+
];
34+
35+
ob_start();
36+
include __DIR__ . '/../../../templates/login_post.php';
37+
$output = ob_get_clean();
38+
39+
$this->assertNotFalse($output);
40+
$this->assertStringContainsString(
41+
'action="' . Util::sanitizeHTML($_['ssoUrl']) . '"',
42+
$output
43+
);
44+
$this->assertStringContainsString(
45+
'name="SAMLRequest" value="' . Util::sanitizeHTML($_['samlRequest']) . '"',
46+
$output
47+
);
48+
$this->assertStringContainsString(
49+
'name="RelayState" value="' . Util::sanitizeHTML($_['relayState']) . '"',
50+
$output
51+
);
52+
$this->assertStringContainsString(
53+
'name="SigAlg" value="' . Util::sanitizeHTML($_['sigAlg']) . '"',
54+
$output
55+
);
56+
$this->assertStringContainsString(
57+
'name="Signature" value="' . Util::sanitizeHTML($_['signature']) . '"',
58+
$output
59+
);
60+
$this->assertStringContainsString(
61+
'nonce="' . Util::sanitizeHTML($_['nonce']) . '"',
62+
$output
63+
);
64+
}
65+
}
66+
}

0 commit comments

Comments
 (0)