Click here to Skip to main content
16,016,643 members
Articles / Programming Languages / Visual Basic

"Mutating" Login

Rate me:
Please Sign up or sign in to vote.
1.67/5 (3 votes)
24 Nov 2011CPOL4 min read 34.2K   503   15   14
Login system with breach redundancy handling.

Introduction

I came up with the concept for this after watching Die Hard 4.0 where the White Hat hacker in the movie had written what he called a "mutating security algorithm". I thought that it might be useful to have a system that changes (or mutates) passwords if a login fails enough times that it might present a security risk. 

This login system is not like your conventional system. Classic login systems rely on a defined username and password combination to allow users access to private information. A lot of people don't often use sufficiently strong passwords when they register to be part of a community website or even when they set their login information on internet banking systems.

These passwords are normally things like birthdates or names that have meaning to the registrant. This is where the security risk comes in.
A plausible scenario would be a situation in which a woman signs up for facebook and sets her password as her daughter's full name. Friends of hers on facebook that  may be feeling "mischievous" might guess that her password has something to do with her daughter, and make attempts at guessing her login details.

In this situation, a classic login system would allow for an unlimited number of guesses during which the "attacker" might eventually  guess right and gain access.

This login system addresses such a situation and provides more security to the registered user.

Background

This system was written in Visual Basic.NET and uses a SQL Server database for storage of user information. Most user data is stored as plain text, with the exception of the user's password which is encrypted using SHA1.

Challenges during development were small issues around the encryption of the user's password as well as the tracking of login attempts through the use of a session variable which gets counted on each attempt. These issues were purely conceptual in nature and were resolved relatively quickly.

How It Works

Upon registration, a new user will be sent an email which will contain details about his/her account. These details include their user id, username, and password.
To log in, the user will have to enter their user id first to verify that they indeed do have an account on the system. Once the user id is verified, they will be asked to supply the username and password that is associated with the user id that they entered.

Where there are less than 3 login attempts on record for the current session, the login hashes and salts the value entered into the password field on the login form, and selects a record with user id, username, and password value that are identical to user input. If this selection doesn't return a single row from the database, the login was invalid and an attempt gets counted in the user's session.

Should there be 3 login attempts counted, the account is flagged as locked and, until such time as it is recovered by the user, will not be included in selection for future login attempts.
In addition, a 36 character long value is generated after the account gets locked. This value is then hashed and salted and stored in the database as the new password for the account.

Login.aspx.vb  

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
            ' This account may be vulnerable, generate a random string for the new password and lock the account
            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 = "Specified User ID does not exist."
				lblError.ForeColor = Drawing.Color.Red
			Else
				If UserData.Tables(0).Rows(0)(4).ToString = "Yes" Then
					lblError.Text = "The account you tried to log into has been locked to prevent possible unauthorized access. " & _
					"If this is your account, please check your email for instructions to unlock it."
					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 = "Invalid username or password."
					lblError.ForeColor = Drawing.Color.Red
					Session("LoginAttempt") = CInt(Session("LoginAttempt")) + 1
				Else
					Session("LoggedIn") = True
					Response.Redirect("Home.aspx")
				End If
			Else
				lblError.Text = "The account you tried to log into is now locked due to excessive failed login attempts. " & _
					"If this is your account, please check your email for instructions to unlock it."
				lblError.ForeColor = Drawing.Color.Red
			End If
		Else
			lblError.Text = "Please enter a username and password."
			lblError.ForeColor = Drawing.Color.Red
		End If
	End Sub
End Class 

What this release contains 

This release contains the basic security "measures". Due to challenges with free time, I haven't been able to add the code to process the emails yet. 

Currently included are:

  • Functions to handle SHA1 encryption of user passwords
  • General session management that keeps track of login attempts
  • Bare-bones user interface used while testing. This has not been cleaned up in this version. 

Plans for the future

I always like it when I can find software that works on multiple platforms, so I'll be working on a PHP version that uses mysql as a data backend.

To put any security worries to bed, the next version will include functionality to redirect users off of the login page if they are currently logged in to their account.

Probably the most crucial change in the works will be the modification of the user id from an integer field to a guid(). This will eliminate the possibility of user ids being guessed and make "spoofing" another user's account a lot more complicated. 

Using the code

Before you can use this system, you'll need to change the connection strings. Currently each file that works with the data source has one in it:

  • Create.aspx.vb 
  • Login.aspx.vb 

VB.NET
' This is what the connection string currently looks like:
Private connstr As String = "Data Source=.\SQLEXPRESS; Initial Catalog=test; Integrated Security=True;"

' The values for Initial Catalog and Data Source will need to be changed in order for the system to work correctly with your database. 

Only one table is needed for the system to function correctly. The table must include the following structure for the system to work correctly. 

Users Table:
UserID (PK, int, not null) -- identity(1,1)
Username (varchar(20), not null)
Password (varchar(36), not null)
EmailAddress (varchar(100), not null)
LockedYN (char(3), not null) -- default 'No'

Here's a CREATE sample to get you going: 

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
)

 

Feel free to add more columns to your user table if you wish, but if you remove or change any of these, the system will break.  

Points of Interest   

Google is your friend. The encryption was particularly challenging for me to make work. I found a number of samples that I worked through and based my code (Crypt.aspx.vb) on. 

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer Netgen
South Africa South Africa
I started coding back in high school. My "Computer Science" subject for grade 10 was actually an introduction to programming in Delphi. I struggled a lot and was fairly disheartened and frustrated by the time I got to the end of the book.
That changed, though, when I found an introduction to HTML in the back after all the Delphi. I was hooked! It was simple and I could see the results of my work as I did it.

I kept teaching myself over the years and branched out into other languages as I found my requirements changing.
The first "server-side" tech I learnt was asp.net with visual basic code behind.

Now that I'm working with it as a day job, I've moved over to PHP for my personal projects, so the learning continues.

When I'm not coding, I'm either playing World of Warcraft, some other game or hanging out with friends. I enjoy playing pool and ice skating as "extra curricular" activities.

Comments and Discussions

 
GeneralMy vote of 1 Pin
Marco Bertschi15-May-13 21:37
protectorMarco Bertschi15-May-13 21:37 
GeneralRe: My vote of 1 Pin
ortund15-May-13 22:04
ortund15-May-13 22:04 
GeneralRe: My vote of 1 Pin
Marco Bertschi15-May-13 22:25
protectorMarco Bertschi15-May-13 22:25 
ortund wrote:
It seems strange to me that in most cases (and I'm not talking about online banking/shopping where highly sensitive financial data is passed around), simple password encryption is sufficient for almost everyone

No it is not. They send you an additional pin as SMS to confirm your identity. Furthermore, the connection is SSL encrypted.


ortund wrote:
on the matter is how sh*t it is...

I did not say that it is sh*t, and I am ready to revote the article when you improved it.


ortund wrote:
What this article did was to show me that the programming community of the world doesn't like innovation.

Innovation is good, but after how you presented the so called Innovation I just do not get the point how your solution may be a plus for the security of login.


ortund wrote:
Nobody has come to me saying anything like "nice idea, it has potential, but here's some problems with it: xyz. Would you be open to collaboration with me to improve on it? Maybe we can deliver something that is properly world class".

I'd love to collaborate, but I simply do not have the time at the moment.
I am sorry if I was not clear enough about the actual issues:
-> What is the innovation? It is common practice, in critical medical applications for example, to lock the account after three failed login attempts and regenerate a new password
-> You do not explain how you actually do the hashing and salting

My suggestions to improve the article:
-> Go away from the focus of "What happens when the login fails three times" and go rather for something like "How to store a password securely" - explain the hashing & salting, and describe what you do when a user sets a new password, a user requests a new password or a user logs into the system.
-> Explain the code carefully. Every method you wrote by yourself should be explained step-by-step (What does it? Why? How?).


ortund wrote:
No, it's always just been "this sucks and you don't have a shitting clue what you're doing". When I wrote this, I really wanted to develop my abilities in terms of security. I was learning about penetration testing, hashing, salting, all of it... but this community has been so negative and destructive about this article that I quickly lost all motivation to even bother going anywhere with any of it.

I hope my suggestions are constructive for you to improve the article.
However, security is not only defined in just "What do I do when a user fails to login?". It is about "How can I prevent people from stealing data", too. You learned about hashing and salting, a topic which is not very good covered on CodeProject yet. That is good. Now it is at you to pick up the topic and make an explanation about hashing and salting, which would be appreciated by many community members.

And I hope I was able to correct the picture you have about our community!

Please, if you have further questions about how to write a good article, feel free to get back to me!

cheers,
Marco
Marco Bertschi

Twitter | Articles | G+

GeneralMy vote of 1 Pin
Not Active1-Dec-11 2:26
mentorNot Active1-Dec-11 2:26 
GeneralRe: My vote of 1 Pin
ortund19-Dec-11 19:36
ortund19-Dec-11 19:36 
GeneralRe: My vote of 1 Pin
Not Active20-Dec-11 2:35
mentorNot Active20-Dec-11 2:35 
SuggestionSecurity? Pin
geo_m24-Nov-11 21:39
geo_m24-Nov-11 21:39 
GeneralRe: Security? Pin
ortund25-Nov-11 2:42
ortund25-Nov-11 2:42 
GeneralRe: Security? Pin
geo_m25-Nov-11 4:25
geo_m25-Nov-11 4:25 
GeneralRe: Security? Pin
ortund27-Nov-11 19:49
ortund27-Nov-11 19:49 
GeneralRe: Security? Pin
geo_m29-Nov-11 0:23
geo_m29-Nov-11 0:23 
QuestionRe: Security? Pin
ortund19-Dec-11 19:31
ortund19-Dec-11 19:31 
AnswerRe: Security? Pin
geo_m19-Dec-11 20:33
geo_m19-Dec-11 20:33 
AnswerRe: Security? Pin
geo_m19-Dec-11 21:29
geo_m19-Dec-11 21:29 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.