| 关键词: nbsp crlf configuration ret foreach server persistKeys Servers phpmyadmin export |
Trace注:原文在http://xorl.wordpress.com/2009/04/23/cve-2009-1285-phpmyadmin-code-injection/ 貌似有的地方需要用代理看。 Well, I usually don’t blog about these bugs but phpMyAdmin is a project that is used almost everywhere and this is a quick and dirty way to get code execution. This issue affects phpMyAdmin 3.x before 3.1.3.2 and it was disclosed on 14 April 2009. The bug is present at setup/lib/ConfigFile.class.php file. Here is an outline of that file from 3.1.3.1 release: 1 <?php ...10 class ConfigFile11 {12 /**13 * Stores default PMA config from config.default.php14 * @var array15 */16 private $cfg; ...259 /**260 * Creates config file261 *262 * @return string263 */264 public function getConfigFile()265 {266 $crlf = (isset($_SESSION['eol']) && $_SESSION['eol'] == 'win') ? "\r\n" : "\n";267 $c = $_SESSION['ConfigFile'];268269 // header270 $ret = '<?php' . $crlf ...279 // servers280 if ($this->getServerCount() > 0) {281 $ret .= "/* Servers configuration */$crlf\$i = 0;" . $crlf . $crlf;282 foreach ($c['Servers'] as $id => $server) {283 $ret .= '/* Server: ' . $this->getServerName($id) . " [$id] */" . $crlf284 . '$i++;' . $crlf;285 foreach ($server as $k => $v) {286 $ret .= "\$cfg['Servers'][\$i]['$k'] = "287 . var_export($v, true) . ';' . $crlf;288 }289 $ret .= $crlf;290 }291 $ret .= '/* End of servers configuration */' . $crlf . $crlf;292 } ...So… function getConfigFile() retrieves various information. Here it constructs a configuration file and $ret includes the PHP code. At line 281 it starts the file with comment: /* Servers configuration */Then, as you can clearly see at line 283 the configuration will have a new comment which is: /* Server: <getServerName()> "id" */However, $id is completely user controlled since it’s derived from the session variable ConfigFile at line 267. For example, if a user specifies an $id of: bleh */ <?php echo date(); ?> /* He will end up with a configuration file that includes this: /* Server: <getServerName()> bleh */ <?php echo date(); ?> /* */This simple code injection was patched by limiting the user input using preg_replace() function like this: foreach ($c['Servers'] as $id => $server) {+ $k = preg_replace('/[^A-Za-z0-9_]/', '_', $k); $ret .= '/* Server: ' . $this->getServerName($id) . " [$id] */" . $crlfWhich replaces any matches of /[^A-Za-z0-9_]/ with _ and moves on with the next element. The same bug was also in the following code of the same function: 296 // other settings297 $persistKeys = $this->persistKeys;298 foreach ($c as $k => $v) {299 $ret .= "\$cfg['$k'] = " . var_export($v, true) . ';' . $crlf;300 if (isset($persistKeys[$k])) {301 unset($persistKeys[$k]);302 }303 }Where the exact same logic applies and also the same patch :-P foreach ($c as $k => $v) {+ $k = preg_replace('/[^A-Za-z0-9_]/', '_', $k); $ret .= "\$cfg['$k'] = " . var_export($v, true) . ';' . $crlf;There was another instance of that bug at the last loop of that function which was this: 305 // keep 1d array keys which are present in $persist_keys (config_info.inc.php)306 foreach (array_keys($persistKeys) as $k) {307 if (strpos($k, '/') === false) {308 $ret .= "\$cfg['$k'] = " . var_export($this->getDefault($k), true) . ';' . $crlf;309 }310 }311 $ret .= '?>';312313 return $ret;314 }315 }316 ?>Again, the concept is the same in the foreach() loop at line 306 and the patch was of course: if (strpos($k, '/') === false) {+ $k = preg_replace('/[^A-Za-z0-9_]/', '_', $k); $ret .= "\$cfg['$k'] = " . var_export($this->getDefault($k), true) . ';' . $crlf;The evil auditors among us would have caught that the bug is still there ;-) Don’t tell anyone… (I usually don’t write publicly about such things but what the hell… It’s just phpMyAdmin)! |
|
声明:文章版权归原作者所有 部分文章转自互联网 如有侵权请联系
[邮箱地址] 删除
|