关于验证的基础

时间:2013-01-11 19:02:00

标签: php database security web-applications authorization

在Web应用程序中,当然在很多情况下我们将支持CRUD(创建,检索,更新,删除)

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

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

问题是,这个基本问题是否有任何好的或更好的解决方案?

由于

3 个答案:

答案 0 :(得分:4)

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

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

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

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

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

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

  3. 任何不是GET的操作,都使用HTTP POST来执行。换句话说,你不应该把id放在查询字符串中,而应该放在post数据中。

答案 1 :(得分:2)

假设您在使用会话时在会话中注册了userid: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

}

更改'table'(数据库中的哪个表包含此信息),'userid'(该表中的用户ID列名)和'room'(该表中的room id列名)

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

答案 2 :(得分:2)

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

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

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