2

在 web 应用中,当然很多情况下我们会支持 CRUD(Create, Retriever, Update, Delete)

基本程序员会做类似下面的事情(没有验证):

delete?room_id=12
update?room_id=13

显示的 room_id 仅适用于属于用户/客户的房间。第一个身份验证仅使用用户名和密码。嗯,这是一个标准。

但我相信我们不应该相信用户。不良用户可能会猜到不属于他的 room_id。像delete?room_id=199

我问我的程序员朋友,他们甚至从来没有考虑过这个问题。

所以为了防止这种情况,我有一个基本的解决方案,总是为任何相关对象传递 user_id。在采取任何行动之前进行此类查询is the room_id belong to the user。如果这是唯一的解决方案,那么我必须修改我已经编写的所有查询。

问题是,对于这个基本问题有什么好的或更好的解决方案吗?

谢谢

4

3 回答 3

4

你的方法很好。你的程序员朋友没有考虑到这一点,我并不感到惊讶。不幸的是,安全似乎是大多数程序员最不关心的事情。

在一个好的系统中,您将对几乎所有执行的操作执行授权检查,以查看该特定用户是否被授权执行该操作。在整个应用程序中构建此签入通常是一种很好的做法,即使对于您通常不关心它们是否被授权的事情:有一天您可能会这样做。

在您的场景中,该操作可能是检索房间、更新房间甚至删除房间。

为了帮助解决问题,我有一些建议:

  1. 如果可能,使 room_id 不可猜测。假设您已经使用 int 作为主键,简单的方法是在客户端浏览器和应用程序之间传递时对其进行加密/解密。

  2. 确保在浏览器端,您没有传入用户 ID,而是从会话中或通过其他机制提取。关键是您不想相信用户将 id 传递给您。

  3. 任何不是 GET 的操作,都使用 HTTP POST 来执行。换句话说,您根本不应该将 id 放在查询字符串中,而应该将其作为发布数据。

于 2013-01-11T19:23:24.517 回答
2

假设您在他登录时已在会话中注册了用户 ID: session_register("userid");

然后你可以这样做来检查登录的用户是否拥有房间(正如你所说的,你有一个同时包含 roomid 和 userid 的数据库)

$connect = mysql_connect("$server", "$dbuser", "$dbpassword")
    OR die(mysql_error());

$room = intval($_GET['room_id']);
$user = mysql_real_escape_string($_SESSION['userid']);

mysql_select_db("$databasename", $connect);
$select = mysql_query("SELECT userid AS uid FROM table WHERE userid='$user' AND room='$room'");
$fetch = mysql_fetch_assoc($select); 
$found = $fetch['uid']; 

if ($found == $_SESSION['userid']){

// User owns this room let him delete

} else {

// FAIL, This user does not own this room

}

更改“表”(数据库中的哪个表包含此信息)、“用户 ID”(该表中的用户 ID 列名)和“房间”(该表中的房间 ID 列名)

编辑: 如果您的 room_ids 可能有任何字符,请删除 intval(); 从 $room 并为它做一个 real_escaping,如果 room_ids 只是数字不要改变它

于 2013-01-11T19:32:02.787 回答
2

永远不要相信你的客户传递给你的任何东西。每个请求都必须在服务器端进行验证,并检查是否允许登录的用户执行该操作。

每个文本输入都必须在插入或查看时进行清理。后者有更大的遗忘机会,从而为XSS提供了一个领域。我建议对模板使用隐式清理。

还要尽量避免将 GET 方法用于批评操作。攻击者总是可以强制用户访问 URL(iframe,向他发送缩短的链接)。您还应该在删除表单中添加特殊生成的令牌以防止CSRF 攻击

于 2013-01-11T20:23:01.053 回答