在标准 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
如果是其他注入(inject)导致查询失败,那也没关系,只要数据没有损坏。
对我来说这似乎足够了,但在我心里,我知道我错了。
说明:
- 在 Postgres 中准备好的语句虽然速度非常快,但设置和维护起来很麻烦 - 它们适用于使用良好的查询,但不适用于自定义查询。
- 为每个事务创建准备好的语句是巨大 数据库命中。如果可以在应用程序级别实现安全性,则更受欢迎。
最后,考虑where子句
emp_tp='abc' and hire_dt=current_dt-'2 years' and super_emp_id is distinct from emp_id
这里有多少个占位符?在将其输入带有占位符的准备好的语句之前,需要对其进行正确解析,对吗?还是我完全错过了船?
主要事实:
- 不为参数化准备好的语句编写 SQL 子句解析器是可行的
- 不编写保证无害的 SQL 子句清理器是不切实际的
解决方法:
对于 SELECTS,随机 SQL 可能是一个问题:既然保护数据库太难了,就让数据库保护自己吧!有不同的用户有不同的 Angular 色/权限。使用只读用户进行选择。对于普通 SQL,这保证了这些语句中没有 DML。
最佳实践:四个 db 用户访问
开发人员
,做所有事情(从不在网络应用程序中用作连接)dml
- 几乎可以对所有内容进行选择/dml(必须用于 dml)read
- 可以选择(用于所有选择,无论是准备好的还是文本)login
- 只能执行登录/密码功能(在登录过程中使用)
密码保护:
dml
和read
可能无法通过 select 或 dml 访问密码数据login
应仅通过 protected 函数访问密码数据,例如,
function login( username, password ) - returns user_id function set_password( usr_id, password ) - sets password
- 只有
login
可以运行login()
和set_password()
函数 - 根据您的数据库,
登录
可能需要对密码列进行 sql 访问 - 根据您的数据库,
password
列本身可能受到保护;如果不是,则应该从user
表中移出到它自己的安全表中
在 mysql
中使用管理员工具进行设置,大约需要 30 分钟,包括编写登录函数和拆分密码列的时间。
最佳答案
您正在做的是 sql 注入(inject)的定义,无法清除。您不能以安全的方式传入 WHERE
子句故事的结尾。您必须在服务器端构建这部分查询。事实上,您没有意识到这一点意味着您必须阅读更多有关 sql 注入(inject)的信息,明确询问 StackOverflow 是解决此问题的不安全方法。担心的是您可能永远无法了解此漏洞的基础知识。
$order
可以使用白名单以安全的方式完成。例如:
if(in_array($_GET['order'],$list_of_rows)){
$order=$_GET['order'];
}
如果您传入表名或列名,请确保将其与白名单进行检查,否则这将是 sql 注入(inject)。
关于javascript - sql 注入(inject) - 如何清理程序生成的 sql 子句?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7291630/