我正在尝试在MySql中编写一个存储过程,它将接受一个参数,然后检查该参数是否包含“DROP”,“INSERT”,“UPDATE”,“TRUNCATE”等任何文本,几乎任何不是SELECT语句的东西。我知道它并不理想,但遗憾的是SELECT语句是在客户端构建的,并且为了防止某种中间人改变,它只是服务器增加的安全级别。
我尝试过几种方法来完成它,但是,它对我不起作用。我想出了类似的东西:
CREATE PROCEDURE `myDatabase`.`execQuery` (in INC_query text)
BEGIN
#check to see if the incoming SQL query contains INSERT, DROP, TRUNCATE,
#or UPDATE as an added measure of security
IF (
SELECT LOCATE(LOWER(INC_query),'drop') OR
SELECT LOCATE(LOWER(INC_query),'truncate') OR
SELECT LOCATE(LOWER(INC_query),'insert') OR
SELECT LOCATE(LOWER(INC_query),'update') OR
SELECT LOCATE(LOWER(INC_query),'set')
>= 1)
THEN
SET @command = INC_query;
PREPARE statement FROM @command;
EXECUTE statement;
ELSE
SELECT * FROM database.otherTable; #just a generic output to know the procedure executed correctly, and will be removed later. Purely testing.
END IF;
END
即使它包含我的任何“可过滤”单词,它仍会执行查询。任何帮助都会受到赞赏,或者如果有更好的办法,我会全力以赴。
答案 0 :(得分:1)
如果您有一个名为updated_at
或settings
的列,该怎么办?你不可能期望这个按你的意愿工作。这种技术是网上clbuttic引用如此之多的原因。
如果你走这条路的话,你真的会弄得一团糟。
解决此问题的唯一合理方法是发送您要构建的查询类型的参数,然后使用经过审核的白名单允许的术语在您的应用程序中构建查询。用JSON表示的一个例子:
{
"select" : {
"table" : "users",
"columns" : [ "id", "name", "DROP TABLE users", "SUM(date)", "password_hash" ],
"joins" : {
"orders" : [ "users.id", "orders.user_id" ]
}
}
您只需创建一个发出此类事物的查询构造函数,另一个将其转换回有效查询。您可能只想列出要查询的特定列,因为某些列可能是秘密的,也可能只是内部的,不会被公开,例如本例中的password_hash
。
您还可以允许(SUM|MIN|MAX|AVG)\((\w+)\)
等模式捕获特定的分组操作或JOIN
条件。这取决于你想要走多远。