zoukankan      html  css  js  c++  java
  • 你的登录接口真的安全吗?


     

    前言

    当您学习编写程序时,第一行代码是hello world。但是,当您开始学习WEB后台技术时,许多人的第一个功能是编写登录名(轻声:我不认识其他人,我还是这样)。

    但是,当我采访许多工作经验短的学生或与之交流时,我发现许多学生在简历上写了:负责项目登录/注册功能模块的开发和设计,但是他们都很简单。实现了功能逻辑,并且在安全性方面考虑不太多。本文主要是与您聊天。设计登录界面时,它不仅是功能上的实现,而且还是我们需要考虑的安全性。

    安全风险

    暴力破解!

    只要该网站在公共网络上公开,就很有可能成为目标网站。尝试使用这种简单有效的方法:

    以多种方式获得网站的用户名后,编写一个程序遍历所有可能的密码,直到找到正确的密码为止

    伪代码如下:

    # 密码字典

    password\_dict = []

    # 登录接口

    login\_url = ''

    def attack(username):

    for password in password\_dict:

    data = {'username': username, 'password': password}

    content = requests.post(login\_url, data).content.decode('utf-8')

    if 'login success' in content:

    print('got it! password is : %s' % password)

    那么我们如何预防这种情况呢?

    验证码

    我是聪明的学生想到的,当密码输入错误一定次数后,我可以添加验证码验证!例如,我们设置为当用户的密码错误3次时,要求用户输入图像验证码以继续登录操作:

    伪代码如下:

    fail\_count = get\_from\_redis(fail\_username)

    if fail\_count >= 3:

    if captcha is None:

    return error('需要验证码')

    check\_captcha(captcha)

    success = do\_login(username, password)

    if not success:

    set\_redis(fail\_username, fail\_count + 1)

    伪代码不考虑并发性,实际开发中可以考虑锁定。

    这确实可以过滤掉一些非法攻击,但是使用当前的OCR技术,普通的图像验证码确实很难有效地阻止机器人(我们为此遭受了很多苦难)。搜索公共垂直编号:rHub,[]获得前端和后端的入门教程!当然,我们也可以花钱购买类似于第三方公司提供的滑动验证的验证方案,但是它不是100%安全的并且会被破解(痛苦的一课)。

    登录限制

    当时,有些学生说我可以直接限制异常用户的登录操作。当密码输入错误一定次数后,将直接拒绝用户的登录。稍后恢复。例如,当我们将一个帐户设置为以10个错误登录时,该帐户的所有登录操作将在5分钟内被拒绝。

    伪代码如下:

    fail\_count = get\_from\_redis(fail\_username)

    locked = get\_from\_redis(lock\_username)

    if locked:

    return error('拒绝登录')

    if fail\_count >= 3:

    if captcha is None:

    return error('需要验证码')

    check\_captcha(captcha)

    success = do\_login(username, password)

    if not success:

    set\_redis(fail\_username, fail\_count + 1)

    if fail\_count + 1 >= 10:

    # 失败超过10次,设置锁定标记

    set\_redis(lock\_username, true, 300s)

    嗯,这确实可以解决用户密码被爆破的问题。但是,这将带来另一个风险:尽管攻击者无法获取该网站的用户信息,但它可能阻止我们网站的所有用户登录!

    攻击者只需要遍历所有用户名(即使没有用户名,也可以是随机的)来登录,那么这些用户将始终被锁定,从而导致普通用户无法登录该网站!

    IP限制

    然后,由于不可能直接定位用户名,因此我们可以处理IP。如果直接阻止了攻击者的IP,一切都会好起来的。我们可以设置为,当某个IP下调用登录界面的错误次数达到一定数量时,将禁止该IP的登录操作。

    伪代码如下:

    ip = request['IP']

    fail\_count = get\_from\_redis(fail\_ip)

    if fail\_count > 10:

    return error('拒绝登录')

    # 其它逻辑

    # do something()

    success = do\_login(username, password)

    if not success:

    set\_redis(fail\_ip, true, 300s)

    这也可以在一定程度上解决问题。实际上,许多电流限制操作都是在IP上执行的。例如,niginx的限流模块可以在一个单位时间内限制IP的访问次数。

    但是这里仍然存在问题:

    例如,许多学校和公司现在使用相同的出口IP。如果直接通过IP限制它,则可能会意外杀死其他普通用户。

    拥有如此多的VPN,攻击者是完全可以的。您可以在IP被阻止进行攻击之后切换VPN

    移动验证

    没有更好的方法来阻止它?当然有。我们可以看到,近年来,几乎所有应用程序都允许用户绑定他们的手机。一是国家实名政策要求,二是手机与身份证基本相同,并且基本上可以代表一个人的身份。如此多的安全操作都基于手机验证,因此也可以登录。

    1. 当用户输入密码超过3次时,要求用户输入验证码(最好使用滑动验证)。
    2. 如果用户输入密码超过10次,则弹出手机验证,要求输入 用户使用手机验证码和密码双重认证
    手机验证码防刷卡是另一个问题。我不会从这里开始。我将在有时间的时候谈论我们将来要做的事情。

    伪代码如下:

    fail\_count = get\_from\_redis(fail\_username)

    if fail\_count > 3:

    if captcha is None:

    return error('需要验证码')

    check\_captcha(captcha)

    if fail\_count > 10:

    # 大于10次,使用验证码和密码登录

    if dynamic\_code is None:

    return error('请输入手机验证码')

    if not validate\_dynamic\_code(username, dynamic\_code):

    delete\_dynamic\_code(username)

    return error('手机验证码错误')

    success = do\_login(username, password, dynamic\_code)

    if not success:

    set\_redis(fail\_username, fail\_count + 1)

    我们结合了上述方法,并增加了手机验证码的验证方式,基本上可以防止相当数量的恶意攻击者。但是没有一个系统绝对安全,我们只能尽可能增加攻击者的成本。您可以根据网站的实际情况选择适当的策略。

    中间人攻击吗?

    什么是中间人攻击

    ***中间人攻击(缩写为MITM)***,简单来说,A和B处于通信过程中, 攻击者通过嗅探和拦截来获取或修改A和B的通信内容。

    举个栗子:小白派快递员去小黄,途中经过快递点A,小黑躲在快递点A上,或者干脆打开快递点B装成快递点A。然后秘密地打开快递站。小白快递员给小黄看里面的东西。您甚至可以离开小白的快递员,打包一角钱的盒子,然后寄给小黄。

    在登录过程中,如果攻击者嗅探从客户端发送到服务器的登录请求,则可以轻松获得用户的用户名和密码。

    HTTPS

    防止中间人攻击的最简单,最有效的操作是替换HTTPS并修改网站中的所有HTTP请求以强制使用HTTPS。

    ***为什么HTTPS可以阻止中间人攻击? ***

    HTTPS实际上在HTTP和TCP协议之间添加了SSL / TLS协议,以确保数据的安全传输。与HTTP相比,HTTPS具有以下特征:

    内容加密

    数据完整性

    身份验证

    具体的 HTTPS 原理这里就不再扩展了,大家可以自行 Google

    加密传输

    除了HTTPS,我们还可以手动加密和传输敏感数据:

    可以在客户端对用户名进行加密,并在服务器端进行解密

    可以在客户端将密码设置为MD5传输 防止暴露密码的纯文本

    其他

    除了上面我们讨论的那些以外,实际上还可以考虑许多其他任务,例如:

    操作日志,每个用户的登录名和敏感信息 需要记录操作日志(包括IP,设备等)

    异常操作或登录提醒。使用以上操作日志,我们可以根据该日志进行风险提示。例如,当用户登录,更改密码或异常登录时,可以通过短信

    提醒用户。拒绝弱密码注册或更改密码时,不允许用户设置弱密码

    防止遍历用户名。注册某些网站时,输入用户名后,将提示用户名是否存在。这样,存在网站所有用户名将被泄露(仅遍历界面)的风险,并且需要在交互或逻辑上加以限制

    ...

    后记

    现在 国家继续颁布各种法律,越来越重视用户数据。作为开发人员,我们还需要做更多的工作来保护用户数据和用户隐私。希望我能为您们提供一些帮助。

  • 相关阅读:
    Qt开发陷阱一QSTACKWIDGET
    【解决】安装compass失败(gem install compass)
    Qt使用MySQL笔记一
    win7双系统安装openSUSE13.2解决【引导加载器安装期间出错】问题
    【转载】Sublime Text 3065 Keygen and Patcher
    HTML4,HTML5,XHTML 之间有什么区别?
    【转】实例解说双缓冲
    【MFC】利用双缓冲和随机函数rand()实现蒲公英飞舞
    基本sql语句--入门语句
    Linux使用jstat命令查看jvm的GC情况
  • 原文地址:https://www.cnblogs.com/whiteshds/p/13636521.html
Copyright © 2011-2022 走看看