Chr*_*ler 16 php mysql security
在我们的应用程序中,用户可以以SQL语句的形式创建自定义导出功能.像这样的东西:
SELECT name, age, date_birth FROM users WHERE group_id = 2
Run Code Online (Sandbox Code Playgroud)
我不希望他们通过插入DELETE语句来清除整个数据库.我的想法是:
我们正在使用PHP PDO.
Pet*_*ter 20
在我看来,有三种选择可供选择:
创建一个工具,在后台为用户创建查询.只需单击按钮并输入表格名称即可.通过这种方式,您可以在后台捕获所有奇怪的行为,使您不会因为不想执行的查询而面临危险.
创建仅允许执行SELECT
查询的MySQL用户.我相信你甚至可以决定允许用户选择哪些表.使用该用户执行用户输入的查询.创建有你想让它做你的权限一个单独的用户UPDATE
,INSERT
和DELETE
查询.
在执行查询之前,请确保其中没有任何有害内容.扫描查询以查找错误的语法.
例:
// Check if SELECT is in the query
if (preg_match('/SELECT/', strtoupper($query)) != 0) {
// Array with forbidden query parts
$disAllow = array(
'INSERT',
'UPDATE',
'DELETE',
'RENAME',
'DROP',
'CREATE',
'TRUNCATE',
'ALTER',
'COMMIT',
'ROLLBACK',
'MERGE',
'CALL',
'EXPLAIN',
'LOCK',
'GRANT',
'REVOKE',
'SAVEPOINT',
'TRANSACTION',
'SET',
);
// Convert array to pipe-seperated string
// strings are appended and prepended with \b
$disAllow = implode('|',
array_map(function ($value) {
return '\b' . $value . '\b';
}
), $disAllow);
// Check if no other harmfull statements exist
if (preg_match('/('.$disAllow.')/gai', $query) == 0) {
// Execute query
}
}
Run Code Online (Sandbox Code Playgroud)
注意:在执行此检查之前,您可以添加一些PHP代码来过滤掉注释
您要做的事情很有可能,但是您永远不会100%保证它是安全的.而不是让用户进行查询,最好使用API向用户提供数据.
既然你说过,如果有其他选择,你不愿意使用只读SQL帐户.如果你运行PHP 5.5.21+或5.6.5+:我建议检查查询的第一个语句是否是SELECT语句并禁用PDO连接中的多个查询.
首先禁用PDO对象上的多语句...
$pdo = new PDO('mysql:host=hostname;dbname=database', 'user', 'password', [PDO::MYSQL_ATTR_MULTI_STATEMENTS => false]);
Run Code Online (Sandbox Code Playgroud)
然后检查查询中的第一个语句是否使用SELECT并且没有子查询.第一个正则表达式忽略前导空格是可选的,第二个正则表示检测将用于创建子查询的括号 - 这确实会产生阻止用户使用SQL函数的副作用,但根据您的示例我不认为这是一个问题.
if (preg_match('/^(\s+)?SELECT/i', $query) && preg_match('/[()]+/', $query) === 0) {
// run query
}
Run Code Online (Sandbox Code Playgroud)
如果您运行的是旧版本,则可以禁用模拟准备以防止执行多个语句,但这依赖于正在使用的PDO :: prepare().
FWIW:使用预准备语句/为用户生成安全查询或使用只读SQL帐户会好得多.如果你正在使用MySQL并拥有管理员权限/远程访问权限,我建议使用SQLyog社区版(https://github.com/webyog/sqlyog-community/wiki/Downloads)创建只读用户帐户.它非常用户友好,因此您无需学习GRANT语法.
归档时间: |
|
查看次数: |
2510 次 |
最近记录: |