Making SQL password query case sensitive using COLLATE - sql

I am using the following SQL code in my VB in VS2013. I want to create a login form using a database of users stored into a UserList. However The query is not case sensitive. How do I change my query string to use COLLATE or any other case sensitive comparison
Dim Check As String = _
"SELECT COUNT(*) AS Expr1 FROM UserList HAVING (Username = '" & _
_UsernameTextBox.Text & "') AND ([Password]= '" & _PasswordTextBox.Text & _
"') AND (UserType = '" & User.ToString & "')"
With search
.CommandText = Check
.Connection = cn
If .ExecuteScalar() = 1 Then
Me.Hide()
If User = "Trader" Then
Trader.Show()
ElseIf User = "Broker" Then
Broker.Show()
ElseIf User = "Corporate" Then
Corporate.Show()
ElseIf User = "System" Then
SystemManager.Show()
End If
Else : MsgBox("IncorrectInput")
End If`

"SELECT COUNT(*) AS Expr1 FROM UserList
HAVING (Username = #username)
AND ([Password] COLLATE Latin1_General_CS_AS = #password)
AND (UserType = #usertype)
"
Apart from the fact that you don't have your password stored and compared with a slow salted cryptographic hash function (=non-reversible encryption), your query is also vulnerable to SQL-injection (when I use a username like "Jean le Rond d'Alambert" or just "d'Alambert".
Another bug is that when you save the password as plain text, say e.g. (n)varchar(32), I can enter a password that is longer than that (e.g. a sentence) ==> bug
Given you're writing a financial application ("broker", "corporate"), SQL-injection is an intolerable security risk.
You can for example MD5-hash your password (cheap & dirty):
master.dbo.fn_varbintohexstr(HashBytes('MD5', 'test'))
You have a "System.Data.SqlClient.SqlCommand",
there you can add a System.Data.SqlClient.SqlCommand
using (SqlConnection connection = new SqlConnection(connectionString))
{
connection.Open();
//
// Description of SQL command:
// 1. It selects all cells from rows matching the name.
// 2. It uses LIKE operator because Name is a Text field.
// 3. #Name must be added as a new SqlParameter.
//
using (SqlCommand command = new SqlCommand(
"SELECT * FROM Dogs1 WHERE Name LIKE #Name", connection))
{
//
// Add new SqlParameter to the command.
//
command.Parameters.Add(new SqlParameter("Name", dogName));
//
// Read in the SELECT results.
//
SqlDataReader reader = command.ExecuteReader();
while (reader.Read())
{
int weight = reader.GetInt32(0);
string name = reader.GetString(1);
string breed = reader.GetString(2);
Console.WriteLine("Weight = {0}, Name = {1}, Breed = {2}",
weight,
name,
breed);
}
}
}
If you do it right from the start, then you don't have to change anything later.

Related

Username and password not case sensitive

I know that I am not storing my passwords in hash but for the purposes of this database, that doesn't matter.
The code references an SQL database that stores the passwords as plain text
Here's the code:
/*Checks to see if the username and password matcch the database
If it does, it lets you in, if not you displays an error message*/
string user = textBox1.Text.ToString();
string pass = textBox2.Text;
MySqlConnection conn = new MySqlConnection(ConnectionString);
MySqlDataAdapter sda = new MySqlDataAdapter("SELECT COUNT(*) from Employees WHERE UserName = '"+(user)+ "' and Password = '"+(pass)+"' collate Latin1_Genral_CS_AS", conn);
DataTable dt = new DataTable();
sda.Fill(dt);
if(dt.Rows[0][0].ToString() == "1")
{
HomeScreen home = new HomeScreen();
this.Hide();
home.ShowDialog();
}
else
{
MessageBox.Show("Incorrect Username or Password", "alter", MessageBoxButtons.OK, MessageBoxIcon.Error );
}
You can convert both the input values and table columns to lowercase or uppercase:
/*Checks to see if the username and password matcch the database
If it does, it lets you in, if not you displays an error message*/
string user = textBox1.Text.ToLower();
string pass = textBox2.Text.ToLower();
MySqlConnection conn = new MySqlConnection(ConnectionString);
MySqlDataAdapter sda = new MySqlDataAdapter("SELECT COUNT(*) from Employees WHERE LOWER(UserName) = '"+(user)+ "' and LOWER(Password) = '"+(pass)+"' collate Latin1_Genral_CS_AS", conn);
DataTable dt = new DataTable();
sda.Fill(dt);
if(dt.Rows[0][0].ToString() == "1")
{
HomeScreen home = new HomeScreen();
this.Hide();
home.ShowDialog();
}
else
{
MessageBox.Show("Incorrect Username or Password", "alter", MessageBoxButtons.OK, MessageBoxIcon.Error );
}
You can alter your database to use the collation you wish:
ALTER DATABASE DBNAME CHARACTER SET utf8 COLLATE utf8_general_ci;
However, this will only apply on new tables. You can alter a table column to use the collation of your preference:
ALTER TABLE table_name MODIFY column_name column_datatype COLLATE utf8_bin;

Why does this parameterized sql query not return results?

I am taking over a VB project and with my limited VB skills I cannot get the following to parameterized query to return results:
Dim strSQLUser As String = "Select Name, CompanyID from Users where UserName = #UserName"
dbCommand = New SqlCommand(strSQLUser, dbConn)
dbCommand.Parameters.AddWithValue("#UserName", User)
dr = dbCommand.ExecuteReader
However this is the original code that does work:
Dim strSQLUser As String = "Select Name, CompanyID from Users where UserName ='" & User & "'"
dbCommand = New SqlCommand(strSQLUser, dbConn)
dr = dbCommand.ExecuteReader
As you can see the original code was vulnerable to sql injection and needs to be fixed.
Extra - Here is the line that does the reading:
While dr.Read
DbUser = dr.GetValue(0).ToString
DbCompany = dr.GetValue(1).ToString
End While
Try this:
Dim strSQLUser As String = "Select Name, CompanyID from Users where UserName =#UserName"
dbCommand = New SqlCommand(strSQLUser, dbConn)
dbCommand.Parameters.AddWithValue("#UserName", User.Text)
dr = dbCommand.ExecuteReader
Also the better approach is provide the value as:
dbCommand.Parameters.Add("#UserName", SqlDbType.VarChar).Value = User.Text
Assuming User to be the varchar ie., text type.
When using parameters you do not specify the quotes around parameters '. All the parameters are automatically converted to their respective column types such as date, nvarchar etc. So no more quotes.
Dim strSQLUser As String = "Select Name, CompanyID from Users where UserName =#UserName"

Concatenate database query result to a string

I am trying to take the single result from a SQL query and concatenate it to a string. Using SQL Server and Visual Studios.
Dim Password As SqlDataReader
cmd.CommandText = "Select Password from tblLogin where Username = '" & UsernameTextBox.Text & "' and EmailAddress = '" & EmailAddressTextBox.Text & "'"
Password = cmd.ExecuteReader
EmailMessage.Body = ("Your password is: " & Password)
The error I am getting is that I cannot use the operator & with Password.
The Password variable in your code is a SQLDataReader object, not a string. It can have many values, so you need to get the part you want out of it. (https://msdn.microsoft.com/en-us/library/haa3afyz(v=vs.110).aspx?cs-save-lang=1&cs-lang=vb#code-snippet-2)
If Password.HasRows Then
Do While Password.Read()
EmailMessage.Body = ("Your password is: " & Password.GetString(0))
Loop
Else
Console.WriteLine("No rows found.")
End If
I would also recommend changing the Password SQLDataREader to a different name, just to make it less confusing.

sql command query for log in asp.net

Hello i been looking around and i cant seem to find how to make a safe sql command ( vs injections ) for checking log in details from the database , i found something like this code which seem to be the thing i need but i cant seem to understand how to actully check if the user exists.
This code happens on LogIn Button click , and i am suppose to redirect the user to another page + save some of the valuse from the row ( like userId , companyId and few others ) into sessions for later use . I just not so sure how .
Protected Sub enterBtn_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Me.Load
Dim connectionString As String = ConfigurationManager.ConnectionStrings("ConnectionString").ToString()
Dim query As String = String.Format("select userName, userPassword, companyId from " & "[users] where userName like '%+#userName+%', userBox.Text)
Using con As New SqlConnection(connectionString)
'
' Open the SqlConnection.
'
con.Open()
'
' The following code uses an SqlCommand based on the SqlConnection.
'
Using da As New SqlDataAdapter()
Using command As New SqlCommand(query, con)
'pass the parameter
command.Parameters.Add(New SqlParameter("#userName", userBox.Text))
command.Parameters.Add(New SqlParameter("#userPassword", passwordInput.Text))
command.Parameters.Add(New SqlParameter("#companyId", companyIdBox.Text))
Dim ds As New DataSet()
da.SelectCommand = command
da.Fill(ds, "test")
End Using
End Using
End Using
Change your query string to
Dim query As String = "select userName, userPassword, companyId " & _
"from [users] " & _
"where userName like #userName " & _
"userPassword = #userPassword " & _
"companyID = #companyID"
and then in the section where you add the parameters
command.Parameters.Add(New SqlParameter("#userName", "%" & userBox.Text "%"))
The trick is to write the query text as clean as possible and add the wildcard required by the like directly in the value passed to the SqlParameter constructor
I suggest also to use a different way to build your Parameters collection
command.Parameters.Add(New SqlParameter With
{
.ParameterName = "#userName",
.Value = "%" & userBox.Text "%",
.SqlDbType = SqlDbType.NVarChar
})
This is more verbose but avoids the confusion between the two overloads of the Add method the one that accepts an SqlDbType and the one that accepts an object as second parameter.
Then if you want to know if a user with that name, password an company has been found just loop at the count of rows present in the first table of the DataSet
If ds.Tables(0).Rows.Count > 0 then
... you have your user .....
End if
However a better query would be
Dim query As String = "IF EXISTS(select 1 from [users] " & _
"where userName like #userName " & _
"userPassword = #userPassword " & _
"companyID = #companyID) " & _
"SELECT 1 ELSE SELECT 0"
and instead of the SqlDataAdapter and DataSet you write simply
Using con As New SqlConnection(connectionString)
Using command As New SqlCommand(query, con)
con.Open()
command.Parameters.Add(New SqlParameter("#userName", userBox.Text))
command.Parameters.Add(New SqlParameter("#userPassword", passwordInput.Text))
command.Parameters.Add(New SqlParameter("#companyId", companyIdBox.Text))
Dim userExists = Convert.ToInt32(command.ExecuteScalar())
if userExists = 1 Then
Session["UserValidated"] = "Yes"
else
Session["UserValidated"] = "No"
End If
End Using
End Using

Exception while retrieve a null field from sql ce 3.5

I am storing an image in a table in varbinary(max) format, actually first time it will be empty, I am checking whether it is empty of not but while checking for null field I am getting any exception stating invalid cast so can any one suggest what is the problem with this.
code sample is
con = new SqlCeConnection(CommonClass.ConnectionStringStartup);
con.Open();
SqlCeCommand cmd = con.CreateCommand();
cmd.CommandText = "SELECT Signature,UserId FROM UserMaster Where " +
" LoginName = '" + UserName + "' " +
" AND Password = '" + Password + "'";
cmd.CommandType = CommandType.Text;
// MessageBox.Show(UserName);
SqlCeDataReader dr;
dr = cmd.ExecuteReader(CommandBehavior.CloseConnection);
if (dr.Read())
{
if (dr.IsDBNull(0))
SignLoaded = false;
else
SignLoaded = true;
}
Thanks in advance
With regards
Bharath kumar
To me, it looks like this should work?
Have you tried Convert.IsDbNull( dr.GetValue(0))?
Otherwise I can only suggest using dr.GetValue(0) and look at the result.
Cheers