summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSimon Rettberg2020-07-30 17:21:29 +0200
committerSimon Rettberg2020-07-31 12:05:13 +0200
commit4e31f99e098568c5d133125630533dad91d07348 (patch)
treed6302d3d526a79f64c0b081581679f928f55da54
parent[exams] More sanity checks regarding date/time and locations (diff)
downloadslx-admin-4e31f99e098568c5d133125630533dad91d07348.tar.gz
slx-admin-4e31f99e098568c5d133125630533dad91d07348.tar.xz
slx-admin-4e31f99e098568c5d133125630533dad91d07348.zip
[serversetup-bwlp-ipxe/statistics] Sanitize strings from clients
Some string from the clients might not be well suited for utf-8 representation. Add wrapper functions that clean utf-8 strings, or convert ANSI strings to UTF-8 while removing problematic chars.
-rw-r--r--inc/util.inc.php33
-rw-r--r--modules-available/serversetup-bwlp-ipxe/api.inc.php2
-rw-r--r--modules-available/serversetup-bwlp-ipxe/inc/scriptbuilderbase.inc.php3
-rw-r--r--modules-available/serversetup-bwlp-ipxe/inc/scriptbuilderipxe.inc.php10
-rw-r--r--modules-available/statistics/api.inc.php24
5 files changed, 55 insertions, 17 deletions
diff --git a/inc/util.inc.php b/inc/util.inc.php
index 6be06bf6..83b2d54a 100644
--- a/inc/util.inc.php
+++ b/inc/util.inc.php
@@ -559,4 +559,37 @@ SADFACE;
}
}
+ /**
+ * Remove any non-utf8 sequences from string.
+ */
+ public static function cleanUtf8(string $string) : string
+ {
+ // https://stackoverflow.com/a/1401716/2043481
+ $regex = '/
+ (
+ (?: [\x00-\x7F] # single-byte sequences 0xxxxxxx
+ | [\xC0-\xDF][\x80-\xBF] # double-byte sequences 110xxxxx 10xxxxxx
+ | [\xE0-\xEF][\x80-\xBF]{2} # triple-byte sequences 1110xxxx 10xxxxxx * 2
+ | [\xF0-\xF7][\x80-\xBF]{3} # quadruple-byte sequence 11110xxx 10xxxxxx * 3
+ ){1,100} # ...one or more times
+ )
+ | . # anything else
+ /x';
+ return preg_replace($regex, '$1', $string);
+ }
+
+ /**
+ * Remove non-printable < 0x20 chars from ANSI string, then convert to UTF-8
+ */
+ public static function ansiToUtf8(string $string) : string
+ {
+ $regex = '/
+ (
+ (?: [\x20-\xFF] ){1,100} # ignore lower non-printable range
+ )
+ | . # anything else
+ /x';
+ return iconv('MS-ANSI', 'UTF-8', preg_replace($regex, '$1', $string));
+ }
+
}
diff --git a/modules-available/serversetup-bwlp-ipxe/api.inc.php b/modules-available/serversetup-bwlp-ipxe/api.inc.php
index dd559efa..dcfa7774 100644
--- a/modules-available/serversetup-bwlp-ipxe/api.inc.php
+++ b/modules-available/serversetup-bwlp-ipxe/api.inc.php
@@ -7,7 +7,7 @@
} else {
$builder = new ScriptBuilderIpxe();
}
- $bootEntryId = Request::get('beid', false, 'string');
+ $bootEntryId = Util::cleanUtf8(Request::get('beid', false, 'string'));
$entryId = Request::get('entryid', false, 'int');
if ($bootEntryId !== false) {
$entry = BootEntry::fromDatabaseId($bootEntryId);
diff --git a/modules-available/serversetup-bwlp-ipxe/inc/scriptbuilderbase.inc.php b/modules-available/serversetup-bwlp-ipxe/inc/scriptbuilderbase.inc.php
index b9867ed9..7bf9e2a3 100644
--- a/modules-available/serversetup-bwlp-ipxe/inc/scriptbuilderbase.inc.php
+++ b/modules-available/serversetup-bwlp-ipxe/inc/scriptbuilderbase.inc.php
@@ -59,6 +59,9 @@ abstract class ScriptBuilderBase
}
$this->hasExtension = $slxExtensions ?? (bool)Request::any('slx-extensions', false, 'int');
$this->uuid = Request::any('uuid', false, 'string');
+ if (!preg_match('/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i', $this->uuid)) {
+ $this->uuid = false;
+ }
}
/**
diff --git a/modules-available/serversetup-bwlp-ipxe/inc/scriptbuilderipxe.inc.php b/modules-available/serversetup-bwlp-ipxe/inc/scriptbuilderipxe.inc.php
index 1b33a1ac..a6376b0e 100644
--- a/modules-available/serversetup-bwlp-ipxe/inc/scriptbuilderipxe.inc.php
+++ b/modules-available/serversetup-bwlp-ipxe/inc/scriptbuilderipxe.inc.php
@@ -126,10 +126,8 @@ HERE;
{
if ($this->hasExtension) {
$slxConsoleUpdate = '--update';
- $slxPasswordOnly = '--nouser';
} else {
$slxConsoleUpdate = '';
- $slxPasswordOnly = '';
}
$serverIp = $this->serverIp;
@@ -258,19 +256,18 @@ HERE;
if ($special === 'localboot') {
// Get preferred localboot method, depending on system model
// Check if required arguments are given; if not, spit out according script and chain to self
- $uuid = Request::any('uuid', false, 'string');
// Get platform - EFI or PCBIOS
$manuf = Request::any('manuf', false, 'string');
$product = Request::any('product', false, 'string');
- if ($uuid === false && $manuf === false && $product === false) {
+ if ($this->uuid === false && $manuf === false && $product === false) {
return $this->redirect('special', 'localboot');
}
$BOOT_METHODS = Localboot::BOOT_METHODS[$this->platform];
$localboot = false;
$model = false;
- if ($uuid !== false && Module::get('statistics') !== false) {
+ if ($this->uuid !== false && Module::get('statistics') !== false) {
// If we have the machine table, we rather try to look up the system model from there, using the UUID
- $row = Database::queryFirst('SELECT systemmodel FROM machine WHERE machineuuid = :uuid', ['uuid' => $uuid]);
+ $row = Database::queryFirst('SELECT systemmodel FROM machine WHERE machineuuid = :uuid', ['uuid' => $this->uuid]);
if ($row !== false && !empty($row['systemmodel'])) {
$model = $row['systemmodel'];
}
@@ -284,6 +281,7 @@ HERE;
if (!empty($manuf)) {
$model .= " ($manuf)";
}
+ $model = Util::ansiToUtf8($model);
}
}
// Query
diff --git a/modules-available/statistics/api.inc.php b/modules-available/statistics/api.inc.php
index f7c0ac32..23b86ef4 100644
--- a/modules-available/statistics/api.inc.php
+++ b/modules-available/statistics/api.inc.php
@@ -51,8 +51,8 @@ if ($type{0} === '~') {
$kvmstate = Request::post('kvmstate', 'UNKNOWN', 'string');
$valid = array('UNKNOWN', 'UNSUPPORTED', 'DISABLED', 'ENABLED');
if (!in_array($kvmstate, $valid)) $kvmstate = 'UNKNOWN';
- $cpumodel = Request::post('cpumodel', '', 'string');
- $systemmodel = Request::post('systemmodel', '', 'string');
+ $cpumodel = Util::cleanUtf8(Request::post('cpumodel', '', 'string'));
+ $systemmodel = Util::cleanUtf8(Request::post('systemmodel', '', 'string'));
$id44mb = Request::post('id44mb', 0, 'integer');
if ($id44mb < 0 || $id44mb > 10240000) $id44mb = 0;
$badsectors = Request::post('badsectors', 0, 'integer');
@@ -61,7 +61,7 @@ if ($type{0} === '~') {
if (!is_string($hostname) || $hostname === $ip) {
$hostname = '';
}
- $data = Request::post('data', '', 'string');
+ $data = Util::cleanUtf8(Request::post('data', '', 'string'));
// Prepare insert/update to machine table
$new = array(
'uuid' => $uuid,
@@ -99,7 +99,7 @@ if ($type{0} === '~') {
$moresql .= ' hostname = :hostname,';
}
if (($runmode = Request::post('runmode', false, 'string')) !== false) {
- $new['currentrunmode'] = $runmode;
+ $new['currentrunmode'] = Util::cleanUtf8($runmode);
$moresql .= ' currentrunmode = :currentrunmode,';
}
$new['oldstate'] = $old['state'];
@@ -208,7 +208,7 @@ if ($type{0} === '~') {
}
}
if (($runmode = Request::post('runmode', false, 'string')) !== false) {
- $params['currentrunmode'] = $runmode;
+ $params['currentrunmode'] = Util::cleanUtf8($runmode);
$strUpdateBoottime .= ' currentrunmode = :currentrunmode, ';
}
// Figure out what's happening - state changes
@@ -227,6 +227,9 @@ if ($type{0} === '~') {
if ($sessionLength !== 0 || $old['logintime'] === 0) {
// This event is a start of a new session, rather than an update
$params['user'] = Request::post('user', null, 'string');
+ if (is_string($params['user'])) {
+ $params['user'] = Util::cleanUtf8($params['user']);
+ }
$res = Database::exec('UPDATE machine SET lastseen = UNIX_TIMESTAMP(),'
. $strUpdateBoottime
. " logintime = UNIX_TIMESTAMP(), currentuser = :user, currentsession = NULL, state = 'OCCUPIED' "
@@ -274,7 +277,8 @@ if ($type{0} === '~') {
if (!array_key_exists('name', $screen))
continue;
// Filter bogus data
- $screen['name'] = iconv('UTF-8', 'UTF-8//IGNORE', $screen['name']);
+ $screen['name'] = Util::cleanUtf8($screen['name']);
+ $port = Util::cleanUtf8($port);
if (empty($screen['name']))
continue;
if (array_key_exists($screen['name'], $hwids)) {
@@ -305,7 +309,7 @@ if ($type{0} === '~') {
. " VALUES (:id, :key, :value) ON DUPLICATE KEY UPDATE value = VALUES(value)", array(
'id' => $machinehwid,
'key' => $key,
- 'value' => $value,
+ 'value' => Util::cleanUtf8($value),
));
}
}
@@ -423,10 +427,10 @@ function writeClientLog($type, $description)
// For backwards compat, we require the . prefix
if ($type{0} === '.') {
if ($type === '.vmchooser-session') {
- $user = Request::post('user', 'unknown', 'string');
+ $user = Util::cleanUtf8(Request::post('user', 'unknown', 'string'));
$loguser = Request::post('loguser', 0, 'int') !== 0;
- $sessionName = Request::post('name', 'unknown', 'string');
- $sessionUuid = Request::post('uuid', '', 'string');
+ $sessionName = Util::cleanUtf8(Request::post('name', 'unknown', 'string'));
+ $sessionUuid = Util::cleanUtf8(Request::post('uuid', '', 'string'));
$session = strlen($sessionUuid) === 36 ? $sessionUuid : $sessionName;
Database::exec("UPDATE machine SET currentuser = :user, currentsession = :session WHERE clientip = :ip",
compact('user', 'session', 'ip'));