在电影中,白帽黑客编写了一种他称之为“变异安全算法”的程序。这启发了开发一种系统,当登录失败次数足够多以至于可能存在安全风险时,系统会自动变更(或变异)密码。这种登录系统与传统系统不同。传统的登录系统依赖于固定的用户名和密码组合来允许用户访问私人信息。许多人在注册社区网站或设置网上银行系统的登录信息时,并不经常使用足够强大的密码。
这些密码通常是出生日期或对注册者有意义的名字。这就是安全风险所在。一个可能的情景是,一位女士在Facebook上注册,并将密码设置为她女儿的全名。她在Facebook上的朋友可能会猜测她的密码与她的女儿有关,并尝试猜测她的登录详情。在这种情况下,传统的登录系统将允许无限次的猜测,攻击者最终可能会猜对并获取访问权限。
这种登录系统解决了这种情况,并为注册用户提供了更多的安全保障。
该系统是用Visual Basic.NET编写的,并使用SQL Server数据库存储用户信息。大多数用户数据都以明文形式存储,密码除外,密码使用SHA1进行加密。在开发过程中遇到的挑战主要是用户密码的加密以及通过会话变量跟踪登录尝试次数,这些挑战本质上是概念性的,并且相对容易解决。
在注册时,新用户将收到一封电子邮件,其中包含有关他/她的账户的详细信息。这些详细信息包括他们的用户ID、用户名和密码。要登录,用户必须首先输入他们的用户ID以验证他们确实在系统中有账户。一旦用户ID得到验证,他们将被要求提供与他们输入的用户ID相关联的用户名和密码。
如果当前会话记录的登录尝试次数少于3次,登录系统将对登录表单中输入的密码字段进行哈希和盐处理,并选择与用户输入完全相同的用户ID、用户名和密码值的记录。如果此选择没有从数据库返回单行记录,则登录无效,尝试次数将计入用户的会话。
如果记录了3次登录尝试,账户将被标记为锁定,并且在用户恢复之前,不会被包括在未来的登录尝试中。此外,在账户被锁定后,将生成一个36个字符长的值。然后对此值进行哈希和盐处理,并将其存储在数据库中作为账户的新密码。
以下是VB.NET代码示例:
Imports System.Data
Imports System.Data.SqlClient
Public Class Login
Inherits System.Web.UI.Page
Private connstr As String = "Data Source=.\SQLEXPRESS; Initial Catalog=test; Integrated Security=True;"
Private conn As SqlConnection = New SqlConnection(connstr)
Public NewPass As String = Nothing
Public HashedPass As String = Nothing
Public UserId As Integer = Nothing
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
If Not IsPostBack Then
pnlLoginForm.Visible = False
Session("LoginAttempt") = 0
End If
If Session("LoginAttempt") = 2 Then
Dim s As String = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
Dim r As New Random
Dim sb As New StringBuilder
Dim idx As Integer = Nothing
For i As Integer = 1 To 8
idx = r.Next(0, 61)
NewPass += sb.Append(s.Substring(idx, 1)).ToString
Next
HashedPass = Crypt.Compute(NewPass, "SHA512", Nothing)
Dim sql As String = "UPDATE Users SET Password = @Pass, LockedYN = @Lock"
Dim cmd As New SqlCommand(sql, conn)
cmd.Parameters.AddWithValue("@Pass", NewPass)
cmd.Parameters.AddWithValue("@Lock", "Yes")
conn.Open()
cmd.ExecuteNonQuery()
conn.Close()
End If
End Sub
Private Sub btnVerifyID_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles btnVerifyID.Click
If txtUserId.Text IsNot Nothing Then
Dim UserData As New DataSet
Dim UserAdapter As New SqlDataAdapter
UserAdapter.SelectCommand = New SqlCommand("SELECT * FROM Users WHERE UserId = @ID", conn)
UserAdapter.SelectCommand.Parameters.AddWithValue("@ID", txtUserId.Text)
UserAdapter.Fill(UserData)
If UserData.Tables(0).Rows.Count <> 1 Then
lblError.Text = "指定的用户ID不存在。"
lblError.ForeColor = Drawing.Color.Red
Else
If UserData.Tables(0).Rows(0)(4).ToString = "Yes" Then
lblError.Text = "尝试登录的账户已被锁定,以防止可能的未授权访问。如果这是账户,请检查电子邮件以获取解锁说明。"
lblError.ForeColor = Drawing.Color.Red
Else
UserId = txtUserId.Text
pnlLoginForm.Visible = True
End If
End If
End If
End Sub
Private Sub btnLogin_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles btnLogin.Click
If txtUser.Text IsNot Nothing And txtPass.Text IsNot Nothing Then
If Session("LoginAttempt") <> 2 Then
Dim pass As String = Crypt.Compute(txtPass.Text, "SHA512", Encoding.UTF8.GetBytes(Crypt.SaltValue))
Dim UserData As New DataSet
Dim UserAdapter As New SqlDataAdapter
UserAdapter.SelectCommand = New SqlCommand("SELECT * FROM Users WHERE Username = @User AND Password = @Pass AND LockedYN = @Lock", conn)
UserAdapter.SelectCommand.Parameters.AddWithValue("@User", txtUser.Text)
UserAdapter.SelectCommand.Parameters.AddWithValue("@Pass", pass)
UserAdapter.SelectCommand.Parameters.AddWithValue("@Lock", "No")
UserAdapter.Fill(UserData)
If UserData.Tables(0).Rows.Count <> 1 Then
lblError.Text = "无效的用户名或密码。"
lblError.ForeColor = Drawing.Color.Red
Session("LoginAttempt") = CInt(Session("LoginAttempt")) + 1
Else
Session("LoggedIn") = True
Response.Redirect("Home.aspx")
End If
Else
lblError.Text = "尝试登录的账户由于多次失败的登录尝试已被锁定。如果这是账户,请检查电子邮件以获取解锁说明。"
lblError.ForeColor = Drawing.Color.Red
End If
Else
lblError.Text = "请输入用户名和密码。"
lblError.ForeColor = Drawing.Color.Red
End If
End Sub
End Class
此版本包含了基本的安全“措施”。由于空闲时间的挑战,还没有能够添加处理电子邮件的代码。目前包括的有:
总是喜欢能够跨平台工作的软件,所以将致力于一个使用mysql作为数据后端的PHP版本。为了消除任何安全担忧,下一个版本将包括将用户从登录页面重定向的功能,如果他们当前已登录到他们的账户。正在进行的最重要的变化将是将用户ID从整数字段修改为guid()。这将消除用户ID被猜测的可能性,并使“伪造”另一个用户的账户变得更加复杂。
在能够使用此系统之前,需要更改连接字符串。当前每个与数据源工作的文件中都有一个:
VB.NET
Private connstr As String = "Data Source=.\SQLEXPRESS; Initial Catalog=test; Integrated Security=True;"
Initial Catalog和Data Source的值需要更改,以便系统能够正确地与数据库一起工作。系统正常工作只需要一个表。表必须包括以下结构,系统才能正确工作。
以下是创建示例:
SQL
CREATE TABLE [dbo].[Users](
[UserID] [int] IDENTITY(1,1) NOT NULL,
[Username] [varchar](20) NOT NULL,
[Password] [varchar](36) NOT NULL,
[EmailAddress] [varchar](100) NOT NULL,
[LockedYN] [char](3) NOT NULL,
CONSTRAINT [PK_Users] PRIMARY KEY CLUSTERED (
[UserID] ASC
)
)