问题描述
|
我是PHP / sql的新手(第一天),所以如果我以向后的方式进行操作,请原谅我。
下面的这个PHP旨在将100个最新条目返回到数据库中。我尝试通过选择要返回的100个条目并按创建该条目的日期(时间戳)进行排序。这会将最近的100个条目返回给数据库吗?还是我理解错了?
$type = isset($_GET[\'type\']) ? $_GET[\'type\'] : \"global\";
$offset = isset($_GET[\'offset\']) ? $_GET[\'offset\'] : \"0\";
$count = isset($_GET[\'count\']) ? $_GET[\'count\'] : \"100\";
$sort = isset($_GET[\'sort\']) ? $_GET[\'sort\'] : \"date DESC\";
// Localize the GET variables
$udid = isset($_GET[\'udid\']) ? $_GET[\'udid\'] : \"\";
$name = isset($_GET[\'name\']) ? $_GET[\'name\'] : \"\";
// Protect against sql injections
$type = MysqL_real_escape_string($type);
$offset = MysqL_real_escape_string($offset);
$count = MysqL_real_escape_string($count);
$sort = MysqL_real_escape_string($sort);
$udid = MysqL_real_escape_string($udid);
$name = MysqL_real_escape_string($name);
// Build the sql query
$sql = \"SELECT * FROM $table WHERE \";
switch($type) {
case \"global\":
$sql .= \"1 \";
break;
case \"device\":
$sql .= \"udid = \'$udid\' \";
break;
case \"name\":
$sql .= \"name = \'$name\' \";
break;
}
$sql .= \"ORDER BY $sort \";
$sql .= \"LIMIT $offset,$count \";
$result = MysqL_query($sql,$conn);
if(!$result) {
die(\"Error retrieving scores \" . MysqL_error());
}
//echo $result;
$rows = array();
while($row = MysqL_fetch_assoc($result)) {
$rows[] = $row;
}
解决方法
尽管ѭ1是MySQL关键字,这应该可以工作,因此您需要将ѭ1括在反引号中或重命名该列。
另外,在建立查询之前,请务必确保已清除这些输入。在没有卫生的情况下,根据
$_GET
或$_POST
的用户可编辑值构建查询是非常不安全的。
对于WHERE
参数,您应该在那些参数上运行mysql_real_escape_string()
(我看到的是,我不确定您之前是否有过)。这样就足够了,因为您要将这些值包装在查询中的引号中,并且由于要转义该字符串,因此任何企图突破那些引号的尝试都将无效。
对于诸如“ 7”之类的东西,我将定义一个有效的允许值“列表”,并检查以确保您的参数在该列表中。例如:
$valid_orderbys = array(\'`date` DESC\',\'`date` ASC\',\'`name` DESC\',\'`name` ASC\');
if (in_array($_GET[\'sort\'],$valid_orderbys))
{
// you\'re good,you can use this value
}
else
{
// unexpected value,either alert the user or
// use a default value you define
}
或者对于LIMIT
,您可以使用PHP的内置is_numeric()
来验证所提供的值是数字,而不是精心制作的字符串。
仅跳过$table
,ORDER BY
和LIMIT
参数是不够的,因为它们没有用引号引起来,因此有人可以恶意注入in14ѭ值。最终使您的查询类似:
SELECT * FROM ; DROP TABLE whatever; --WHERE ...
查询由分号分隔,因此这里有三个查询。第一个失败是因为它无效,第二个成功删除了表,第三个只是注释,因此什么也没有发生。但是您可以看到,如果让用户抛出他们想要的任何内容作为这些参数之一,那将是一个巨大的安全漏洞。 (我不确定将表名括在反引号中是否有帮助,有人知道了吗?请在任何情况下都可以对attack9ѭ和ORDER BY
参数进行相同的攻击。)
,如果每个记录都有一个唯一的自动递增ID(如您所愿),则,18 to会更有效。
,实际上,您已经对了。您只应查看指定的列,而不要使用*。