PHP+MySQL登录认证

不管是从实用性还是从安全性出发,使用MySQL保存网站用户信息,在登录时获取并进行匹配。若信息存在且正确,为用户分配cookie或session,完成认证,若信息不存在或有误,则认证失败。这是最简单的思维,但实现的方法多种多样,我先肤浅地探讨一二。

最简单直接

分析:这种方法根据查询数据库中的用户名与密码,若二者匹配(唯一),则认为信息正确,即认证成功。但这种方法弊端非常明显,在无安全过滤的情况下,WHERE处存在两个注入点,恶意提交username=admin'or1=1#password=abc'or1=1#等万能密码可以操控SQL语句,实现任意用户登录。

SELECT * FROM users WHERE username = 'admin'or1=1#' and password = 'xxx';  
# 在username处已经把后面的密码认证给注释掉了,且整条语句返回真,从而认证成功。  

修复加固一

造成SQL注入的核心成因是程序把用户输入的字符串当成代码来执行,使得SQL语句改变了结构,与开发者的预期产生出入。所以一大重要方法是把用户输入的数据绑定为字符串,可以使用PDO处理,也可以使用PHP的addslashes()处理输入数据,该函数会自动转义特殊符号,如单引号,可以防止传入数据中的单引号拼接在SQL语句中执行时引起各种错误及恶意利用。

分析:上述加固方法能很好地防止大部分注入攻击,但在数据库设置字符有转换时仍会有编码转换漏洞,如从utf8转向gbk时,传入%df%27,程序先对%27进行转义,但在后续转码过程中,反斜杠将与%df组合形成一个字符从而使单引号逃脱,需要额外注意。

修复加固二

进行身份认证时凭借一条SQL语句返回TrueFalse来判断登录成功与否并不可靠,即使对传入的参数处理的足够恰当,但这并不是一种安全的方法。
可以把认证过程分为几个步骤,同时通过将密码进行哈希单向加密,添加salt防止彩虹表爆破等方式保护用户信息安全。先附上简单的示例:

分析:把传入的usernamepassword分成两部分进行认证,先查询username是否存在,返回的数据有空或一条。然后提取返回数据中的password与传入的password进行比较,若完全相符则通过认证,不相符或username不存在则无法通过认证。
该方法可以控制只有当传入正确的用户名与密码才能成功认证,用户名处即使使用万能密码也毫无意义,而密码处即使使用万能密码也不会带入数据库进行处理。

修复加固三

很多开发者现在已没必要重复造轮子了,使用最新版的thinkphp,lavarel等框架进行开发,内置的数据库语句处理已做的非常安全。或使用PDO预处理,绑定参数会自动处理数据中的单引号,防止数据恶意执行。

登录认证后的注入

这种攻击首先是通过注册恶意用户名(名称含有单引号及SQL语句),在正常登录后被暂存于session等地方,然后在其它地方调用时直接使用,导致执行其中恶意代码。

二次注入漏洞分析

发表评论

电子邮件地址不会被公开。 必填项已用*标注