一次性密码安全风险

时间:2011-10-10 19:45:22

标签: java security web

我们正在开发一个Web应用程序,用户必须输入一次性密码(我们通过电子邮件发送给用户)才能完成操作。但是,如果恶意用户开发机器人并猜测我们生成一次性密码的模式,他可以输入一些随机电子邮件ID,甚至不查看他可以确认交易的电子邮件。这样他就可以用错误的确认来攻击系统。有人可以告诉我们人们如何处理这个问题吗?

由于

8 个答案:

答案 0 :(得分:4)

只使用没有模式的随机密码。优点是,如果密码可以在邮件中点击,则可以使密码更长,因为用户不必输入密码。

答案 1 :(得分:3)

如果您的随机一次性密码与常规密码具有相同的熵,则应该与其他任何密码解决方案一样好。

这是一个示例密码生成代码段,应该是相当不可预测的:

import java.security.SecureRandom;
import java.util.Random;

class Test {

    public static String generatePassword() {
        String chars = "abcdefghijklmnopqrstuvwxyz"
                     + "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
                     + "0123456789!@%$%&^?|~'\"#+="
                     + "\\*/.,:;[]()-_<>";

        final int PW_LENGTH = 20;
        Random rnd = new SecureRandom();
        StringBuilder pass = new StringBuilder();
        for (int i = 0; i < PW_LENGTH; i++)
            pass.append(chars.charAt(rnd.nextInt(chars.length())));
        return pass.toString();
    }

    public static void main(String[] args) {
        System.out.println(generatePassword());
        System.out.println(generatePassword());
        System.out.println(generatePassword());
    }
}

<强>输出:

  

Qp';Md#93Dxh\0|%%Ny7
  oqvntn2).~W@%P'EM*AS
  WEo2sz2Sm~a'm=Ss&Lu[

答案 2 :(得分:3)

我猜你的问题描述中你生成的“一次性密码”实际上是某种形式的粗加密,你可以通过这种形式来反转这个过程,以便找出他们所指的帐户。

这是错误的方法,一次性密码需要是随机的,所以没有办法根据电子邮件地址计算密码。您需要将一次性密码(最好是哈希)与数据库中的帐户信息一起存储,然后使用它进行查找。

答案 3 :(得分:2)

使用高熵源生成密码 - 在unix try / dev / urandom中 - 这将有效地为您提供一次性密码。

答案 4 :(得分:2)

不要这样做。向其发送 URL链接,其中包含一个巨大的密码(安全票证)作为URL参数,并安排您的结束,以便如果该参数存在且正确(i)他们已登录并且(ii) )UUID的有效性在发送后立即或在一两天内停止。根据您的容器可能需要做一些事情,但它更安全。我为此使用java.util.UUID,很好很长。

答案 5 :(得分:1)

你是对的,你在计划中有一个很大的安全漏洞,但你发现了错误的漏洞!

您的问题是您通过电子邮件发送 - 电子邮件不安全。

至于猜测问题,只要你使用足够长的密码,这个问题在统计上是不可能的。你可能想在他们猜错了100次之后锁定他们。

我见过的一个技巧是向用户询问Paypal或银行帐号。然后,您可以随机存入一些存款。所以他们看到34,91和82美分的存款。然后他们使用这些数字作为密码!很聪明吧?

答案 6 :(得分:0)

实施一次性密码,这在计算上无法猜测。

例如,使用随机字符串生成器生成长度为15个字符的字符串,使用大写字母,小写字母和数字池。

这导致了62 ^ 15种可能的组合,这对于暴力破解计划来说是非常困难的。

答案 7 :(得分:0)

只要在首次使用后使OTP无效,将6位随机数作为OTP就不会有安全风险。在一次尝试中猜测一个6位数字几乎是不可能的。既然你只尝试一次,那么蛮力也不值得担心。只需确保生成一个真正随机的数字,例如使用SecureRandom。

所以,采取步骤:

  1. 列表项
  2. 生成6位随机数OTP
  3. 将其与帐户相关联(例如,用户输入电子邮件和OTP)
  4. 在给定用户电子邮件的每次auth尝试时,使OTP无效,登录是否成功
  5. 使用Java,您可以使用以下方法生成OTP:

    public static final String getOTP(int length) {
    
        Random r = new SecureRandom();
        return String.valueOf(r.nextInt((int)Math.pow(10, length)));
    }
    

    希望这是有道理的。