Javascript 使用JS执行MySQL查询及其涉及的安全问题
我一直在互联网上寻找一种用JavaScript定义查询的方法,将该查询传递给PHP。让PHP建立一个MySQL连接,执行查询并返回json编码的结果 然而,我担心的是这个方法的安全性,因为用户可能会篡改查询,做你不想让他们做的事情,或者请求你不想让他们看到的数据 问题: 在这样的应用程序/插件中,您建议采取什么样的安全措施来防止用户请求我不希望他们请求的信息 编辑 我的插件的最终结果是Javascript 使用JS执行MySQL查询及其涉及的安全问题,javascript,php,mysql,security,Javascript,Php,Mysql,Security,我一直在互联网上寻找一种用JavaScript定义查询的方法,将该查询传递给PHP。让PHP建立一个MySQL连接,执行查询并返回json编码的结果 然而,我担心的是这个方法的安全性,因为用户可能会篡改查询,做你不想让他们做的事情,或者请求你不想让他们看到的数据 问题: 在这样的应用程序/插件中,您建议采取什么样的安全措施来防止用户请求我不希望他们请求的信息 编辑 我的插件的最终结果是 var data = Querier({ table: "mytable", columns:
var data = Querier({
table: "mytable",
columns: {"column1", "column2", "column3"},
where: "column2='blablabla'",
limit: "10"
});
我将让该函数发出一个AJAX请求,并使用上述数据在PHP中执行一个查询。我想知道这会带来什么安全风险,以及如何预防这些风险。您的问题不清楚您是否允许用户键入将针对您的数据库运行的查询,或者您在浏览器中运行的代码是否正在这样做(例如,不是用户) 如果是用户:你必须真正信任他们,因为他们可以(也可能会)破坏你的数据库 如果是您在浏览器中运行的代码在创建它们:不要这样做。相反,让客户端代码将数据发送到服务器,并在服务器上使用完全预防措施制定查询,以防止SQL注入(参数化查询等)
重新更新: 我至少可以看到几个问题:
where: "column2='blablabla'"
现在,假设我决定在它被发送到服务器并更改为:
where: "column2=');DROP TABLE Stuff; --"
http://xkcd.com/327/“>
您无法向服务器发送完整的WHERE
子句,因为您不能信任它。这就是参数化查询的要点:
相反,请按名称指定列,并在PHP端确保正确处理参数值()
现在,您可以在不盲目信任客户端文本的情况下构建查询;您需要对列名、运算符等进行彻底验证取决于你打算怎么做,你可能会有一个比这个经济体中的洞更大的洞,或者根本没有洞 如果要在客户端编写查询并发送到php,我将创建一个用户,该用户只有
select
、insert
、delete
和update
,没有访问任何其他数据库的权限。如果使用SQlite,请忽略此选项。
我劝你不要这样 如果您在服务器端构建查询,只需将所需数据塞入服务器即可 我会将代码更改为如下内容:
var link = QuerierLink('sql.php');//filename to use for the query
var data = Querier('users',link);//locks access to only this table
data.select({
columns: ['id','name','email'],
where: [
{id:{'>':5}},
{name:{'like':'%david%'}}
],
limit:10
});
在服务器端,它将生成查询:
select `id`,`name`,`email` from `db.users` where `id`>5 and `name` like '%david%' limit 10
这将是更好的使用
对于准备好的报表,您可以使用:
select `id`,`name`,`email` from `db.users` where `id`>:id and `name` like :name limit 10
传递给PDO,伪代码:
$query='select `id`,`name`,`email` from `'.$database_name.'.users` where `id`>:id and `name` like :name limit 10';
$result=$PDO->exec($query,array(
'id'=>5,
'name'=>'%david%'
)
);
这是首选的方式,因为您可以更好地控制传递的内容
此外,请沿表的名称设置确切的数据库名称,以避免用户访问其他表/数据库中的内容。其他数据库包括
information\u schema
,其中包含整个数据库中的每一条信息,包括用户列表和限制。对于SQlite,忽略这一点
如果要使用MySQL/MariaDB/other,则应禁用所有读/写权限
您真的不希望任何人将文件写入您的服务器!特别是写入他们希望的任何位置。
风险:他们有一只新的小狗供攻击者随心所欲!这是一个巨大的洞。
解决方案:使用或系统变量,使用
.htaccess
禁用或限制对阻止外部访问的目录的访问
如果使用SQlite,只需根据模板文件为每个连接的客户端创建一个.SQlite(3)
文件。然后在用户关闭连接时删除该文件,或者对于超过x时间的文件,每n分钟删除一次。风险:用
.sqlite
文件填充磁盘。解决方案:尽早清除文件或使用带有
cron
作业的ramdisk
很久以前,我就想实现这样的想法,这是一个锻炼头脑的好方法。
也许我会像这样实现它!更重要的是要小心您为MySQL用户授予此类操作的权限。 例如,您不希望他们删除数据库,也不希望他们执行这样的请求:
LOAD DATA LOCAL INFILE '/etc/passwd' INTO TABLE test FIELDS TERMINATED BY '\n';
您必须限制此MySQL用户启用的操作,以及他访问的表
访问总数据库:
grant select on database_name.*
to 'user_name'@'localhost' identified by 'password';
访问表:
grant select on database_name.table_name
to 'user_name'@'localhost' identified by 'password';
然后…还有什么…这应该避免不必要的SQL注入,以更新/修改表或访问其他表/数据库,至少,只要您向该用户授予的唯一权限是“选择特定表/数据库”
但这并不能避免用户启动一个愚蠢的性能要求,这可能需要您所有的CPU
var data = Querier({
table: "mytable, mytable9, mytable11, mytable12",
columns: {"mytable.column1", "count(distinct mytable11.column2)",
"SUM(mytable9.column3)"},
where: "column8 IN(SELECT column7 FROM mytable2
WHERE column4 IN(SELECT column5 FROM mytable3)) ",
limit: "500000"
});
如果您不希望MySQL服务器可能出现故障,您必须对传递的数据进行一些检查
引入简单的JavaScript数据访问
因此,您希望快速原型化一个非常酷的Web2.0JavaScript应用程序,但不想花费所有时间编写连接代码来访问数据库?传统上,要从数据库到前端获取数据,您需要
var data = Querier({
table: "mytable, mytable9, mytable11, mytable12",
columns: {"mytable.column1", "count(distinct mytable11.column2)",
"SUM(mytable9.column3)"},
where: "column8 IN(SELECT column7 FROM mytable2
WHERE column4 IN(SELECT column5 FROM mytable3)) ",
limit: "500000"
});
// Sample functions to update authors
function updateAuthorsTable() {
dbw.getAll( function(data) {
$('#authors').html('<table id="authors"><tr><td>ID</td><td>Author</td></tr></table>');
$(data).each( function( ind, author ) {
$('#authors tr:last').after('<tr><td>'+author.id+'</td><td>'+author.name+'</td></tr>');
});
});
}
$(document).ready(function() {
dbw = new DbWrapper();
dbw.table = 'authors';
updateAuthorsTable();
$('#addbutton').click( function() {
dbw.insertObject( { name: $('#authorname').val() },
function(data) {
updateAuthorsTable();
});
});
});