Skip to content

Commit bcedd68

Browse files
committed
Security fix: Replace all calls to unserialize() with calls to phpMyAdmin's safeUnserialize wrapper.
1 parent 480fa9e commit bcedd68

File tree

11 files changed

+124
-34
lines changed

11 files changed

+124
-34
lines changed

admin.php

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ function doCluster($type, $confirm=false) {
2020

2121
echo "<form action=\"{$script}\" method=\"post\">\n";
2222
foreach($_REQUEST['ma'] as $v) {
23-
$a = unserialize(htmlspecialchars_decode($v, ENT_QUOTES));
23+
$a = safeUnserialize(htmlspecialchars_decode($v, ENT_QUOTES));
2424
echo "<p>", sprintf($lang['strconfclustertable'], $misc->printVal($a['table'])), "</p>\n";
2525
echo "<input type=\"hidden\" name=\"table[]\" value=\"", htmlspecialchars($a['table']), "\" />\n";
2626
}
@@ -103,7 +103,7 @@ function doReindex($type, $confirm=false) {
103103

104104
echo "<form action=\"{$script}\" method=\"post\">\n";
105105
foreach($_REQUEST['ma'] as $v) {
106-
$a = unserialize(htmlspecialchars_decode($v, ENT_QUOTES));
106+
$a = safeUnserialize(htmlspecialchars_decode($v, ENT_QUOTES));
107107
echo "<p>", sprintf($lang['strconfreindextable'], $misc->printVal($a['table'])), "</p>\n";
108108
echo "<input type=\"hidden\" name=\"table[]\" value=\"", htmlspecialchars($a['table']), "\" />\n";
109109
}
@@ -181,7 +181,7 @@ function doAnalyze($type, $confirm=false) {
181181

182182
echo "<form action=\"{$script}\" method=\"post\">\n";
183183
foreach($_REQUEST['ma'] as $v) {
184-
$a = unserialize(htmlspecialchars_decode($v, ENT_QUOTES));
184+
$a = safeUnserialize(htmlspecialchars_decode($v, ENT_QUOTES));
185185
echo "<p>", sprintf($lang['strconfanalyzetable'], $misc->printVal($a['table'])), "</p>\n";
186186
echo "<input type=\"hidden\" name=\"table[]\" value=\"", htmlspecialchars($a['table']), "\" />\n";
187187
}
@@ -256,7 +256,7 @@ function doVacuum($type, $confirm = false) {
256256

257257
echo "<form action=\"{$script}\" method=\"post\">\n";
258258
foreach($_REQUEST['ma'] as $v) {
259-
$a = unserialize(htmlspecialchars_decode($v, ENT_QUOTES));
259+
$a = safeUnserialize(htmlspecialchars_decode($v, ENT_QUOTES));
260260
echo "<p>", sprintf($lang['strconfvacuumtable'], $misc->printVal($a['table'])), "</p>\n";
261261
echo "<input type=\"hidden\" name=\"table[]\" value=\"", htmlspecialchars($a['table']), "\" />\n";
262262
}

all_db.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ function doDrop($confirm) {
9797
// If multi drop
9898
if (isset($_REQUEST['ma'])) {
9999
foreach($_REQUEST['ma'] as $v) {
100-
$a = unserialize(htmlspecialchars_decode($v, ENT_QUOTES));
100+
$a = safeUnserialize(htmlspecialchars_decode($v, ENT_QUOTES));
101101
echo "<p>", sprintf($lang['strconfdropdatabase'], $misc->printVal($a['database'])), "</p>\n";
102102
printf('<input type="hidden" name="dropdatabase[]" value="%s" />', htmlspecialchars($a['database']));
103103
}

constraints.php

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ function addForeignKey($stage, $msg = '') {
3838
if (!isset($_POST['match'])) $_POST['match'] = null;
3939
if (!isset($_POST['deferrable'])) $_POST['deferrable'] = null;
4040
if (!isset($_POST['initially'])) $_POST['initially'] = null;
41-
$_REQUEST['target'] = unserialize($_REQUEST['target']);
41+
$_REQUEST['target'] = safeUnserialize($_REQUEST['target']);
4242

4343
$misc->printTrail('table');
4444
$misc->printTitle($lang['straddfk'],'pg.constraint.foreign_key');
@@ -129,16 +129,16 @@ function addForeignKey($stage, $msg = '') {
129129
break;
130130
case 3:
131131
// Unserialize target
132-
$_POST['target'] = unserialize($_POST['target']);
132+
$_POST['target'] = safeUnserialize($_POST['target']);
133133

134134
// Check that they've given at least one column
135-
if (isset($_POST['SourceColumnList'])) $temp = unserialize($_POST['SourceColumnList']);
135+
if (isset($_POST['SourceColumnList'])) $temp = safeUnserialize($_POST['SourceColumnList']);
136136
if (!isset($_POST['IndexColumnList']) || !is_array($_POST['IndexColumnList'])
137137
|| sizeof($_POST['IndexColumnList']) == 0 || !isset($temp)
138138
|| !is_array($temp) || sizeof($temp) == 0) addForeignKey(2, $lang['strfkneedscols']);
139139
else {
140140
$status = $data->addForeignKey($_POST['table'], $_POST['target']['schemaname'], $_POST['target']['tablename'],
141-
unserialize($_POST['SourceColumnList']), $_POST['IndexColumnList'], $_POST['upd_action'], $_POST['del_action'],
141+
safeUnserialize($_POST['SourceColumnList']), $_POST['IndexColumnList'], $_POST['upd_action'], $_POST['del_action'],
142142
$_POST['match'], $_POST['deferrable'], $_POST['initially'], $_POST['name']);
143143
if ($status == 0)
144144
doDefault($lang['strfkadded']);

display.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ function doEditRow($confirm, $msg = '') {
3131
if (is_array($_REQUEST['key']))
3232
$key = $_REQUEST['key'];
3333
else
34-
$key = unserialize(urldecode($_REQUEST['key']));
34+
$key = safeUnserialize(urldecode($_REQUEST['key']));
3535

3636
if ($confirm) {
3737
$misc->printTrail($_REQUEST['subject']);
@@ -238,7 +238,7 @@ function doDelRow($confirm) {
238238
echo "</form>\n";
239239
}
240240
else {
241-
$status = $data->deleteRow($_POST['table'], unserialize(urldecode($_POST['key'])));
241+
$status = $data->deleteRow($_POST['table'], safeUnserialize(urldecode($_POST['key'])));
242242
if ($status == 0)
243243
doBrowse($lang['strrowdeleted']);
244244
elseif ($status == -2)

fulltext.php

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -264,9 +264,9 @@ function doSaveCreateConfig() {
264264

265265
if ($err != '') return doCreateConfig($err);
266266

267-
if ($_POST['formParser'] != '') $formParser = unserialize($_POST['formParser']);
267+
if ($_POST['formParser'] != '') $formParser = safeUnserialize($_POST['formParser']);
268268
else $formParser = '';
269-
if ($_POST['formTemplate'] != '') $formTemplate = unserialize($_POST['formTemplate']);
269+
if ($_POST['formTemplate'] != '') $formTemplate = safeUnserialize($_POST['formTemplate']);
270270
else $formTemplate = '';
271271

272272
$status = $data->createFtsConfiguration($_POST['formName'], $formParser, $formTemplate, $_POST['formComment']);
@@ -667,7 +667,7 @@ function doSaveCreateDict() {
667667

668668
if(!isset($_POST['formIsTemplate'])) $_POST['formIsTemplate'] = false;
669669
if(isset($_POST['formTemplate']))
670-
$formTemplate = unserialize($_POST['formTemplate']);
670+
$formTemplate = safeUnserialize($_POST['formTemplate']);
671671
else
672672
$formTemplate = '';
673673
if(!isset($_POST['formLexize'])) $_POST['formLexize'] = '';
@@ -773,7 +773,7 @@ function doDropMapping($confirm) {
773773
if (isset($_REQUEST['ma'])) {
774774

775775
foreach($_REQUEST['ma'] as $v) {
776-
$a = unserialize(htmlspecialchars_decode($v, ENT_QUOTES));
776+
$a = safeUnserialize(htmlspecialchars_decode($v, ENT_QUOTES));
777777
echo "<p>", sprintf($lang['strconfdropftsmapping'], $misc->printVal($a['mapping']), $misc->printVal($_REQUEST['ftscfg'])), "</p>\n";
778778
printf('<input type="hidden" name="mapping[]" value="%s" />', htmlspecialchars($a['mapping']));
779779
}
@@ -835,7 +835,7 @@ function doAlterMapping($msg = '') {
835835
$ma_mappings = array();
836836
$ma_mappings_names = array();
837837
foreach($_REQUEST['ma'] as $v) {
838-
$a = unserialize(htmlspecialchars_decode($v, ENT_QUOTES));
838+
$a = safeUnserialize(htmlspecialchars_decode($v, ENT_QUOTES));
839839
printf('<input type="hidden" name="formMapping[]" value="%s" />', htmlspecialchars($a['mapping']));
840840
$ma_mappings[] = $data->getFtsMappingByName($_POST['ftscfg'], $a['mapping']);
841841
$ma_mappings_names[] = $a['mapping'];

functions.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -426,7 +426,7 @@ function doDrop($confirm) {
426426
//If multi drop
427427
if (isset($_REQUEST['ma'])) {
428428
foreach($_REQUEST['ma'] as $v) {
429-
$a = unserialize(htmlspecialchars_decode($v, ENT_QUOTES));
429+
$a = safeUnserialize(htmlspecialchars_decode($v, ENT_QUOTES));
430430
echo "<p>", sprintf($lang['strconfdropfunction'], $misc->printVal($a['function'])), "</p>\n";
431431
echo '<input type="hidden" name="function[]" value="', htmlspecialchars($a['function']), "\" />\n";
432432
echo "<input type=\"hidden\" name=\"function_oid[]\" value=\"", htmlspecialchars($a['function_oid']), "\" />\n";

libraries/lib.inc.php

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -286,3 +286,93 @@
286286
}
287287

288288
$plugin_manager = new PluginManager($_language);
289+
290+
/**
291+
* Safe unserializer wrapper
292+
*
293+
* It does not unserialize data containing objects
294+
*
295+
* Function from phpMyAdmin version 5.2.1
296+
*
297+
* @param string $data Data to unserialize
298+
*
299+
* @return mixed|null
300+
*/
301+
function safeUnserialize(string $data) {
302+
/* validate serialized data */
303+
$length = strlen($data);
304+
$depth = 0;
305+
for ($i = 0; $i < $length; $i++) {
306+
$value = $data[$i];
307+
308+
switch ($value) {
309+
case '}':
310+
/* end of array */
311+
if ($depth <= 0) {
312+
return null;
313+
}
314+
315+
$depth--;
316+
break;
317+
case 's':
318+
/* string */
319+
// parse sting length
320+
$strlen = intval(substr($data, $i + 2));
321+
// string start
322+
$i = strpos($data, ':', $i + 2);
323+
if ($i === false) {
324+
return null;
325+
}
326+
327+
// skip string, quotes and ;
328+
$i += 2 + $strlen + 1;
329+
if ($data[$i] !== ';') {
330+
return null;
331+
}
332+
333+
break;
334+
335+
case 'b':
336+
case 'i':
337+
case 'd':
338+
/* bool, integer or double */
339+
// skip value to separator
340+
$i = strpos($data, ';', $i);
341+
if ($i === false) {
342+
return null;
343+
}
344+
345+
break;
346+
case 'a':
347+
/* array */
348+
// find array start
349+
$i = strpos($data, '{', $i);
350+
if ($i === false) {
351+
return null;
352+
}
353+
354+
// remember nesting
355+
$depth++;
356+
break;
357+
case 'N':
358+
/* null */
359+
// skip to end
360+
$i = strpos($data, ';', $i);
361+
if ($i === false) {
362+
return null;
363+
}
364+
365+
break;
366+
default:
367+
/* any other elements are not wanted */
368+
return null;
369+
}
370+
}
371+
372+
// check unterminated arrays
373+
if ($depth > 0) {
374+
return null;
375+
}
376+
377+
return unserialize($data);
378+
}

schemas.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -274,7 +274,7 @@ function doDrop($confirm) {
274274
//If multi drop
275275
if (isset($_REQUEST['ma'])) {
276276
foreach($_REQUEST['ma'] as $v) {
277-
$a = unserialize(htmlspecialchars_decode($v, ENT_QUOTES));
277+
$a = safeUnserialize(htmlspecialchars_decode($v, ENT_QUOTES));
278278
echo '<p>', sprintf($lang['strconfdropschema'], $misc->printVal($a['nsp'])), "</p>\n";
279279
echo '<input type="hidden" name="nsp[]" value="', htmlspecialchars($a['nsp']), "\" />\n";
280280
}

sequences.php

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -297,18 +297,18 @@ function doDrop($confirm, $msg = '') {
297297
doDefault($lang['strspecifysequencetodrop']);
298298
exit();
299299
}
300-
300+
301301
if ($confirm) {
302302
$misc->printTrail('sequence');
303303
$misc->printTitle($lang['strdrop'],'pg.sequence.drop');
304304
$misc->printMsg($msg);
305-
305+
306306
echo "<form action=\"sequences.php\" method=\"post\">\n";
307-
307+
308308
//If multi drop
309309
if (isset($_REQUEST['ma'])) {
310310
foreach($_REQUEST['ma'] as $v) {
311-
$a = unserialize(htmlspecialchars_decode($v, ENT_QUOTES));
311+
$a = safeUnserialize(htmlspecialchars_decode($v, ENT_QUOTES));
312312
echo "<p>", sprintf($lang['strconfdropsequence'], $misc->printVal($a['sequence'])), "</p>\n";
313313
printf('<input type="hidden" name="sequence[]" value="%s" />', htmlspecialchars($a['sequence']));
314314
}

tables.php

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -330,7 +330,7 @@ function doCreateLike($confirm, $msg = '') {
330330

331331
if (!isset($_REQUEST['tablespace'])) $_REQUEST['tablespace'] = '';
332332

333-
$status = $data->createTableLike($_REQUEST['name'], unserialize($_REQUEST['like']), isset($_REQUEST['withdefaults']),
333+
$status = $data->createTableLike($_REQUEST['name'], safeUnserialize($_REQUEST['like']), isset($_REQUEST['withdefaults']),
334334
isset($_REQUEST['withconstraints']), isset($_REQUEST['withindexes']), $_REQUEST['tablespace']);
335335

336336
if ($status == 0) {
@@ -563,7 +563,7 @@ function doInsertRow($confirm, $msg = '') {
563563
else {
564564
if (!isset($_POST['values'])) $_POST['values'] = array();
565565
if (!isset($_POST['nulls'])) $_POST['nulls'] = array();
566-
$_POST['fields'] = unserialize(htmlspecialchars_decode($_POST['fields'], ENT_QUOTES));
566+
$_POST['fields'] = safeUnserialize(htmlspecialchars_decode($_POST['fields'], ENT_QUOTES));
567567

568568
if ($_SESSION['counter']++ == $_POST['protection_counter']) {
569569
$status = $data->insertRow($_POST['table'], $_POST['fields'], $_POST['values'],
@@ -604,7 +604,7 @@ function doEmpty($confirm) {
604604

605605
echo "<form action=\"tables.php\" method=\"post\">\n";
606606
foreach ($_REQUEST['ma'] as $v) {
607-
$a = unserialize(htmlspecialchars_decode($v, ENT_QUOTES));
607+
$a = safeUnserialize(htmlspecialchars_decode($v, ENT_QUOTES));
608608
echo "<p>", sprintf($lang['strconfemptytable'], $misc->printVal($a['table'])), "</p>\n";
609609
printf('<input type="hidden" name="table[]" value="%s" />', htmlspecialchars($a['table']));
610610
}
@@ -669,7 +669,7 @@ function doDrop($confirm) {
669669

670670
echo "<form action=\"tables.php\" method=\"post\">\n";
671671
foreach($_REQUEST['ma'] as $v) {
672-
$a = unserialize(htmlspecialchars_decode($v, ENT_QUOTES));
672+
$a = safeUnserialize(htmlspecialchars_decode($v, ENT_QUOTES));
673673
echo "<p>", sprintf($lang['strconfdroptable'], $misc->printVal($a['table'])), "</p>\n";
674674
printf('<input type="hidden" name="table[]" value="%s" />', htmlspecialchars($a['table']));
675675
}

0 commit comments

Comments
 (0)