Virtual Developer Workshop: Containerized Development with Docker
It has become a common practice to provide a secure login for companies web sites, and they adopt different methodologies. Some of those methods are either very expensive that middle or small size companies cannot afford or these are not 100 % foolproof. When I faced such a situation and was asked to find a solution for secure login to my company's official site that should not rely upon the user to keep their credentials confidential and safe, I came up with the following solutions.
Simple User ID and Password
This method, I believe, is the least secure method because users are human beings and they may disclose their ids and passwords unintentionally.
Client Certificate Authentication
A Microsoft Certificate Server can be installed on a Windows Server machine and user certificates can be issued to site users. Furthermore, the web site can be configured to require both username and password and a user certificate.
Two-factor authentication requires that two methods be used when accessing content on the secure web site. For example, one factor can be the username and password, and the second factor can be biometric input, such as a fingerprint. The two-factor authentication methods typically depend on what I know and what I have. Most two-factor authentication schemes require very expensive third-party devices that provide the what I have component.
You can develop a simple Windows application that will enable the user to provide his user ID and password. The application will get the system MAC address and send it along with the ID/password to web server. Upon receiving the ID, password, and MAC, the web server will grant access to the user only if his/her machine is registered.
After careful analysis, I decided to work on the last option—MAC-based authentication—although client certificate authentication was also feasible and suitable. However, granting access to web site users through a window application was a unique and interesting idea to me.
Understanding the Code
To better understand the code, kindly go through the paths of program execution that I have outlined below. The demo application (a window application is written in VB 6.0) is also attached. It deals with two main topics of the programming world:
- Registry reading/writing
- MAC address retrieval
Paths of Program Execution
- The application will retrieve the system's MAC address and display it to the user when it is run for the first time. Also, it will create a new key in the system Tegistry. The MAC address, along with the user ID and password, must be sent to the web site administrator to register the machine.
- After the user puts in his login and password on the login screen and presses OK, the program silently gets the system MAC address using GetAdaptersInfo and CopyMemory APIs. GetAdaptersInfo helps in reliably getting all MAC addresses for the system, but only for active and enabled interfaces. CopyMemory copies a block of memory from one memory location to another. Details can be found in MSDN.
- After getting all required information from user and his/her system, a web browser session is initiated using the Internet Explorer component.
Dim ie As New SHDocVw.InternetExplorer Header = "Content-Type: application/x-www-form-urlencoded" & _ Chr(10) & Chr(13) URI = "http://www.yourwebsite.com/Login.asp" macId = Replace(Trim(GetMACs_AdaptInfo()), "-", "", 1, -1, _ vbTextCompare) 'case-insensitive PostData = "uid=" & userName & "&pwd=" & password & "&mid=" & _ macId 'Encoding: Convert string data into byte array Post = StrConv(PostData, vbFromUnicode) ie.Visible = True ie.Navigate2 URI, , , Post, Header
For the Registry creation, I used the following API.
hTopKey = HKEY_CURRENT_USER sRegPath = "Key1\Key2\Key3" sa.nLength = Len(sa) sa.bInheritHandle = CLng(True) lResult = RegCreateKeyEx(hTopKey, sRegPath, 0, _ vbNullString, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, _ sa, hKey, lDisposition) If lResult = ERROR_SUCCESS Then If lDisposition = REG_CREATED_NEW_KEY Then CreateRegistry = True ElseIf lDisposition = REG_OPENED_EXISTING_KEY Then CreateRegistry = False End If Else CreateRegistry = False
Details of parameters and return values of RegCreateKeyEx method can be found in MSDN. The Registry key must be created under .HKEY_CURRENT_USER if the application's user has limited rights on the machine. I created a key in the system Registry in the following manner to hide it from prying eyes.
--> HKEY_CURRENT_USER -->Key1 -->Key2 -->Key3
The program first checks the Registry entry you just created when it is run for the first time on the machine. If the key is found, the login screen is shown.
sts = GetAdaptersInfo(AdapInfo, bufLen) If (bufLen = 0) Then Exit Function numStructs = bufLen / Len(AdapInfo) ReDim IPinfoBuf(0 To bufLen - 1) As Byte sts = GetAdaptersInfo(IPinfoBuf(0), bufLen) If (sts <> 0) Then Exit Function srcPtr = VarPtr(IPinfoBuf(0)) For i = 0 To numStructs - 1 If (srcPtr = 0) Then Exit For CopyMemory AdapInfo, ByVal srcPtr, Len(AdapInfo) With AdapInfo If (.AdapterType = MIB_IF_TYPE_ETHERNET) Then retStr = retStr & MAC2String(.MACaddress) & " " End If End With srcPtr = AdapInfo.Next Next i
IE component is available under Project --> Reference --> Microsoft Internet Controls. To successfully run the attached demo application, you must provide the name of your active web site and a page that will accept the user ID, password, and MAC information from Request.Forms collection in the URI variable. On the web end, you can have your web site in PHP, ASP, ASP.NET or in any other language. This window application requires just an active URL to which it could pass the credentials. Everything else will be taken care of by the login web page itself.
I have tested this application on machines having the Windows Vista, XP, 2000, and 98 operating systems. If anyone finds any problem with the application, please let me know.
The one thing that I dont like about this application is that it gets all MAC addresses of the system. I could not successfully find the MAC address of the Ethernet interface only. If anyone successfully gets it, please share it with me also.
To make the code work, I got a little help from Manni HV's article, Reliably Retrieve MAC Address(es) with VB.