我应该 mysql_real_escape_string 我从用户那里获得的所有 cookie 以避免 php 中的 mysql 注入吗?

StackOverflow https://stackoverflow.com/questions/90517

  •  01-07-2019
  •  | 
  •  

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

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

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

有帮助吗?

解决方案

你什么 真的 首先需要做的就是不要发送这些可破解的 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 值,那么做您想做的事情的最佳方法是使用 带有绑定参数的准备好的语句.

其他提示

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

但是,您应该 使用参数化查询(通过 mysqli 或 PDO)来保护自己免受 SQL 注入。否则你可能会面临这样的结局 小鲍比·泰布尔斯的学校.

我只在将变量插入 SQL 语句之前使用 mysql_real_escape_string 。如果你的一些变量是 已经 逃脱了,然后你又逃脱了他们。这是您在新手博客 Web 应用程序中看到的一个经典错误:

当有人写撇号时,它会不断添加斜杠,从而破坏博客的页面。

变量的值本身并不危险:只有当你把它放入绳子或类似的东西中时,你才会开始误入危险的水域。

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

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

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() );

这将只允许正确的数据和预设数量的变量进入数据库。

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

你应该 mysql_real_escape_string 任何事物 这可能有潜在的危害。永远不要相信用户可以更改的任何类型的输入。

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

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

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 中),以便后续页面加载将哈希值发送回服务器,以便与您选择的会话存储中保存的哈希值进行比较。

mysql_real_escape_string 已经过时了......如今,您确实应该使用参数绑定。

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

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

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top