我想知道此sql查询是否已从sql-injection保护起来,是否还可以,或者我应该修改某些内容。
我试图绑定GET中的ID,如果一切正常,我将使用具有该ID的实际查询。
if(isset($_GET['id']) && $_GET['id'] != null) {
$id = $_GET['id'];
$stmt = $mysqli->prepare('SELECT id FROM maps WHERE id = ?');
$stmt->bind_param('i', $id);
$stmt->execute();
$result = $stmt->get_result();
if (mysqli_num_rows($result) == 1) {
$row = $result->fetch_assoc();
$secid = $row["id"];
} else {
header("LOCATION: index.php");
}
$sql = "SELECT
maps.id,
maps.name,
maps.description,
maps.date,
maps.mcversion,
maps.mapid,
maps.category,
maps.format,
maps.userid,
users.username,
users.rank,
users.verified,
users.mc_username,
(SELECT COUNT(*) FROM likes WHERE likes.mapid = maps.id) AS likes,
(SELECT COUNT(*) FROM downloads WHERE downloads.mapid = maps.id) AS downloads,
(SELECT COUNT(*) FROM subscribe WHERE subscribe.channelid = maps.userid) AS subscribes,
(SELECT COUNT(*) FROM views WHERE views.mapid = maps.id) AS views
FROM maps
INNER JOIN users
ON maps.userid = users.id
WHERE maps.id = '$secid'";
$result = mysqli_query($con,$sql);
if (mysqli_num_rows($result) > 0) {
$row = mysqli_fetch_assoc($result);
} else {
header("LOCATION: index.php");
}
} else {
header("LOCATION: index.php");
}
答案 0 :(得分:5)
一般经验法则:如果您的查询具有变量插值,例如与$secid
一样,则可能没有。
使用带占位符值的准备好的语句来确保您没有注入问题。您需要手动进行其他任何检查和验证。 仔细彻底。
由于$secid
来自数据库,所以不能保证它是什么。那可能是一个VARCHAR
列,或者如果不是现在,它可能会在将来。。这就是使SQL注入成为永久威胁的原因。今天有充分根据的假设可能会在以后证明是危险的。
在这种特殊情况下,没有理由不使用占位符值。第一个查询的用途可疑。第二个罐头应该并且应该使用完全相同的方法来显示?
而不是一个值。
作为强制自己编写安全代码的一种方式,在定义查询时仅使用单引号的字符串。这样,任何意外的SQL注入都将变得无害,相反,您将在数据库中显示文字$值,而不是用户数据,这些值在测试中非常容易发现。除非您要查找SQL注入错误,否则它们不会。
答案 1 :(得分:0)
这是更好的解决方案吧?
if(isset($_GET['id']) && $_GET['id'] != null) {
$id = $_GET['id'];
$stmt = $mysqli->prepare("SELECT
maps.id,
maps.name,
maps.description,
maps.date,
maps.mcversion,
maps.mapid,
maps.category,
maps.format,
maps.userid,
users.username,
users.rank,
users.verified,
users.mc_username,
(SELECT COUNT(*) FROM likes WHERE likes.mapid = maps.id) AS likes,
(SELECT COUNT(*) FROM downloads WHERE downloads.mapid = maps.id) AS downloads,
(SELECT COUNT(*) FROM subscribe WHERE subscribe.channelid = maps.userid) AS subscribes,
(SELECT COUNT(*) FROM views WHERE views.mapid = maps.id) AS views
FROM maps
INNER JOIN users
ON maps.userid = users.id
WHERE maps.id = ?");
$stmt->bind_param('i', $id);
$stmt->execute();
$result = $stmt->get_result();
if (mysqli_num_rows($result) == 1) {
$row = $result->fetch_assoc();
} else {
header("LOCATION: index.php");
die();
}
} else {
header("LOCATION: index.php");
die();
}