By Supermac - Wed 22 Jul 2015
|
I'd like to write a routine to import massively customers (from csv file or from an SQL table, previously extracted from an ERP) in [tblKartrisUsers] table.
Giving a look to the table I found that the minimal info I should supply to an insert command are: [U_EmailAddress],[U_Password],[U_AccountHolderName],[U_LanguageID],[U_SaltValue] having that the rest of fields in SQL database have a default value or are not needed to let then the user access the site.
The problem are [U_Password] and [U_SaltValue] values: I don't understand how they work because it seems to me that every record in [tblKartrisUsers] table has its [U_SaltValue] as if every password has its personal decrypting key (randomly generated?). Furthermore, even [U_SaltValue] seems encrypted itself... maybe using Hash Salt String defined in install process and stored in web.config.file?
May you summarize to me how it works the relationship between [U_Password] and [U_SaltValue] (and eventually web.config's Hash Salt String)? And then may you suggest to me a modus operandi to reach my goal?
Thank you a lot
|
By Paul - Thu 23 Jul 2015
|
Suggest as a starting point you look at the UsersBLL.vb, and in particular the _Add function
Public Shared Function _Add(ByVal U_AccountHolderName As String, ByVal U_EmailAddress As String, ByVal U_Password As String, ByVal U_LanguageID As Integer, _ ByVal U_CustomerGroupID As Integer, ByVal U_CustomerDiscount As Double, ByVal blnUserApproved As Boolean, _ ByVal blnUserAffiliate As Boolean, ByVal U_AffiliateCommission As Double, ByVal U_SupportEndDate As Date, ByVal U_Notes As String) As Integer Try Dim dtNull As Nullable(Of DateTime) = Nothing Dim strRandomSalt As String = Membership.GeneratePassword(20, 0) Return CustomerDetailsAdptr._Add(U_AccountHolderName, U_EmailAddress, EncryptSHA256Managed(U_Password, strRandomSalt), U_LanguageID, U_CustomerGroupID, U_CustomerDiscount, blnUserApproved, _ blnUserAffiliate, U_AffiliateCommission, IIf(U_SupportEndDate = Nothing Or U_SupportEndDate = "#12:00:00 AM#", dtNull, U_SupportEndDate), U_Notes, strRandomSalt) Catch ex As Exception ReportHandledError(ex, Reflection.MethodBase.GetCurrentMethod()) Return Nothing End Try
End Function
This references the EncryptSHA256Managed function, from which you can see how the password in Kartris is hashed:
ConfigurationManager.AppSettings("hashsalt") & ClearString & SaltString
ConfigurationManager.AppSettings("hashsalt") is a value created when you install Kartris, and is written into an appsetting near the top of your web.config file. The SaltString is a random code up to 20 chars long created for each record. The ClearString is the cleartext password.
So if a user chooses 'mypassword123' as their password, then to get the hashed value you see in the users table we do
[hashsalt-from-user-record] & "mypassword123" & [hash-from-web-config]
Then we sha-256 this, and base64 encode the result.
For the purposes of your script to import usernames, you could use the same hashsalt for each user, but it's not a good idea, it's best to generate a random one for each user. Then you need the hashsalt value from your web.config file too, a sha-256 function and base64 function.
btw, the reason we have a global hashsalt as well as one in web.config is for additional security - the db alone doesn't contain all the information you'd need to hash a password guess, so it increases the number of attempts you'd need to make to get a hit massively. It also means if you take a Kartris db from one site and put it on another one, the password logins won't work unless you make sure the web.config hashsalt value matches.
|
By Mart - Fri 24 Jul 2015
|
Also, adding a hash salt for each separate password record makes brute force attacks more difficult... if we didn't do that an attacker could attack all the passwords at once. If you have thousands of user accounts his chances of breaking a few are very high, but with a separate salt per password, it means he realistically can only attack one at a time, making a brute force attack much more difficult.
|
By Supermac - Mon 27 Jul 2015
|
Thank you a lot I'll keep updated you on my progress!
|
By Supermac - Thu 30 Jul 2015
|
Ok let's say I inserted a record in [tblKartrisUsers] table and now my user could already enter the site logging in.
Now I have to insert his address, etcetera in [tblKartrisAddresses] table.
In KartrisClassess.vb there's an interesting [AddUpdate] function... I think I should use this one, can you please confirm and explain me values I can assign to ADR_Type? If I understand correctly, after insertion this function returns ADR_ID, is it right?
|
By Supermac - Thu 30 Jul 2015
|
I could use a thing like this?
Dim idcliente = userBLL._Add(U_AccountHolderName, U_EmailAddress, U_Password, U_LanguageID, U_CustomerGroupID, U_CustomerDiscount, blnUserApproved, blnUserAffiliate, U_AffiliateCommission, U_SupportEndDate, U_Notes)
'userBLL._Add may return nothing if something goes wrong if not isnothing(idcliente) then 'create address object with data from file Dim addr = New KartrisClasses.Address(<name of customer>, <company>, <address>, <city>, <P.O.code>, <destination.D_ID of customer's country>, <phone>
'insert new address Dim addrID = KartrisClasses.Address.AddUpdate(addr, idcliente, True) end if
???
|
By Supermac - Fri 31 Jul 2015
|
YEAH IT WORKS! :-) Added a page to backend that loads csv file and do all job using K's classes/methods... Now I've only to save passwords in a file (I create them randomly as clear strings and save them in a temporary table with relative customer name) and prompt it to the user, otherwise nobody will know how to access website :-)
|
|