在标准Ajax中,where
和order by
SQL子句是由程序(而不是用户)提供的,例如
var url = ".select?dd=emp&where="+escape("emp_tp='abc' and hire_dt<current_date-'2 years' and super_emp_id is distinct from emp_id")
在服务器上被
应答$where = (isset($_GET['where'])) ? pureClause($_GET['where']) : null;
$order = (isset($_GET['order'])) ? pureClause($_GET['order']) : null;
...
$query = $query.(($where)?" where $where":'').(($order)?" order by $order":'');
问题是pureClause
函数应该是什么样的?
现在pureClause
只是抛出错误,如果有以下任何一个存在:
; select insert update delete drop create truncate
如果其他注入导致查询失败,没关系,只要数据未损坏。
对我来说这似乎足够了,但在我心里,我知道我错了。
澄清:
- Postgres中的
- 预处理语句虽然非常快,但设置和维护起来很麻烦——它们适用于使用良好的查询,但不适用于自定义查询。
- 为每个事务创建一个准备好的语句是一个巨大的数据库冲击。如果可以在应用程序级别获得安全性,则更可取。
emp_tp='abc' and hire_dt=current_dt-'2 years' and super_emp_id is distinct from emp_id
这里有多少占位符?在将其输入到带有占位符的预处理语句之前,需要对其进行正确解析,对吗?还是我完全错过了机会?
主要事实:
- not为参数化准备语句编写SQL子句解析器
- not编写一个SQL子句清理程序来保证没有危害
解决方案:
用于select,其中随机SQL可能是一个问题:因为保护数据库太难了,让数据库保护自己吧!不同的用户具有不同的角色/权限。使用只读用户进行选择。对于普通SQL,这保证了这些语句中没有DML。
最佳实践:四个 db用户访问
-
developer
,做一切(绝不使用作为web应用程序的连接) -
dml
-可以选择/dml在几乎所有(必须使用dml) -
read
-可以选择(用于所有选择,无论是准备的还是文本) -
login
-只能执行登录/密码功能(在登录过程中使用)
密码保护:
-
dml
和read
不能访问密码数据,通过select或dml -
login
只能通过受保护的函数(例如 )访问密码数据
- 只有
login
可以运行login()
和set_password()
函数 根据您的数据库, - 根据你的数据库,
password
列可以保护自己;如果没有,那么应该从user
表移到它自己的安全表 中。
login
可能需要sql访问密码列在mysql
中使用管理员工具进行设置,花费了大约30分钟,包括编写登录函数和拆分密码列的时间。
您正在做的是sql注入的定义,不能被清理。您不能以安全的方式传入WHERE
子句句号。您必须在服务器端构建查询的这一部分。事实上,你没有认识到这意味着你必须阅读更多关于sql注入,显然问StackOverflow是一个不安全的方法来解决这个问题。担心的是,您可能永远不会了解这个漏洞的基本原理。
$order
可以通过白名单安全完成。例如:
if(in_array($_GET['order'],$list_of_rows)){
$order=$_GET['order'];
}
如果您正在传递表名或列名,请确保将其与白名单进行检查,否则这将是sql注入。
明白了!通过数据库用户(连接)路由所有这些查询,该用户在数据库上只被授予SELECT权限!
尝试DML将阻塞。这并不能防止DoS攻击(有很多方法可以做到这一点!),但确实可以保护数据。也不能保证安全查询,比如登录。但是对于客户端生成的WHERE和ORDER,以防止DML为目标,这应该工作得很好。
10/15年前总是为不同的角色设置不同的用户,但随着应用程序层等的出现,这种习惯已经过时了。重新投资这些原则可能是个好主意。
除非hear different将其标记为正确答案-它满足所有标准,但它避开了理论上不可能的挑战,即编写消毒程序。
始终使用预处理语句。它将处理输入转义并避免sql注入。不需要像pureClause
这样的黑客。查看mysqli_stmt::prepare()
正如@Stephen建议的那样,提供WHERE作为对象,然后解析该对象并生成安全的SQLVar where = {emp_tp: {条件:平等价值:"abc"}Var order = {emp_tp:"ASC"}
发送json:
var params = {
w: where,
o: order
}
$.post(url,params,function(result){...}, 'json');
在PHP中
$where = isset($_POST['w']) ? json_decode($_POST['w') : array();
if (!empty($where)) {
foreach ($where as $field => $data) {
// validate that field exists
// validate that operator is valid
$sql .= sprintf('%s %s "%s"', $field, $data->operator, mysql_escape_string($data->value));
}
}