From cea2644812df118fbc9beb2223f8a09eac35f494 Mon Sep 17 00:00:00 2001 From: Joshua Smith Date: Fri, 25 May 2018 13:44:24 -0400 Subject: [PATCH 1/2] Write tests to demonstrate CVE-2015-5243 See #19 --- tests/ParserTest.php | 83 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 83 insertions(+) diff --git a/tests/ParserTest.php b/tests/ParserTest.php index 41413a61..8e601abe 100644 --- a/tests/ParserTest.php +++ b/tests/ParserTest.php @@ -133,4 +133,87 @@ public function get_date(string $date, string $format, string $expected) $this->assertEquals($expected, $actual); } + + /** + * @return void + * + * @test + * @group CVE-2015-5243 + */ + public function generic_parser_a_blocks() + { + $rawData = ["Registrant Name: \${k}\n"]; + $translate = [ + 'Registrant Name' => 'owner.name', + ]; + $disclaimer = ''; + + $output = generic_parser_a_blocks($rawData, $translate, $disclaimer); + $this->assertEquals('${k}', $output['main']['owner']['name']); + } + + /** + * @return void + * + * @test + * @group CVE-2015-5243 + */ + public function generic_parser_b() + { + $rawData = ["Registrant Name: \${field}\n"]; + + $output = generic_parser_b($rawData); + $this->assertEquals('${field}', $output['owner']['name']); + } + + /** + * @return void + * + * @test + * @group CVE-2015-5243 + */ + public function get_blocks_one() + { + $rawData = ["Domain: \${field}\n"]; + $items = [ + 'domain.name' => 'Domain:', + ]; + + $output = get_blocks($rawData, $items); + $this->assertEquals('${field}', $output['domain']['name']); + } + + /** + * @return void + * + * @test + * @group CVE-2015-5243 + */ + public function get_blocks_two() + { + $rawData = [ + "Registrar:\n", + "\tName:\t \${field}\n", + ]; + $items = [ + 'agent' => 'Registrar:', + ]; + + $output = get_blocks($rawData, $items); + $this->assertEquals("Name:\t \${field}", $output['agent'][0]); + } + + /** + * @return void + * + * @test + * @group CVE-2015-5243 + */ + public function get_contact() + { + $rawData = ["fax: \${field}\n"]; + + $output = get_contact($rawData); + $this->assertEquals('${field}', $output['fax']); + } } From 863ccf62824f9998099ed20c2952ec8953ce3d06 Mon Sep 17 00:00:00 2001 From: Joshua Smith Date: Fri, 18 May 2018 13:32:33 -0400 Subject: [PATCH 2/2] Fix CVE-2015-5243 Based on code by David Saez PAdros sparc See https://github.com/sparc/phpWhois.org/compare/18849d1a98b992190612cdb2561e7b4492c505f5...8c6a18686775b25f05592dd67d7706e47167a498#diff-b8adbe1292f8abca1f943aa844db52aa Fixes #19 --- src/whois.parser.php | 72 ++++++++++++++++++++++++++++++-------------- 1 file changed, 49 insertions(+), 23 deletions(-) diff --git a/src/whois.parser.php b/src/whois.parser.php index ab822eab..655de3ea 100644 --- a/src/whois.parser.php +++ b/src/whois.parser.php @@ -110,7 +110,7 @@ function generic_parser_a_blocks($rawdata, $translate, &$disclaimer) { if ($k == '') continue; if (strstr($k, '.')) { - eval("\$block" . getvarname($k) . "=\$v;"); + $block = assign($block, $k, $v); continue; } } else @@ -350,11 +350,11 @@ function generic_parser_b($rawdata, $items = array(), $dateformat = 'mdy', $hasr if ($pos !== false) { if ($field != '') { - $var = '$r' . getvarname($field); $itm = trim(substr($val, $pos + strlen($match))); - if ($itm != '') - eval($var . '="' . str_replace('"', '\"', $itm) . '";'); + if ($itm != '') { + $r = assign($r, $field, str_replace('"', '\"', $itm)); + } } if (!$scanall) @@ -378,17 +378,45 @@ function generic_parser_b($rawdata, $items = array(), $dateformat = 'mdy', $hasr return $r; } -function getvarname($vdef) { - $parts = explode('.', $vdef); - $var = ''; +/** + * @param array $array The array to populate + * @param string[] $parts + * @param mixed $value The value to be assigned to the $vDef key + * + * @return array The updated array + * @see https://github.com/sparc/phpWhois.org/compare/18849d1a98b992190612cdb2561e7b4492c505f5...8c6a18686775b25f05592dd67d7706e47167a498#diff-b8adbe1292f8abca1f943aa844db52aa Original fix by David Saez PAdros sparc + */ +function assign_recursive(array $array, array $parts, $value) +{ + $key = array_shift($parts); - foreach ($parts as $mn) - if ($mn == '') - $var = $var . '[]'; - else - $var = $var . '["' . $mn . '"]'; + if (count($parts) === 0) { + if (!$key) { + $array[] = $value; + } else { + $array[$key] = $value; + } + } else { + if (!isset($array[$key])) { + $array[$key] = []; + } + $array[$key] = assign_recursive($array[$key], $parts, $value); + } - return $var; + return $array; +} + +/** + * @param array $array The array to populate + * @param string $vDef A period-separated string of nested array keys + * @param mixed $value The value to be assigned to the $vDef key + * + * @return array The updated array + * @see https://github.com/sparc/phpWhois.org/compare/18849d1a98b992190612cdb2561e7b4492c505f5...8c6a18686775b25f05592dd67d7706e47167a498#diff-b8adbe1292f8abca1f943aa844db52aa Original fix by David Saez PAdros sparc + */ +function assign(array $array, string $vDef, $value) +{ + return assign_recursive($array, explode('.', $vDef), $value); } /** @@ -431,9 +459,8 @@ function get_blocks($rawdata, $items, $partial_match = false, $def_block = false $endtag = $last; $line = $val; } else { - $var = getvarname(strtok($field, '#')); - $itm = trim(substr($val, $pos + strlen($match))); - eval('$r' . $var . '=$itm;'); + $var = strtok($field, '#'); + $r = assign($r, $var, trim(substr($val, $pos + strlen($match)))); } break; @@ -499,9 +526,10 @@ function get_blocks($rawdata, $items, $partial_match = false, $def_block = false $pos = strpos($line, $match); if ($pos !== false) { - $var = getvarname(strtok($field, '#')); - if ($var != '[]') - eval('$r' . $var . '=$block;'); + $var = strtok($field, '#'); + if ($var != '[]') { + $r = assign($r, $var, $block); + } } } } @@ -582,6 +610,7 @@ function get_contact($array, $extra_items = array(), $has_org = false) { $items = $extra_items; } + $r = []; foreach ($array as $key => $val) { $ok = true; @@ -597,11 +626,8 @@ function get_contact($array, $extra_items = array(), $has_org = false) { $itm = trim(substr($val, $pos + strlen($match))); - /** - * @todo Get rid of eval - */ if ($field != '' && $itm != '') { - eval('$r' . getvarname($field) . '=$itm;'); + $r = assign($r, $field, $itm); } $val = trim(substr($val, 0, $pos));