

PHP安全编码——书写安全的代码
4、验证码安全
2024-01-22
提问
问题1:应该如何正确使用图形验证码?
问题2:应该如何正确使用短信验证码?
问题3:应该如何正确使用邮件验证码?
课程单元
1. 一个图片验证码的例子
2. 错误一:验证码为空
3. 错误二:验证码太简单
4. 错误三:在客户端校验验证码
5. 错误四:验证码保存在cookie中
6. 错误五:没有及时销毁验证码
7. 错误六:验证码图片文件名漏洞
8. 错误七:验证码没有跟账户绑定
1. 一个图片验证码的例子
下面是一个简单的图片验证码:

下面是对应的html代码:

下面是图片验证码的简单php代码:

下面是检查验证码是否正确的简单php代码:

2. 错误一:验证码为空
验证码是在图片中生成并且存放进session中,因此,只要我们不请求图片,则session为空,如果我们直接使用浏览器访问提交页面,例如:xxx.php?code=,传入code为空,则满足了$_GET[“code”] == $_SESSION[“code”]的条件,成功跳过了验证码判断。
解决办法:必须判断$_SESSION[“code”]是否为空。

3. 错误二:验证码太简单

4位数随机码,对于找回密码等重要场合,太过于简单,用户很容易通过反复提交、暴力破解等方式进行破解。
解决办法:对于找回密码等重要场合,验证码必须足够长、足够复杂,如果采用md5方式生成验证码,则原始字符串应该是字母加数字加特殊符号,10位以上的长度,才能确保相对安全。
4. 错误三:客户端校验验证码
类似如下在客户端判断验证码的方式,非常容易被表单提交欺骗攻击的方式跳过验证码校验步骤,而直接提交服务器,因此,验证码校验步骤必须在服务器端进行。

5. 错误四:cookie保存验证码
对于邮件验证码等需要长期保存的验证码,采用如下的方式将验证码保存在cookie中,方便再次读取,是错误的,原因是,客户端cookie非常容易被用户读取到,会导致验证码泄漏,从而失去验证的效果。
解决方法:对于需要长期保存的验证码,必须保存在服务器端,可以保存在数据库中,而不能保存在客户端cookie中。

6. 错误五:未及时销毁验证码
对于下面的判断程序,当验证码不正确时,没有及时销毁验证码,$_SESSION[“code”]中的值会一直保持不变,导致用户可以通过反复提交的方式,试出来验证码是多少。比如对于4位数验证码,用户可以使用循环,从0000到9999逐个测试,很快就能测试出来验证码是多少。
解决方法:验证码校验错误时,必须及时销毁验证码,用户必须重新获取验证码,增加用户循环测试的难度。

7. 错误六:验证码文件名泄漏
例如,对于下面这种图形验证码,很容易通过查看源代码的方式,发现验证码是多少。

解决方法:验证码图片文件名不能是有实际含义的文件名,必须是用户无法理解含义的文件名,比如code.php这种没有特别含义的文件名。

8. 错误七:验证码未绑定账户
例如,找回密码验证码,验证码校验成功后,用户可以修改密码。类似下面的代码,用户可以传递任意的userId,导致可以修改任意用户密码。

解决办法:对于修改密码等与账户相关的操作,userId等关键参数,必须与验证码相关联,而不能是用户随意输入的参数。关联方式可以用数据库、session等关联,但不能是cookie,原因同错误四,用户很容易获得和修改cookie的值,构建虚假的关联关系,从而导致关联无效。


关注我们,获取更多资讯