mirror of
https://gitlab.com/ArkHost/WHMCS-ArkhostVPSAG.git
synced 2026-07-24 07:45:55 +02:00
Harden VPSAG module: credential logging, path injection, suspension, signature, XSS
- Redact decrypted reseller API credentials from module logs (ArkhostVPSAG_Error). - Validate client-controlled values before they enter upstream API URL paths (graph time, backup file, firewall rule id, ISO id, rDNS IP); restrict VPS ID to digits. Prevents path/parameter injection (IDOR). - Suspend via Disable/Enable instead of Stop/Start, and reject state-changing client-area actions on non-active services (suspended client can't power on). - Verify the provisioning callback signature with hash_equals instead of !=. - Fix callback assigned-IP assembly: keep all extra IPv4s, join with real newlines (was dropping the first IP and using a literal backslash-n). - Make callback html_entity_decode array-safe. - Escape untrusted output: JSON_HEX_TAG-encode serverInfo for the <script> block, HTML-escape serverInfo/OS fields in template + error.tpl, escape firewall/backup values built via innerHTML.
This commit is contained in:
@@ -651,7 +651,7 @@ if (arkhostVNCHashDetected) {
|
||||
|
||||
<script type="text/javascript">
|
||||
var productURL = '{$WEB_ROOT}/clientarea.php?action=productdetails&id={$serviceid}';
|
||||
var serverInfoInitial = JSON.parse('{$serverInfo|json_encode}');
|
||||
var serverInfoInitial = {$serverInfoJson nofilter};
|
||||
var lang = {
|
||||
moduleactionfailed: 'Action failed!',
|
||||
moduleactionsuccess: 'Action completed successfully',
|
||||
@@ -907,6 +907,16 @@ if (arkhostVNCHashDetected) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Escape untrusted values before inserting them into innerHTML.
|
||||
function escapeHtml(value) {
|
||||
return String(value == null ? '' : value)
|
||||
.replace(/&/g, '&')
|
||||
.replace(/</g, '<')
|
||||
.replace(/>/g, '>')
|
||||
.replace(/"/g, '"')
|
||||
.replace(/'/g, ''');
|
||||
}
|
||||
|
||||
function updateBackupTable(data) {
|
||||
var tableBody = document.querySelector('#backupTable tbody');
|
||||
tableBody.innerHTML = '';
|
||||
@@ -956,9 +966,9 @@ if (arkhostVNCHashDetected) {
|
||||
statusBadge = '<span class="badge badge-danger">' + lang.backups.error + '</span>';
|
||||
}
|
||||
|
||||
row.innerHTML =
|
||||
'<td>' + backupDate + '</td>' +
|
||||
'<td>' + (backup.size || 'N/A') + '</td>' +
|
||||
row.innerHTML =
|
||||
'<td>' + escapeHtml(backupDate) + '</td>' +
|
||||
'<td>' + escapeHtml(backup.size || 'N/A') + '</td>' +
|
||||
'<td>' + backupType + '</td>' +
|
||||
'<td>' + statusBadge + '</td>' +
|
||||
'<td style="white-space: nowrap;">' +
|
||||
@@ -1075,12 +1085,12 @@ if (arkhostVNCHashDetected) {
|
||||
rulesList.forEach(function(rule) {
|
||||
if (rule && rule.id) {
|
||||
var row = document.createElement('tr');
|
||||
row.innerHTML =
|
||||
'<td>' + (rule.action || 'N/A') + '</td>' +
|
||||
'<td>' + (rule.port || 'N/A') + '</td>' +
|
||||
'<td>' + (rule.protocol || 'N/A') + '</td>' +
|
||||
'<td>' + (rule.source || 'N/A') + '</td>' +
|
||||
'<td>' + (rule.note || 'N/A') + '</td>' +
|
||||
row.innerHTML =
|
||||
'<td>' + escapeHtml(rule.action || 'N/A') + '</td>' +
|
||||
'<td>' + escapeHtml(rule.port || 'N/A') + '</td>' +
|
||||
'<td>' + escapeHtml(rule.protocol || 'N/A') + '</td>' +
|
||||
'<td>' + escapeHtml(rule.source || 'N/A') + '</td>' +
|
||||
'<td>' + escapeHtml(rule.note || 'N/A') + '</td>' +
|
||||
'<td>' +
|
||||
'<a href="#" onclick="ArkHostVPS_API(\'Delete Firewall rule\', true, { rule_id: \'' + rule.id + '\' }); return false;" title="Delete">' +
|
||||
'<i class="fa fa-trash text-danger"></i>' +
|
||||
@@ -1575,16 +1585,16 @@ if (arkhostVNCHashDetected) {
|
||||
<table class="table table-sm table-borderless mb-0">
|
||||
<tr>
|
||||
<td class="text-muted" width="40%">{$_LANG['Overview']['Hostname']}:</td>
|
||||
<td><strong>{$serverInfo['hostname']|default:'N/A'}</strong></td>
|
||||
<td><strong>{$serverInfo['hostname']|default:'N/A'|escape}</strong></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="text-muted">{$_LANG['IPv4']} Address:</td>
|
||||
<td><code>{$serverInfo['ip']}</code></td>
|
||||
<td><code>{$serverInfo['ip']|escape}</code></td>
|
||||
</tr>
|
||||
{if $serverInfo['ipv6']}
|
||||
<tr>
|
||||
<td class="text-muted">{$_LANG['IPv6']} Address:</td>
|
||||
<td><code style="font-size: 11px;">{$serverInfo['ipv6']}</code></td>
|
||||
<td><code style="font-size: 11px;">{$serverInfo['ipv6']|escape}</code></td>
|
||||
</tr>
|
||||
{/if}
|
||||
<tr>
|
||||
@@ -1593,7 +1603,7 @@ if (arkhostVNCHashDetected) {
|
||||
{if $serverInfo['operatingSystem']['image']}
|
||||
<img src="{$serverInfo['operatingSystem']['image']}" width="20" height="20" class="mr-1" style="vertical-align: middle;">
|
||||
{/if}
|
||||
{$serverInfo['operatingSystem']['name']|default:'N/A'}
|
||||
{$serverInfo['operatingSystem']['name']|default:'N/A'|escape}
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
@@ -1605,17 +1615,17 @@ if (arkhostVNCHashDetected) {
|
||||
<td>
|
||||
<img src="{$serverInfo['statusImage']}" height="20" class="mr-1" style="vertical-align: middle;">
|
||||
<span class="{if $serverInfo['status'] == 'running'}text-success{else}text-danger{/if}">
|
||||
<strong>{$serverInfo['statusDescription']}</strong>
|
||||
<strong>{$serverInfo['statusDescription']|escape}</strong>
|
||||
</span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="text-muted">{$_LANG['Overview']['Uptime']}:</td>
|
||||
<td><strong>{$serverInfo['uptime_text']|default:'N/A'}</strong></td>
|
||||
<td><strong>{$serverInfo['uptime_text']|default:'N/A'|escape}</strong></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="text-muted">{$_LANG['Overview']['ServerType']}:</td>
|
||||
<td><strong>{$serverInfo['server_type']|default:'Standard'}</strong></td>
|
||||
<td><strong>{$serverInfo['server_type']|default:'Standard'|escape}</strong></td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
@@ -1993,7 +2003,7 @@ if (arkhostVNCHashDetected) {
|
||||
<div class="col-md-6">
|
||||
<div class="mb-3">
|
||||
<label class="form-label">{$_LANG['Settings']['Hostname']['Title']}:</label>
|
||||
<input class="form-control" id="hostnameRDNS" type="text" size="30" maxlength="128" value="{$serverInfo['hostname']}">
|
||||
<input class="form-control" id="hostnameRDNS" type="text" size="30" maxlength="128" value="{$serverInfo['hostname']|escape}">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -2045,7 +2055,7 @@ if (arkhostVNCHashDetected) {
|
||||
<label class="form-label">{$_LANG['Settings']['Password']['Title']}:</label>
|
||||
|
||||
<div class="input-group mb-3">
|
||||
<input class="form-control" id="vpsPassword" type="password" size="30" maxlength="128" disabled value="{if $serverInfo['install_root'] != ''}{$serverInfo['install_root']}{else}Expired{/if}">
|
||||
<input class="form-control" id="vpsPassword" type="password" size="30" maxlength="128" disabled value="{if $serverInfo['install_root'] != ''}{$serverInfo['install_root']|escape}{else}Expired{/if}">
|
||||
<button class="btn btn-outline-secondary" type="button" onclick="ArkHostVPS_ShowPassword();return false;">
|
||||
<i class="fa fa-eye" id="showPasswordIcon" aria-hidden="true"></i>
|
||||
</button>
|
||||
@@ -2080,14 +2090,14 @@ if (arkhostVNCHashDetected) {
|
||||
</div>
|
||||
|
||||
<div class="media-body float-left text-left p-2">
|
||||
<h6 class="distro_name media-heading">{$operatingSystemsGroup['name']}</h6>
|
||||
<h6 class="distro_name media-heading">{$operatingSystemsGroup['name']|escape}</h6>
|
||||
<span id="{$group}-version" class="version small">{$_LANG['Settings']['Reinstall']['Version']}</span>
|
||||
</div>
|
||||
</button>
|
||||
|
||||
<div class="os_badge_list dropdown-menu w-100">
|
||||
{foreach from=$operatingSystemsGroup['versions'] item=$operatingSystem}
|
||||
<a class="dropdown-item" href="#" data-os="{$operatingSystem['id']}" data-group="{$group}" onclick="ArkHostVPS_ChooseOS(this);return false;">{$operatingSystem['name']}</a>
|
||||
<a class="dropdown-item" href="#" data-os="{$operatingSystem['id']|escape}" data-group="{$group|escape}" onclick="ArkHostVPS_ChooseOS(this);return false;">{$operatingSystem['name']|escape}</a>
|
||||
{/foreach}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user