使用参数如何防止SQL注入?
使用参数如何防止SQL注入 很多人都说,使用参数而不是输入字符串(例如,来自网站用户)可以防止SQL注入使用参数如何防止SQL注入?,sql,sql-injection,Sql,Sql Injection,使用参数如何防止SQL注入 很多人都说,使用参数而不是输入字符串(例如,来自网站用户)可以防止SQL注入 但我不明白,我的意思是“drop database”字符串与在查询中使用的参数中输入的“drop database”字符串有何不同 myfunction(myuser) { sql="SELECT user, password FROM users WHERE user='"+myuser+"'" return db.execute(sql) } 攻击者可通过此调用利用此漏
但我不明白,我的意思是“drop database”字符串与在查询中使用的参数中输入的“drop database”字符串有何不同
myfunction(myuser)
{
sql="SELECT user, password FROM users WHERE user='"+myuser+"'"
return db.execute(sql)
}
攻击者可通过此调用利用此漏洞获取表的所有密码:
myfunction("x' OR true OR 'a'='")
相反,如果程序员通过绑定变量执行查询:
myfunction(myuser)
{
sql="SELECT user, password FROM users WHERE user=?"
sql.setParam(1, myUser)
return db.execute(sql)
}
在这种情况下,攻击者输入前一个棘手的值是没有用的,因为数据库引擎将100%透明地处理该值,而不允许其中包含任何控制字符。请参阅sql注入攻击的示例:让我们假设以下伪代码:
myfunction(myuser)
{
sql="SELECT user, password FROM users WHERE user='"+myuser+"'"
return db.execute(sql)
}
攻击者可通过此调用利用此漏洞获取表的所有密码:
myfunction("x' OR true OR 'a'='")
相反,如果程序员通过绑定变量执行查询:
myfunction(myuser)
{
sql="SELECT user, password FROM users WHERE user=?"
sql.setParam(1, myUser)
return db.execute(sql)
}
在这种情况下,攻击者输入任何与前一个值相同的棘手值都是无用的,因为数据库引擎将以100%透明的方式处理该值,而不允许其中包含任何控制字符。SQL注入的工作原理是在RDBMS解析SQL语法之前修改SQL查询 查询参数在SQL已被解析后发送到服务器,因此恶意值影响SQL语法解析为时已晚
查询参数只能解释为标量值,如字符串。SQL注入通过在RDBMS解析SQL语法之前修改SQL查询来工作 查询参数在SQL已被解析后发送到服务器,因此恶意值影响SQL语法解析为时已晚 查询参数只能解释为标量值,如字符串。,因为仅仅在字段中输入“drop database”是不够的。您必须添加一些其他字符来说服SQL解释器终止上一条语句并启动一条新语句(以执行DROP)。除其他外,参数化将阻止SQL以预期的方式成功注入和解释此类序列。例如,
“
等可能关闭字符串的字符将被转义,以便它们被视为变量的一部分,而不是SQL的一部分
具体来说,包含一个工作示例。在本例中,有一些PHP代码用于将行插入表中:
$sql = "INSERT INTO Students (Name) VALUES ('" . $studentName . "');";
execute_sql($sql);
如果$studentName
设置为“John”之类的正常值,则代码生成的最终SQL字符串是良性的:
INSERT INTO Students (Name) VALUES ('John');
同样,与您的示例类似,如果将$studentName
设置为“DROP TABLE Students”,它仍然没有任何效果。最后一个SQL是:
INSERT INTO Students (Name) VALUES ('DROP TABLE Students');
没有造成伤害
但是…如果将$studentName
设置为更微妙的值,例如:
Robert'); DROP TABLE Students;--
INSERT INTO Students (Name) VALUES ('Robert'); DROP TABLE Students;--');
最后一个字符串如下所示:
Robert'); DROP TABLE Students;--
INSERT INTO Students (Name) VALUES ('Robert'); DROP TABLE Students;--');
然后将其传递给SQL引擎,SQL引擎将其解释为两条语句(顺便说一句,末尾有一条注释),并执行这两条语句,结果令人不快
但是,如果$studentName
中的值作为参数传递,而不是仅仅连接到标准字符串,那么最终的查询将以
INSERT INTO Students (Name) VALUES ('Robert\'); DROP TABLE Students;--');
注意中间的逃逸<代码> <代码>,因此现在它被认为是字符串的一部分。它不再导致字符串在“t”之后停止
因此,在表中的Name
字段中输入的内容将是
Robert'); DROP TABLE Students;--
DROP TABLE语句不会被执行,因为SQL解释器从未看到它——它只是将其作为要添加到表中的值的一部分来处理
参数化意味着参数值内的任何内容都只被视为字符串(或者可能是数字)——它永远不能在字符串外转义,并被视为SQL语句本身的一部分
进一步阅读:
可能会帮助你更好地理解 因为仅仅在字段中输入“drop database”是不够的。您必须添加一些其他字符来说服SQL解释器终止上一条语句并启动一条新语句(以执行DROP)。除其他外,参数化将阻止SQL以预期的方式成功注入和解释此类序列。例如,“
等可能关闭字符串的字符将被转义,以便它们被视为变量的一部分,而不是SQL的一部分
具体来说,包含一个工作示例。在本例中,有一些PHP代码用于将行插入表中:
$sql = "INSERT INTO Students (Name) VALUES ('" . $studentName . "');";
execute_sql($sql);
如果$studentName
设置为“John”之类的正常值,则代码生成的最终SQL字符串是良性的:
INSERT INTO Students (Name) VALUES ('John');
同样,与您的示例类似,如果将$studentName
设置为“DROP TABLE Students”,它仍然没有任何效果。最后一个SQL是:
INSERT INTO Students (Name) VALUES ('DROP TABLE Students');
没有造成伤害
但是…如果将$studentName
设置为更微妙的值,例如:
Robert'); DROP TABLE Students;--
INSERT INTO Students (Name) VALUES ('Robert'); DROP TABLE Students;--');
最后一个字符串如下所示:
Robert'); DROP TABLE Students;--
INSERT INTO Students (Name) VALUES ('Robert'); DROP TABLE Students;--');
然后将其传递给SQL引擎,SQL引擎将其解释为两条语句(顺便说一句,末尾有一条注释),并执行这两条语句,结果令人不快
但是,如果$studentName
中的值作为参数传递,而不是仅仅连接到标准字符串,那么最终的查询将以
INSERT INTO Students (Name) VALUES ('Robert\'); DROP TABLE Students;--');
注意中间的逃逸<代码> <代码>,因此现在它被认为是字符串的一部分。它不再导致字符串在“t”之后停止
因此,什么被输入到