php – MySQL – 检查查询的6个第一个字符以确保它是SELECT是否安全?

我的同事写了一些非常糟糕的东西.
我们的老板希望能够从我们网站的后台编写任何SELECT查询,然后以CSV格式获得结果.

这些查询将由我们的PRODUCTION MySQL集群执行.
此后台功能应拒绝任何非SELECT查询.

所以他提出了一个非常天真的解决方案.
这是PHP代码:

function checkQuery()
{
        $sQuery = trim($_POST['query']);
        if (empty($sQuery))
                return false;
        $sCmd = substr($sQuery, 0, 6);
        if (strtolower($sCmd) != 'select')
                return errorDiv('Only SELECT queries are authorized');
        return $sQuery;
}

对于不了解PHP的人,此代码从SQL查询字符串的开头和结尾删除空格,然后获取6个第一个字符,将它们转换为小写字符,如果它不匹配(erf …松散匹配)’select’,查询被拒绝.

它对我来说看起来很糟糕和令人作呕.
我试图说服他创建至少另一个具有有限权限的MySQL用户,但他太懒了.

但是我不能证明他有某种黑客是可能的.

他使用mysql_query()来运行查询字符串,此驱动程序一次拒绝多个查询.
我找不到任何真正的漏洞利用,但我认为至少有50%的可能性会发生.

也许一些NUL char,或者一些阻碍utf-8字符可以做到这一点?

最佳答案
我没有看到任何方法绕过你同事的checkQuery例程.如果您没有在PHP中使用mysql_ *函数,那将是微不足道的,但由于它们只允许执行单个语句,因此它们至少不会受到像Little Bobby Tables攻击风格这样的经典攻击.事实上,这是mysql_ *和mysqli_ *中标准查询函数不允许多个语句的关键原因之一(这在mysqli Multiple Statements documentation中有描述).

我看过其他路线,我很满意你的同事的代码确实有效. (有一种产生误报的方法,例如,即使在有效的SELECT查询中也会触发检测,但这对你来说没什么用处.)只要你没有将数据作为副作用改变的功能,它就不应该除了SELECT之外,还可以用一个开始SELECT的语句来做任何事情….

有可能使用SELECT ... INTO OUTFILE将新文件写入服务器.这仅限于新文件,所以你不能破坏/ etc / passwd,或其他什么,但有危险.

我能看到的最危险的情况是,如果您的MySQL服务器与您的PHP服务器是同一台机器,您的MySQL用户可以写入您的PHP目录,而您正在使用的用户具有FILE权限.在这种情况下,精心设计的SELECT … INTO OUTFILE沿着这些方向:

SELECT '<?php echo \'DANGER WILL ROBINSON!\';' INTO OUTFILE '/Users/matt/Sites/dangerous.php'

可能允许某人创建一个新的PHP文件,然后可以通过浏览它来执行,此时有人可以执行任意PHP代码.我在本地测试了这个潜在的漏洞,在给予用户SELECT和FILE权限并允许MySQL对我的wwwroot进行写访问之后,我可以成功创建一个带有上述代码的PHP文件并在我的浏览器中执行它.

除了特定线路上的攻击,如果您当前使用的用户没有FILE权限,这可能是不可能的,我看不出太多危险.我知道这对你没有多大帮助,但它似乎确实是你问题的答案.

但是,我仍然强烈建议您使用MySQL身份验证和安全性为仅具有SELECT权限的此应用程序创建新用户.这是内置的,数据库级的,完全标准的,经过充分验证的,经过良好测试的解决问题的方法,并限制了潜在的未来问题.

例如,如果某人以某种其他方式攻击您的PHP服务器,那么在能够读取您的MySQL用户密码的程度上,他们就可以访问具有高权限的经过身份验证的用户,他们可以将其用于其他攻击(可能是通过投掷他们自己的脚本到你的PHP服务器上并运行它们.)如果MySQL用户只是SELECT,那就限制了你的数据/数据库可能造成的损害,即使你的PHP服务器完全被破坏了.

转载注明原文:php – MySQL – 检查查询的6个第一个字符以确保它是SELECT是否安全? - 代码日志