secubox-openwrt/package/secubox/luci-app-system-hub/htdocs/luci-static/resources/view/system-hub/remote.js
CyberMind-FR e58f479cd4 feat(waf): Update WAF scenarios with 2024-2025 CVEs and OWASP threats
Add detection patterns for latest actively exploited vulnerabilities:
- CVE-2025-55182 (React2Shell, CVSS 10.0)
- CVE-2025-8110 (Gogs RCE), CVE-2025-53770 (SharePoint)
- CVE-2025-52691 (SmarterMail), CVE-2025-40551 (SolarWinds)
- CVE-2024-47575 (FortiManager), CVE-2024-21887 (Ivanti)
- CVE-2024-3400, CVE-2024-0012, CVE-2024-9474 (PAN-OS)

New attack categories based on OWASP Top 10 2025:
- HTTP Request Smuggling (TE.CL/CL.TE conflicts)
- AI/LLM Prompt Injection (ChatML, instruction markers)
- WAF Bypass techniques (Unicode normalization, double encoding)
- Supply Chain attacks (CI/CD poisoning, dependency confusion)
- Extended SSTI (Jinja2, Freemarker, Velocity, Thymeleaf)
- API Abuse (BOLA/IDOR, mass assignment)

CrowdSec scenarios split into 11 separate files for reliability.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-12 05:02:57 +01:00

476 lines
17 KiB
JavaScript
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

'use strict';
'require view';
'require dom';
'require ui';
'require secubox-theme/theme as Theme';
'require system-hub/api as API';
'require system-hub/theme-assets as ThemeAssets';
'require system-hub/nav as HubNav';
'require secubox-portal/header as SbHeader';
'require secubox/kiss-theme';
var shLang = (typeof L !== 'undefined' && L.env && L.env.lang) ||
(document.documentElement && document.documentElement.getAttribute('lang')) ||
(navigator.language ? navigator.language.split('-')[0] : 'en');
Theme.init({ language: shLang });
return view.extend({
load: function() {
return Promise.all([
API.remoteStatus(),
API.ttydStatus()
]);
},
render: function(data) {
var remote = data[0] || {};
var ttyd = data[1] || {};
this.remote = remote;
this.ttyd = ttyd;
var content = [
E('link', { 'rel': 'stylesheet', 'href': L.resource('secubox-theme/secubox-theme.css') }),
ThemeAssets.stylesheet('common.css'),
ThemeAssets.stylesheet('dashboard.css'),
HubNav.renderTabs('remote'),
// rtty Remote Access Section
E('div', { 'class': 'sh-card sh-remote-card' }, [
E('div', { 'class': 'sh-card-header' }, [
E('div', { 'class': 'sh-card-title' }, [ E('span', { 'class': 'sh-card-title-icon' }, '🔗'), _('rtty - Remote Terminal') ]),
E('div', { 'class': 'sh-card-badge', 'id': 'rtty-status-badge' }, remote.running ? _('Connected') : _('Disconnected'))
]),
E('div', { 'class': 'sh-card-body' }, [
// Device ID
E('div', { 'class': 'sh-remote-id' }, [
E('div', { 'class': 'sh-remote-id-icon' }, '🆔'),
E('div', {}, [
E('div', { 'class': 'sh-remote-id-value', 'id': 'rtty-device-id' }, remote.id || _('Not configured')),
E('div', { 'class': 'sh-remote-id-label' }, _('Device ID - Share this with support'))
])
]),
// Configuration fields
E('div', { 'class': 'sh-form-grid', 'style': 'margin-top: 16px;' }, [
// Server Host
E('div', { 'class': 'sh-form-group' }, [
E('label', { 'class': 'sh-form-label' }, _('Server Host')),
E('input', {
'type': 'text',
'class': 'sh-form-input',
'id': 'rtty-host',
'placeholder': 'rttys.example.com',
'value': remote.host || ''
})
]),
// Server Port
E('div', { 'class': 'sh-form-group' }, [
E('label', { 'class': 'sh-form-label' }, _('Server Port')),
E('input', {
'type': 'number',
'class': 'sh-form-input',
'id': 'rtty-port',
'placeholder': '5912',
'value': remote.port || 5912
})
]),
// Token
E('div', { 'class': 'sh-form-group' }, [
E('label', { 'class': 'sh-form-label' }, _('Access Token')),
E('input', {
'type': 'password',
'class': 'sh-form-input',
'id': 'rtty-token',
'placeholder': _('Optional authentication token'),
'value': remote.token || ''
})
]),
// Device Description
E('div', { 'class': 'sh-form-group' }, [
E('label', { 'class': 'sh-form-label' }, _('Description')),
E('input', {
'type': 'text',
'class': 'sh-form-input',
'id': 'rtty-description',
'placeholder': _('Device description'),
'value': remote.description || ''
})
])
]),
// SSL Toggle
this.renderToggle('🔒', _('Use SSL/TLS'), _('Encrypt connection to relay server'), remote.ssl, 'rtty-ssl'),
// Status
!remote.installed ? E('div', { 'style': 'padding: 16px; background: rgba(245, 158, 11, 0.1); border-radius: 10px; border-left: 3px solid #f59e0b; margin-top: 16px;' }, [
E('span', { 'style': 'font-size: 20px; margin-right: 12px;' }, ''),
E('span', {}, _('rtty is not installed.')),
E('a', { 'href': '#', 'style': 'color: #6366f1; margin-left: 8px;', 'click': L.bind(this.installRtty, this) }, _('Install now'))
]) : E('div', { 'style': 'padding: 10px; background: rgba(34,197,94,0.12); border-radius: 10px; margin-top: 16px;' }, [
E('span', { 'style': 'font-size: 20px; margin-right: 12px;' }, remote.running ? '🟢' : '🟠'),
E('span', {}, remote.running ? _('Connected to relay server') : _('Installed but not connected'))
]),
// Actions
E('div', { 'class': 'sh-btn-group', 'style': 'margin-top: 16px;' }, [
E('button', {
'class': 'sh-btn sh-btn-primary',
'id': 'rtty-save-btn',
'click': L.bind(this.saveRttySettings, this)
}, [ '💾 ', _('Save Settings') ]),
E('button', {
'class': 'sh-btn',
'id': 'rtty-toggle-btn',
'click': L.bind(this.toggleRttyService, this)
}, [ remote.running ? ' ' + _('Disconnect') : ' ' + _('Connect') ]),
E('button', {
'class': 'sh-btn',
'click': L.bind(this.showCredentials, this)
}, [ '🔑 ', _('Show Credentials') ])
])
])
]),
// SSH Section
E('div', { 'class': 'sh-card' }, [
E('div', { 'class': 'sh-card-header' }, [
E('div', { 'class': 'sh-card-title' }, [ E('span', { 'class': 'sh-card-title-icon' }, '🔐'), _('SSH Access') ])
]),
E('div', { 'class': 'sh-card-body' }, [
E('div', { 'class': 'sh-sysinfo-grid' }, [
E('div', { 'class': 'sh-sysinfo-item' }, [
E('span', { 'class': 'sh-sysinfo-label' }, _('Status')),
E('span', { 'class': 'sh-sysinfo-value', 'style': 'color: #22c55e;' }, _('Active'))
]),
E('div', { 'class': 'sh-sysinfo-item' }, [
E('span', { 'class': 'sh-sysinfo-label' }, _('Port')),
E('span', { 'class': 'sh-sysinfo-value' }, '22')
])
]),
E('div', { 'style': 'margin-top: 16px; padding: 14px; background: #0a0a0f; border-radius: 8px; font-family: monospace; font-size: 12px; color: #a0a0b0;' }, [
'ssh root@', E('span', { 'style': 'color: #6366f1;' }, window.location.hostname)
])
])
]),
// Web Console (ttyd) Section
E('div', { 'class': 'sh-card sh-webconsole-card' }, [
E('div', { 'class': 'sh-card-header' }, [
E('div', { 'class': 'sh-card-title' }, [ E('span', { 'class': 'sh-card-title-icon' }, '💻'), _('Web Console') ]),
E('div', { 'class': 'sh-card-badge', 'id': 'ttyd-status-badge' }, ttyd.running ? _('Running') : _('Stopped'))
]),
E('div', { 'class': 'sh-card-body' }, [
// Status info
E('div', { 'class': 'sh-sysinfo-grid' }, [
E('div', { 'class': 'sh-sysinfo-item' }, [
E('span', { 'class': 'sh-sysinfo-label' }, _('Status')),
E('span', { 'class': 'sh-sysinfo-value', 'id': 'ttyd-status-text', 'style': ttyd.running ? 'color: #22c55e;' : 'color: #f59e0b;' },
ttyd.installed ? (ttyd.running ? _('Running') : _('Stopped')) : _('Not Installed'))
]),
E('div', { 'class': 'sh-sysinfo-item' }, [
E('span', { 'class': 'sh-sysinfo-label' }, _('Port')),
E('span', { 'class': 'sh-sysinfo-value' }, ttyd.port || 7681)
])
]),
// Install warning or console iframe
!ttyd.installed ? E('div', { 'style': 'padding: 16px; background: rgba(245, 158, 11, 0.1); border-radius: 10px; border-left: 3px solid #f59e0b; margin-top: 16px;' }, [
E('span', { 'style': 'font-size: 20px; margin-right: 12px;' }, ''),
E('span', {}, _('Web Console (ttyd) is not installed.')),
E('a', { 'href': '#', 'style': 'color: #6366f1; margin-left: 8px;', 'click': L.bind(this.installTtyd, this) }, _('Install now'))
]) : (ttyd.running ?
// Console iframe when running
E('div', { 'id': 'ttyd-console-container', 'style': 'margin-top: 16px; border-radius: 8px; overflow: hidden; background: #0a0a0f; border: 1px solid rgba(255,255,255,0.1);' }, [
E('iframe', {
'id': 'ttyd-iframe',
'src': 'http://' + window.location.hostname + ':' + (ttyd.port || 7681),
'style': 'width: 100%; height: 400px; border: none; background: #0a0a0f;',
'title': 'Web Console'
})
]) :
// Start prompt when stopped
E('div', { 'style': 'padding: 20px; background: rgba(99, 102, 241, 0.1); border-radius: 10px; margin-top: 16px; text-align: center;' }, [
E('span', { 'style': 'font-size: 40px; display: block; margin-bottom: 12px;' }, '💻'),
E('p', { 'style': 'margin: 0 0 16px 0; color: #a0a0b0;' }, _('Web Console is ready. Click Start to open the terminal.')),
E('button', {
'class': 'sh-btn sh-btn-primary',
'click': L.bind(this.startTtyd, this)
}, [ '▶️ ', _('Start Console') ])
])
),
// Actions
ttyd.installed ? E('div', { 'class': 'sh-btn-group', 'style': 'margin-top: 16px;' }, [
E('button', {
'class': 'sh-btn sh-btn-primary',
'id': 'ttyd-toggle-btn',
'click': L.bind(this.toggleTtyd, this)
}, [ ttyd.running ? '⏹️ ' + _('Stop') : '▶️ ' + _('Start') ]),
ttyd.running ? E('button', {
'class': 'sh-btn',
'click': L.bind(this.openTtydFullscreen, this)
}, [ '🔲 ', _('Fullscreen') ]) : '',
E('button', {
'class': 'sh-btn',
'click': L.bind(this.refreshTtydStatus, this)
}, [ '🔄 ', _('Refresh') ])
]) : ''
])
]),
// Support Contact (static)
E('div', { 'class': 'sh-card' }, [
E('div', { 'class': 'sh-card-header' }, [
E('div', { 'class': 'sh-card-title' }, [ E('span', { 'class': 'sh-card-title-icon' }, '📞'), _('Contact Support') ])
]),
E('div', { 'class': 'sh-card-body' }, [
E('div', { 'class': 'sh-sysinfo-grid' }, [
E('div', { 'class': 'sh-sysinfo-item' }, [
E('span', { 'class': 'sh-sysinfo-label' }, _('Provider')),
E('span', { 'class': 'sh-sysinfo-value' }, 'CyberMind.fr')
]),
E('div', { 'class': 'sh-sysinfo-item' }, [
E('span', { 'class': 'sh-sysinfo-label' }, _('Email')),
E('span', { 'class': 'sh-sysinfo-value' }, 'support@cybermind.fr')
]),
E('div', { 'class': 'sh-sysinfo-item' }, [
E('span', { 'class': 'sh-sysinfo-label' }, _('Phone')),
E('span', { 'class': 'sh-sysinfo-value' }, '+33 1 23 45 67 89')
]),
E('div', { 'class': 'sh-sysinfo-item' }, [
E('span', { 'class': 'sh-sysinfo-label' }, _('Website')),
E('span', { 'class': 'sh-sysinfo-value' }, 'https://cybermind.fr')
])
])
])
])
];
return KissTheme.wrap(content, 'admin/system/hub/remote');
},
renderToggle: function(icon, label, desc, enabled, id) {
return E('div', { 'class': 'sh-toggle', 'style': 'margin-top: 16px;' }, [
E('div', { 'class': 'sh-toggle-info' }, [
E('span', { 'class': 'sh-toggle-icon' }, icon),
E('div', {}, [
E('div', { 'class': 'sh-toggle-label' }, label),
E('div', { 'class': 'sh-toggle-desc' }, desc)
])
]),
E('div', {
'class': 'sh-toggle-switch' + (enabled ? ' active' : ''),
'id': id,
'click': function(ev) {
ev.target.classList.toggle('active');
}
})
]);
},
showCredentials: function() {
ui.showModal(_('rtty Credentials'), [
E('p', {}, _('Retrieving credentials...')),
E('div', { 'class': 'spinning' })
]);
API.remoteCredentials().then(L.bind(function(result) {
ui.hideModal();
ui.showModal(_('rtty Credentials'), [
E('div', { 'style': 'font-size:16px; margin-bottom:12px;' }, [
E('strong', {}, _('Device ID:')), ' ', (result.id || _('Not configured'))
]),
E('div', { 'style': 'font-size:16px; margin-bottom:12px;' }, [
E('strong', {}, _('Token:')), ' ', (result.token || _('No token set'))
]),
E('p', { 'style': 'color: #a0a0b0; font-size: 13px; margin-top: 16px;' },
_('Share the Device ID with support to allow remote access via the rtty relay server.')),
E('div', { 'class': 'sh-btn-group', 'style': 'margin-top:16px;' }, [
E('button', { 'class': 'sh-btn sh-btn-primary', 'click': ui.hideModal }, _('Close'))
])
]);
}, this)).catch(function(err) {
ui.hideModal();
ui.addNotification(null, E('p', {}, err.message || err), 'error');
});
},
toggleRttyService: function() {
if (!this.remote || !this.remote.installed) return;
var action = this.remote.running ? 'stop' : 'start';
ui.showModal(action === 'start' ? _('Connecting...') : _('Disconnecting...'), [
E('p', {}, action === 'start' ? _('Connecting to relay server...') : _('Stopping rtty service...')),
E('div', { 'class': 'spinning' })
]);
API.remoteServiceAction(action).then(L.bind(function(res) {
ui.hideModal();
if (res.success) {
ui.addNotification(null, E('p', {}, '✅ ' + (res.message || action)), 'info');
this.reload();
} else {
ui.addNotification(null, E('p', {}, res.error || _('Action failed')), 'error');
}
}, this)).catch(function(err) {
ui.hideModal();
ui.addNotification(null, E('p', {}, err.message || err), 'error');
});
},
saveRttySettings: function() {
var host = document.getElementById('rtty-host').value;
var port = parseInt(document.getElementById('rtty-port').value) || 5912;
var token = document.getElementById('rtty-token').value;
var description = document.getElementById('rtty-description').value;
var ssl = document.getElementById('rtty-ssl').classList.contains('active') ? 1 : 0;
if (!host) {
ui.addNotification(null, E('p', {}, _('Server host is required')), 'error');
return;
}
ui.showModal(_('Saving Settings'), [
E('p', {}, _('Saving rtty configuration...')),
E('div', { 'class': 'spinning' })
]);
API.remoteSaveSettings({
host: host,
port: port,
token: token,
description: description,
ssl: ssl
}).then(L.bind(function(result) {
ui.hideModal();
if (result.success) {
ui.addNotification(null, E('p', {}, _('Settings saved successfully')), 'info');
this.reload();
} else {
ui.addNotification(null, E('p', {}, result.error || _('Failed to save settings')), 'error');
}
}, this)).catch(function(err) {
ui.hideModal();
ui.addNotification(null, E('p', {}, err.message || err), 'error');
});
},
installRtty: function(ev) {
ev.preventDefault();
ui.showModal(_('Installing rtty'), [
E('p', {}, _('Installing rtty-openssl package...')),
E('div', { 'class': 'spinning' })
]);
API.remoteInstall().then(L.bind(function(result) {
ui.hideModal();
if (result.success) {
ui.addNotification(null, E('p', {}, result.message || _('Installed successfully')), 'info');
this.reload();
} else {
ui.addNotification(null, E('p', {}, result.error || _('Installation failed')), 'error');
}
}, this)).catch(function(err) {
ui.hideModal();
ui.addNotification(null, E('p', {}, err.message || err), 'error');
});
},
reload: function() {
this.load().then(L.bind(function(data) {
var node = this.render(data);
var root = document.querySelector('.system-hub-dashboard');
if (root && root.parentNode) {
root.parentNode.replaceChild(node, root);
}
}, this));
},
// TTYD Web Console methods
installTtyd: function(ev) {
ev.preventDefault();
ui.showModal(_('Installing Web Console'), [
E('p', {}, _('Installing ttyd...')),
E('div', { 'class': 'spinning' })
]);
API.ttydInstall().then(L.bind(function(result) {
ui.hideModal();
if (result.success) {
ui.addNotification(null, E('p', {}, _('Web Console installed successfully')), 'info');
this.reload();
} else {
ui.addNotification(null, E('p', {}, result.error || _('Installation failed')), 'error');
}
}, this)).catch(function(err) {
ui.hideModal();
ui.addNotification(null, E('p', {}, err.message || err), 'error');
});
},
startTtyd: function() {
ui.showModal(_('Starting Web Console'), [
E('p', {}, _('Starting ttyd service...')),
E('div', { 'class': 'spinning' })
]);
API.ttydStart().then(L.bind(function(result) {
ui.hideModal();
if (result.success) {
ui.addNotification(null, E('p', {}, _('Web Console started on port ') + result.port), 'info');
this.reload();
} else {
ui.addNotification(null, E('p', {}, result.error || _('Failed to start')), 'error');
}
}, this)).catch(function(err) {
ui.hideModal();
ui.addNotification(null, E('p', {}, err.message || err), 'error');
});
},
stopTtyd: function() {
API.ttydStop().then(L.bind(function(result) {
if (result.success) {
ui.addNotification(null, E('p', {}, _('Web Console stopped')), 'info');
this.reload();
} else {
ui.addNotification(null, E('p', {}, result.error || _('Failed to stop')), 'error');
}
}, this));
},
toggleTtyd: function() {
if (this.ttyd && this.ttyd.running) {
this.stopTtyd();
} else {
this.startTtyd();
}
},
openTtydFullscreen: function() {
var port = (this.ttyd && this.ttyd.port) || 7681;
window.open('http://' + window.location.hostname + ':' + port, '_blank');
},
refreshTtydStatus: function() {
API.ttydStatus().then(L.bind(function(status) {
this.ttyd = status;
var badge = document.getElementById('ttyd-status-badge');
var text = document.getElementById('ttyd-status-text');
var btn = document.getElementById('ttyd-toggle-btn');
if (badge) badge.textContent = status.running ? _('Running') : _('Stopped');
if (text) {
text.textContent = status.installed ? (status.running ? _('Running') : _('Stopped')) : _('Not Installed');
text.style.color = status.running ? '#22c55e' : '#f59e0b';
}
if (btn) btn.innerHTML = status.running ? '⏹️ ' + _('Stop') : '▶️ ' + _('Start');
// Reload to update iframe visibility
if (status.running !== this.ttyd.running) {
this.reload();
}
}, this));
},
handleSaveApply: null,
handleSave: null,
handleReset: null
});