2

当用户访问我的网站时,我的脚本会检查 2 个存储用户 ID + 部分密码的 cookie,以自动登录。

可以通过 cookie 编辑器编辑 cookie 的内容,所以我猜有可能在写入的 cookie 中添加一些恶意内容?

我应该在我的所有 cookie 调用中添加mysql_real_escape_string(或其他东西)还是有某种内置程序不允许这种情况发生?

4

9 回答 9

8

真正需要做的不是首先发送这些可破解的 cookie 值。相反,为什么不散列用户名和密码以及(秘密)盐并将其设置为 cookie 值?IE:

define('COOKIE_SALT', 'secretblahblahlkdsfklj');
$cookie_value = sha1($username.$password.COOKIE_SALT);

然后你知道 cookie 值总是一个 40 个字符的十六进制字符串,并且可以将用户发回的值与数据库中的任何内容进行比较,以确定它们是否有效:

if ($user_cookie_value == sha1($username_from_db.$password_drom_db.COOKIE_SALT)) {
  # valid
} else {
  #not valid
}

mysql_real_escape_string顺便说一句,对数据库产生了额外的影响(很多人没有意识到它需要数据库连接并查询 MySQL)。

如果您无法更改您的应用程序并坚持使用可破解的 cookie 值,那么最好的方法是使用带有绑定参数的准备好的语句

于 2008-09-18T06:57:18.393 回答
3

mysql_real_escape_string 的重点不是防止注入攻击,而是确保您的数据准确地存储在数据库中。因此,应该在任何进入数据库的字符串上调用它,无论其来源如何。

但是,您应该使用参数化查询(通过 mysqli 或 PDO)来保护自己免受 SQL 注入。否则你可能会像小鲍比桌的学校一样结束。

于 2008-09-18T07:03:56.193 回答
1

我只在将变量插入 SQL 语句之前使用 mysql_real_escape_string。如果您的某些变量已经被转义,那么您只会让自己感到困惑,然后您再次转义它们。这是您在新手的博客 webapps 中看到的经典错误:

当有人写一个撇号时,它会不断添加斜线,破坏博客\\\\\\\ 的页面。

变量的值本身并不危险:只有当您将其放入字符串或类似的东西时,您才会开始误入危险水域。

当然,永远不要相信来自客户端的任何东西。

于 2008-09-18T06:42:55.527 回答
1

准备好的语句和参数绑定总是一个好方法。

PEAR::MDB2 支持准备好的语句,例如:

$db = MDB2::factory( $dsn );

$types = array( 'integer', 'text' );
$sth = $db->prepare( "INSERT INTO table (ID,Text) (?,?)", $types );
if( PEAR::isError( $sth ) ) die( $sth->getMessage() );

$data = array( 5, 'some text' );
$result = $sth->execute( $data );
$sth->free();
if( PEAR::isError( $result ) ) die( $result->getMessage() );

这只会允许适当的数据和预设数量的变量进入数据库。

您当然应该在进行此之前验证数据,但准备语句是应该完成的最终验证。

于 2008-09-18T09:07:28.533 回答
0

你应该 mysql_real_escape_string任何可能有害的东西。永远不要相信用户可以更改的任何类型的输入。

于 2008-09-18T06:36:28.163 回答
0

我同意你的看法。可以修改 cookie 并发送恶意数据。

我认为在使用 cookie 之前过滤从 cookie 获得的值是一种很好的做法。根据经验,我会过滤任何其他可能被篡改的输入。

于 2008-09-18T06:38:19.843 回答
0

mysql_real_escape_string 太过时了......这些天你真的应该使用参数绑定。

我将通过提及我指的是准备好的语句来详细说明,并提供指向一篇文章的链接,该文章表明有时 mysl_real_escape_string 是不够的:http://www.webappsec.org/projects/articles/091007.txt

于 2008-09-18T06:43:13.967 回答
0

Yegor,您可以在创建/更新用户帐户时存储哈希值,然后在启动登录时,对发布到服务器的数据进行哈希处理,并与该用户名的数据库中存储的数据进行比较。

(在松散的 php 中我的头顶 - 视为伪代码):

$usernameFromPostDbsafe = LimitToAlphaNumUnderscore($usernameFromPost);
$result = Query("SELECT hash FROM userTable WHERE username='$usernameFromPostDbsafe' LIMIT 1;");
$hashFromDb = $result['hash'];
if( (sha1($usernameFromPost.$passwordFromPost.SALT)) == $hashFromDb ){
    //Auth Success
}else{
   //Auth Failure
}

成功验证后,您可以将哈希存储在 $_SESSION 或缓存的已验证用户名/哈希的数据库表中。然后将哈希发送回浏览器(例如在 cookie 中),以便后续页面加载将哈希发送回服务器,以便与您选择的会话存储中保存的哈希进行比较。

于 2008-09-18T07:25:12.430 回答
-1

我建议使用 htmlentities($input, ENT_QUOTES) 而不是 mysql_real_escape_string 因为这也可以防止任何意外输出实际的 HTML 代码。当然,你可以使用 mysql_real_escape_string 和 htmlentities,但你为什么要使用呢?

于 2008-09-18T06:49:48.163 回答