【问题标题】:Basic about Verification验证基础
【发布时间】:2012-12-26 10:25:41
【问题描述】:

在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。 如果这是唯一的解决方案,那么我必须修改我已经编写的所有查询。

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

谢谢

【问题讨论】:

  • @Art:$_POST 如何解决这个问题?基本问题是找到检查对象是否属于用户的最佳方法。这不仅是一个对象,而且将是可能的对象。比如房间、地址、衬衫等
  • 你有没有同时包含 user_id 和 room_id 的数据库?和@Art Planteur,用户也可以发布任何数据,只是在隐藏字段中
  • 我的评论是关于如果不良用户尝试修改 GET 可能会产生错误。 POST 可以解决这个问题。根据您上面的回答,您需要一个请求来检查 room_id 是否与 user_id 存在。你的数据库结构如何?
  • 赞成成为您和您的同事中唯一关心安全的人。

标签: php database security web-applications authorization


【解决方案1】:

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

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

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

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

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

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

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

【讨论】:

  • 太好了,谢谢你的推荐。但我认为加密和解密 id 会使应用程序变慢。
  • @Ahmad,应用程序不会因为几个加密而变慢,同时使用加密和检查数据库比只检查数据库更好
  • @Ahmad:解密/加密 id 所花费的处理时间微不足道,以至于您不会注意到它。
【解决方案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 只是数字不要改变它

【讨论】:

  • 您好,感谢您的回答和示例。从理论上和实践上,您的答案与我的答案相同。我在第一个问题中已经提到过,是在执行任何操作之前检查任何对象是否属于当前用户。来自这个,这意味着我要修改我的所有查询。在执行此示例中的任何操作之前添加检查,对吗?
  • 不客气,是的,您需要在我输入的位置添加您的操作 // 用户拥有此房间,并在 // FAIL 中添加警报以警告用户他不拥有此房间
  • 由于用户 ID 已经是查询条件的一部分,如果找到记录,$found == $_SESSION['userid'] 将始终为真。
【解决方案3】:

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

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-06-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-07-17
    • 1970-01-01
    • 1970-01-01
    • 2012-10-15
    相关资源
    最近更新 更多