Browse Source

Harden DNS record listing escaping (#5196)

divinity76 2 months ago
parent
commit
07dda18ef0
1 changed files with 88 additions and 78 deletions
  1. 88 78
      web/templates/pages/list_dns_rec.php

+ 88 - 78
web/templates/pages/list_dns_rec.php

@@ -1,18 +1,28 @@
+<?php
+	if (!function_exists("tohtml")){
+		function tohtml(string $str): string{
+			if ($str === '') {
+				return '';
+			}
+			return htmlentities($str, ENT_QUOTES|ENT_SUBSTITUTE|ENT_DISALLOWED|ENT_HTML5, 'UTF-8', true);
+		}
+	}
+?>
 <!-- Begin toolbar -->
 <div class="toolbar">
 	<div class="toolbar-inner">
-		<div class="toolbar-buttons">
-			<a class="button button-secondary button-back js-button-back" href="/list/dns/">
-				<i class="fas fa-arrow-left icon-blue"></i><?= _("Back") ?>
-			</a>
-			<?php if ($read_only !== "true") { ?>
-				<a href="/add/dns/?domain=<?= htmlentities($_GET["domain"]) ?>" class="button button-secondary js-button-create">
-					<i class="fas fa-circle-plus icon-green"></i><?= _("Add Record") ?>
+			<div class="toolbar-buttons">
+				<a class="button button-secondary button-back js-button-back" href="/list/dns/">
+					<i class="fas fa-arrow-left icon-blue"></i><?= _("Back") ?>
 				</a>
-				<a href="/edit/dns/?domain=<?= htmlentities($_GET["domain"]) ?>" class="button button-secondary js-button-create">
-					<i class="fas fa-pencil icon-blue"></i><?= _("Edit DNS Domain") ?>
-				</a>
-			<?php } ?>
+				<?php if ($read_only !== "true") { ?>
+					<a href="/add/dns/?<?= tohtml(http_build_query(array("domain" => $_GET["domain"]))) ?>" class="button button-secondary js-button-create">
+						<i class="fas fa-circle-plus icon-green"></i><?= _("Add Record") ?>
+					</a>
+					<a href="/edit/dns/?<?= tohtml(http_build_query(array("domain" => $_GET["domain"]))) ?>" class="button button-secondary js-button-create">
+						<i class="fas fa-pencil icon-blue"></i><?= _("Edit DNS Domain") ?>
+					</a>
+				<?php } ?>
 		</div>
 		<div class="toolbar-right">
 			<div class="toolbar-sorting">
@@ -42,8 +52,8 @@
 				</ul>
 				<?php if ($read_only !== "true") { ?>
 					<form x-data x-bind="BulkEdit" action="/bulk/dns/" method="post">
-						<input type="hidden" name="domain" value="<?= htmlentities($_GET["domain"]) ?>">
-						<input type="hidden" name="token" value="<?= $_SESSION["token"] ?>">
+						<input type="hidden" name="domain" value="<?= tohtml($_GET["domain"]) ?>">
+						<input type="hidden" name="token" value="<?= tohtml($_SESSION["token"]) ?>">
 						<select class="form-select" name="action">
 							<option value=""><?= _("Apply to selected") ?></option>
 							<option value="suspend"><?= _("Suspend") ?></option>
@@ -58,8 +68,8 @@
 			</div>
 			<div class="toolbar-search">
 				<form action="/search/" method="get">
-					<input type="hidden" name="token" value="<?= $_SESSION["token"] ?>">
-					<input type="search" class="form-control js-search-input" name="q" value="<? echo isset($_POST['q']) ? htmlspecialchars($_POST['q']) : '' ?>" title="<?= _("Search") ?>">
+					<input type="hidden" name="token" value="<?= tohtml($_SESSION["token"]) ?>">
+					<input type="search" class="form-control js-search-input" name="q" value="<?= tohtml($_POST['q'] ?? '') ?>" title="<?= _("Search") ?>">
 					<button type="submit" class="toolbar-input-submit" title="<?= _("Search") ?>">
 						<i class="fas fa-magnifying-glass"></i>
 					</button>
@@ -88,60 +98,60 @@
 		</div>
 
 		<!-- Begin DNS record list item loop -->
-		<?php
-			foreach ($data as $key => $value) {
-				++$i;
-				if ($data[$key]['SUSPENDED'] == 'yes') {
-					$status = 'suspended';
-				} else {
-					$status = 'active';
-				}
+			<?php
+				foreach ($data as $key => $value) {
+					++$i;
+					if ($data[$key]['SUSPENDED'] == 'yes') {
+						$status = 'suspended';
+					} else {
+						$status = 'active';
+					}
 			?>
-			<div class="units-table-row <?php if ($status == 'suspended') echo 'disabled'; ?> js-unit"
-				data-sort-date="<?= strtotime($data[$key]['DATE'].' '.$data[$key]['TIME']) ?>"
-				data-sort-record="<?= $data[$key]['RECORD'] ?>"
-				data-sort-type="<?= $data[$key]['TYPE'] ?>"
-				data-sort-ttl="<?= $data[$key]['TTL'] ?>"
-				data-sort-value="<?= $data[$key]['VALUE'] ?>">
-				<div class="units-table-cell">
-					<div>
-						<input id="check<?= $data[$key]["ID"] ?>" class="js-unit-checkbox" type="checkbox" title="<?= _("Select") ?>" name="record[]" value="<?= $data[$key]["ID"] ?>" <?= $display_mode ?>>
-						<label for="check<?= $data[$key]["ID"] ?>" class="u-hide-desktop"><?= _("Select") ?></label>
+				<div class="units-table-row <?php if ($status == 'suspended') echo 'disabled'; ?> js-unit"
+					data-sort-date="<?= tohtml((string)strtotime($data[$key]['DATE'].' '.$data[$key]['TIME'])) ?>"
+					data-sort-record="<?= tohtml($data[$key]['RECORD']) ?>"
+					data-sort-type="<?= tohtml($data[$key]['TYPE']) ?>"
+					data-sort-ttl="<?= tohtml($data[$key]['TTL']) ?>"
+					data-sort-value="<?= tohtml($data[$key]['VALUE']) ?>">
+					<div class="units-table-cell">
+						<div>
+							<input id="check<?= tohtml($data[$key]["ID"]) ?>" class="js-unit-checkbox" type="checkbox" title="<?= _("Select") ?>" name="record[]" value="<?= tohtml($data[$key]["ID"]) ?>" <?= $display_mode ?>>
+							<label for="check<?= tohtml($data[$key]["ID"]) ?>" class="u-hide-desktop"><?= _("Select") ?></label>
+						</div>
 					</div>
-				</div>
-				<div class="units-table-cell units-table-heading-cell u-text-bold">
-					<span class="u-hide-desktop"><?= _("Record") ?>:</span>
-					<?php if (($read_only === 'true') || ($data[$key]['SUSPENDED'] == 'yes')) { ?>
-						<?= substr($data[$key]['RECORD'], 0, 12); if (strlen($data[$key]['RECORD']) > 12 ) echo '...'; ?>
-					<?php } else { ?>
-						<a href="/edit/dns/?domain=<?= htmlspecialchars($_GET['domain']) ?>&record_id=<?= $data[$key]['ID'] ?>&token=<?= $_SESSION['token'] ?>" title="<?= _("Edit DNS Record") . ': '.htmlspecialchars($data[$key]['RECORD']) ?>">
-							<? echo substr($data[$key]['RECORD'], 0, 12); if (strlen($data[$key]['RECORD']) > 12 ) echo '...'; ?>
-						</a>
-					<?php } ?>
-				</div>
-				<div class="units-table-cell">
-					<?php if ($read_only !== "true") { ?>
+					<div class="units-table-cell units-table-heading-cell u-text-bold">
+						<span class="u-hide-desktop"><?= _("Record") ?>:</span>
+							<?php if (($read_only === 'true') || ($data[$key]['SUSPENDED'] == 'yes')) { ?>
+								<?= tohtml(substr($data[$key]['RECORD'], 0, 12)); if (strlen($data[$key]['RECORD']) > 12 ) echo '...'; ?>
+							<?php } else { ?>
+								<a href="/edit/dns/?<?= tohtml(http_build_query(array("domain" => $_GET['domain'], "record_id" => $data[$key]['ID'], "token" => $_SESSION['token']))) ?>" title="<?= tohtml(_("Edit DNS Record") . ': '.$data[$key]['RECORD']) ?>">
+									<?= tohtml(substr($data[$key]['RECORD'], 0, 12)); if (strlen($data[$key]['RECORD']) > 12 ) echo '...'; ?>
+								</a>
+							<?php } ?>
+						</div>
+					<div class="units-table-cell">
+						<?php if ($read_only !== "true") { ?>
 						<ul class="units-table-row-actions">
 							<?php if ($read_only !== "true") { ?>
-								<?php if ($data[$key]["SUSPENDED"] == "no") { ?>
-									<li class="units-table-row-action shortcut-enter" data-key-action="href">
-										<a
-											class="units-table-row-action-link"
-											href="/edit/dns/?domain=<?= htmlspecialchars($_GET["domain"]) ?>&record_id=<?= $data[$key]["ID"] ?>&token=<?= $_SESSION["token"] ?>"
-											title="<?= _("Edit DNS Record") ?>"
-										>
-											<i class="fas fa-pencil icon-orange"></i>
-											<span class="u-hide-desktop"><?= _("Edit DNS Record") ?></span>
-										</a>
+									<?php if ($data[$key]["SUSPENDED"] == "no") { ?>
+										<li class="units-table-row-action shortcut-enter" data-key-action="href">
+											<a
+												class="units-table-row-action-link"
+												href="/edit/dns/?<?= tohtml(http_build_query(array("domain" => $_GET["domain"], "record_id" => $data[$key]["ID"], "token" => $_SESSION["token"]))) ?>"
+												title="<?= _("Edit DNS Record") ?>"
+											>
+												<i class="fas fa-pencil icon-orange"></i>
+												<span class="u-hide-desktop"><?= _("Edit DNS Record") ?></span>
+											</a>
 									</li>
 								<?php } ?>
 								<li class="units-table-row-action shortcut-delete" data-key-action="js">
 									<a
 										class="units-table-row-action-link data-controls js-confirm-action"
-										href="/delete/dns/?domain=<?= htmlspecialchars($_GET["domain"]) ?>&record_id=<?= $data[$key]["ID"] ?>&token=<?= $_SESSION["token"] ?>"
+										href="/delete/dns/?<?= tohtml(http_build_query(array("domain" => $_GET["domain"], "record_id" => $data[$key]["ID"], "token" => $_SESSION["token"]))) ?>"
 										title="<?= _("Delete") ?>"
 										data-confirm-title="<?= _("Delete") ?>"
-										data-confirm-message="<?= sprintf(_("Are you sure you want to delete record %s?"), $key) ?>"
+										data-confirm-message="<?= tohtml(sprintf(_("Are you sure you want to delete record %s?"), $key)) ?>"
 									>
 										<i class="fas fa-trash icon-red"></i>
 										<span class="u-hide-desktop"><?= _("Delete") ?></span>
@@ -150,27 +160,27 @@
 							<?php } ?>
 						</ul>
 					<?php } ?>
+					</div>
+					<div class="units-table-cell u-text-bold u-text-center-desktop">
+						<span class="u-hide-desktop"><?= _("Type") ?>:</span>
+						<?= tohtml($data[$key]["TYPE"]) ?>
+					</div>
+					<div class="units-table-cell u-text-center-desktop">
+						<span class="u-hide-desktop u-text-bold"><?= _("Priority") ?>:</span>
+						<?= tohtml($data[$key]["PRIORITY"]) ?>
+					</div>
+					<div class="units-table-cell u-text-center-desktop">
+						<span class="u-hide-desktop u-text-bold"><?= _("TTL") ?>:</span>
+						<?php if ($data[$key]['TTL'] == ''){ echo tohtml(_('Default')); } else { echo tohtml($data[$key]['TTL']);} ?>
+					</div>
+					<div class="units-table-cell">
+						<span class="u-hide-desktop u-text-bold"><?= _("IP or Value") ?>:</span>
+						<span class="u-text-break">
+							<?= tohtml($data[$key]["VALUE"]) ?>
+						</span>
+					</div>
 				</div>
-				<div class="units-table-cell u-text-bold u-text-center-desktop">
-					<span class="u-hide-desktop"><?= _("Type") ?>:</span>
-					<?= $data[$key]["TYPE"] ?>
-				</div>
-				<div class="units-table-cell u-text-center-desktop">
-					<span class="u-hide-desktop u-text-bold"><?= _("Priority") ?>:</span>
-					<?= $data[$key]["PRIORITY"] ?>
-				</div>
-				<div class="units-table-cell u-text-center-desktop">
-					<span class="u-hide-desktop u-text-bold"><?= _("TTL") ?>:</span>
-					<?php if ($data[$key]['TTL'] == ''){ echo _('Default'); } else { echo $data[$key]['TTL'];} ?>
-				</div>
-				<div class="units-table-cell">
-					<span class="u-hide-desktop u-text-bold"><?= _("IP or Value") ?>:</span>
-					<span class="u-text-break">
-						<?= htmlspecialchars($data[$key]["VALUE"], ENT_QUOTES, "UTF-8") ?>
-					</span>
-				</div>
-			</div>
-		<?php } ?>
+			<?php } ?>
 	</div>
 
 	<div class="units-table-footer">