CLP-01-003 SQL Injection in PHP Backend (High)

The PHP backend is vulnerable to SQL injection attacks. The method
GetList() of the object class user, record, recordversion,
onetimepasswordstatus, and onetimepassword does not sanitize its
parameters sufficiently before adding these to a dynamically constructed
SQL query. Affected are the $sortBy and $limit parameter.

function GetList($fcv_array = array(), $sortBy='', $ascending=true,
$limit='') {
$sqlLimit = ($limit != '' ? "LIMIT $limit" : '');
$this->pog_query = "select * from `onetimepassword` ";
[...]
$this->pog_query .= " order by ".$sortBy." ".($ascending ? "asc" :
"desc")." $sqlLimit";
$cursor = Database::Reader($this->pog_query, $connection);
[...]
}

A vulnerable call of this method can be found in the function
RefreshTree() of the file setup/rpc.php. Its first parameter is passed
to the $sortBy parameter and the two last parameters are passed
concatenated to the $limit parameter of the vulnerable GetList() method.

function RefreshTree($objectName, $root, $offset = '', $limit = '') {
     $sqlLimit = "$offset, $limit";
$instanceList = $instance->GetList(
array(array(strtolower($objectName)."Id",">",0)),
     strtolower($objectName)."Id",
false,
$sqlLimit
);
}

The function RefreshTree() is called with unsanitized parameters when
the GET parameter action is set to Refresh.

$objectName = isset($_REQUEST['objectname']) ? $_REQUEST['objectname'] : '';
$limit = isset($_REQUEST['limit']) ? $_REQUEST['limit'] : '';
$offset = isset($_REQUEST['offset']) ? $_REQUEST['offset'] : '';
$action = $_GET['action'];
switch($action) {
case 'Refresh':
   RefreshTree($objectName, $root, $offset, $limit);
}

An attacker is able to extract arbitrary data from the database,
including user data and OTP keys.

/setup/rpc.php?action=Refresh&objectname=user&offset=1&limit=1 union
select onetimepasswordid,userid,reference,key,key_checksum,data,7,8,9
from clipperz.onetimepassword

The construction of the WHERE clause from the parameter $fcv_array in
the GetList() method is also potentially affected by SQL injection.
Here, expected numeric values are added to the SQL query without
escaping or type-casting.

if(isset($this->pog_attribute_type[$fcv_array[$i][0]]['db_attributes'])
&& $this->pog_attribute_type[$fcv_array[$i][0]]['db_attributes'][0] !=
'NUMERIC'
&& $this->pog_attribute_type[$fcv_array[$i][0]]['db_attributes'][0] !=
'SET') {
}
else {
value = POG_Base::IsColumn($fcv_array[$i][2]) ? $fcv_array[$i][2] :
"'".$fcv_array[$i][2]."'";
$this->pog_query .= "`".$fcv_array[$i][0]."` ".$fcv_array[$i][1]." ".$value;
}

Expected numeric values should be converted to integer before embedding
them into the SQL query. Otherwise, an attacker is able to break out of
the single quotes and inject her own SQL syntax. For more security it is
highly recommended to use prepared statements, as done in the Python and
Java backend.
