I am looking for backdoors in various softwares and wondering if the following code is vulnerable to a sql injection.
There's an email field with the following validation expression. (ASPX/CS)
ValidationExpression="\w+([-+.']\w+)*#\w+([-.]\w+)*\.\w+([-.]\w+)*">
Is it possible to exploit the above to drop a table for example or do anything malicious using a SQL injection?
Thanks
Regards
EDIT 1: People have asked me how this was implemented —
SqlConnection conn = new SqlConnection(snpConnectionString);
SqlCommand command = conn.CreateCommand();
conn.Open();
command.CommandText = "INSERT INTO TABLE_ VALUES ('" + TextBoxFN.Text + "','" + TextBoxLN.Text + "','" + sb1.ToString() + "','" + TextBoxEA.Text + "','" + sb.ToString() + "',0,'" + DateTime.Now + "')";
try{
SqlDataReader reader = command.ExecuteReader();
}
catch
{
Response.Redirect("Error.aspx", true);
}
TextBoxEA.text corresponds to the email address.
Regular expression validation is great for the UI or business layer to check user input to prevent errors.
It is less great for preventing SQL injection.
If the code does not use parameterized queries, it is vulnerable either now, or later after someone makes a minor error updating the regular expression to conform to a new business requirement.
It is best to use parameterized queries like Eric stated, but looking at the regex only the following characters are valid
A-Za-z0-9_-+.'
Without a space I don't think they could inject SQL, but if it was me I'd still make sure to use parameterized queries to be safe.
Related
sqlCommand1 = new SqlCommand("INSERT INTO dbo.Orders(Title,Seats,Payment,DateNTime)"+
"VALUES ('"+ movieName+"',"+numTickets+",'"+creditCardType+"',"+DateTime.Now+")", sqlConnection1);
sqlCommand1.Connection.Open();
sqlCommand1.ExecuteNonQuery();
sqlCommand1.Connection.Close();
No idea what's wrong with this piece of code. Title and Payment are stored as nvarchar types, Seats as an int and DateNTime as DateTime.
Can someone help me with this?
Thanks in advance
Need quotes for dates as well:
,'" + DateTime.Now.ToString("yyyyMMdd") + "')"
But this is very dangerous code you know. You really should use parametrized query for such things!
You will be in trouble if user enters in Title textbox something like this:
some text', 1, 1, '20100101'); drop table dbo.Orders--
And you are fired the same day.
Very likely the error lies here:
... ,"+DateTime.Now+")"
You must make sure, that the string expression for DateTime.Now is parseable in SQL.
Do not put your values into the SQL comman (read about SQL injection)
Read about parameters and how to pass them
Never rely on culture dependant date-time-formats... (read about ISO8601 or ODBC)
Guessing this is called from c# code, you should use parameters instead of concatenating strings into sql statements.
This will both protect you from sql injection attacks and fix your syntax error:
This code should probably work for you, though it's written right here and I didn't test it:
using (var sqlConnection1 = new SqlConnection("ConnectionString"))
{
using (var sqlCommand1 = new SqlCommand("INSERT INTO dbo.Orders(Title,Seats,Payment,DateNTime)" +
"VALUES (#movieName, #numTickets, #creditCardType, #DateTime.Now)", sqlConnection1))
{
sqlCommand1.Parameters.Add("#movieName", SqlDbType.VarChar).Value = movieName;
sqlCommand1.Parameters.Add("#numTickets", SqlDbType.VarChar).Value = numTickets;
sqlCommand1.Parameters.Add("#creditCardType", SqlDbType.Int).Value = creditCardType;
sqlCommand1.Parameters.Add("#movieName", SqlDbType.DateTime).Value = DateTime.Now;
sqlCommand1.Connection.Open();
sqlCommand1.ExecuteNonQuery();
}
}
Try to use following
sqlCommand1 = new SqlCommand("INSERT INTO dbo.Orders(Title,Seats,Payment,DateNTime)"+
"VALUES ('"+ movieName+"',"+numTickets+",'"+creditCardType+"','"+DateTime.Now+"')", sqlConnection1);
sqlCommand1.Connection.Open();
sqlCommand1.ExecuteNonQuery();
sqlCommand1.Connection.Close();
Even after that modification, if you are getting error, please tell datatype of Title,Seats,Payment,DateNTime
You have format date part also.
sqlCommand1 = new SqlCommand("INSERT INTO dbo.Orders(Title,Seats,Payment,DateNTime)"+
"VALUES ('"+ movieName+"',"+numTickets+",'"+creditCardType+"','"+DateTime.Now.ToString("yyyyMMdd")+"')", sqlConnection1);
sqlCommand1.Connection.Open();
sqlCommand1.ExecuteNonQuery();
sqlCommand1.Connection.Close();
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 7 years ago.
Improve this question
After R&D I didn't get solution for this flaw. Please guide me in solving this flaw
Description
This database query contains a SQL injection flaw. The function call constructs a dynamic SQL query using a variable derived from user-supplied input. An attacker could exploit this flaw to execute arbitrary SQL queries against the
database.
Recommendations
Avoid dynamically constructing SQL queries. Instead, use parameterized prepared statements to prevent the database from interpreting the contents of bind variables as part of the query. Always validate user-supplied input to
ensure that it conforms to the expected format, using centralized data validation routines when possible.
public void EditUser(User f)
{
string connectionString
= ConfigurationSettings.AppSettings["ConnectionString"];
SqlConnection conn = new SqlConnection(connectionString);
SqlCommand cmd = conn.CreateCommand();
string adm = (f.IsAdmin?"1":"0");
string phone="",email="";
if(f.PhoneList.Count > 0)
phone = f.PhoneList[0].ToString();
if(f.EmailList.Count > 0)
email = f.EmailList[0].ToString();
for(int i = 1; i < f.PhoneList.Count; i++)
phone = phone + ";" + f.PhoneList[i].ToString();
for(int i = 1; i < f.EmailList.Count; i++)
email = email + ";" + f.EmailList[i].ToString();
cmd.CommandText = "UPDATE Users SET is_admin="+adm+",login='"+f.Login+"',passwd='"+f.Password+
"',firstname='"+f.FirstName+"',lastname='"+f.LastName+"',email='"+email+"',phone='"+phone+"',address='"+f.Address+"' where user_id="+f.UserId;
conn.Open();
int affected = cmd.ExecuteNonQuery();
cmd.ExecuteNonQuery();
}
Your code builds up the SQL command by appending strings together
cmd.CommandText
= "UPDATE Users SET is_admin="+adm+",login='"+f.Login+"',passwd='"+f.Password+
"',firstname='"+f.FirstName+"',lastname='"+f.LastName+"',email='"+email+"',phone='"+phone+"',address='"+f.Address+"' where user_id="+f.UserId;
Suppose someone called your function with a User value where lastname equaled
"Presser';DROP TABLE Users --"
Your SQL command will now destroy the Users table.
See here, where MSDN describes how to avoid this problem.
Hello guys i building a web app with asp.net and using sql ( MS SQL server 2000 ) and now after getting closer to finish i noticed that the sql part of my code taking huge amounts of space... and i was wondering what ways are there to make it easier to maintain? maybe even change to some other language?
Here is a simple example of the way my sql code is built ( there are some much longer commands in my code but they built this way) :
Dim connectionString As String = ConfigurationManager.ConnectionStrings("ConnectionString").ToString()
Dim query As String = "SELECT workerName FROM [poWorker] WHERE ( companyId = #companyId ) AND (workerId=#workerId) "
Using con As New SqlConnection(connectionString)
con.Open()
Using da As New SqlDataAdapter()
Using command As New SqlCommand(query, con)
command.Parameters.Add(New SqlParameter("#workerId", Session("userId")))
command.Parameters.Add(New SqlParameter("#companyId", Session("companyId")))
Dim ds As New DataSet()
da.SelectCommand = command
da.Fill(ds, "test")
If ds.Tables(0).Rows.Count = 1 Then
managerName = ds.Tables(0).Rows(0)(0).ToString()
End If
End Using
End Using
con.Close()
End Using
This is taking a lot of space and i got a lot of sql written this way. I am sure there is some solution in making it easier to maintain, probably using a newer technology? Maybe if i could figure out a way to call all the sql commands from 1-2 functions but so far i failed to do such a thing since there big differences between many of those.
In the example you give, you could simplify the code by using ExecuteScalar - as you are just returning a single value. For example:
Dim query As String = "SELECT workerName FROM [poWorker] WHERE ( companyId = #companyId ) AND (workerId=#workerId) "
Using con As New SqlConnection(connectionString)
con.Open()
Using command As New SqlCommand(query, con)
command.Parameters.Add(New SqlParameter("#workerId", Session("userId")))
command.Parameters.Add(New SqlParameter("#companyId", Session("companyId")))
managerName = command.ExecuteScalar().ToString();
End Using
con.Close()
End Using
A modern way to access databases from code is to use an ORM. The one that Microsoft provides with the .NET Framework is Entity Framework. This allows you to write your query like this:
Dim worker as Worker =
dbContext.Workers
.Where(Function (w) (w.companyId = Session("companyId") and
w.workerId = Session("userId")))
.SingleOrDefault()
If worker IsNot Nothing Then
managerName = worker.workerName
End If
This approach also provides a far more robust approach to dynamic queries as opposed to piecing SQL strings together. For example, you can dynamically swap out Where clauses, OrderBy clauses, and so on, and still have completely typesafe code.
Entity Framework does not have builtin support for SQL Server 2000, but apparently there is a workaround.
The modern way is to no use SQL directly, but rather an OR-Mapper such as Entity Framework that allows you to query using Linq.
The query you show above would the be reduced to something shorter:
using(new context = MyAppDbContext())
{
var workerId = Session["userId"];
var companyId = Session["companyId"];
managerName = context.PoWorker
.Single(w => w.companyId == companyId && w.workerId == workerId)
.workerName;
}
Sorry for using C# syntax, but I hope you can figure out the intention.
I got a problem with this code:
string sql = "select distinct ruoli.c_tip_usr"
+ " from vneczx_ute_app_trn ruoli"
+ " join vnecyd_ent_prf ind"
+ " on ruoli.c_ent = ind.c_ent"
+ " where ruoli.c_app = :appCode"
+ " and ruoli.c_ute_mat = :matricola"
+ " and ind.t_des_ent = :indirizzo";
var ruoli = session.CreateSQLQuery(sql)
.SetString("appCode", Config.Configurator.Istance.ApplicationCode)
.SetString("matricola", user.Matricola)
.SetString("indirizzo", indirizzoCasella)
.List<string>();
This code is correctly executed, the query logged is correct, and the parameter passed correctly evaluated... but it doesn't return any result at all.
Copying the query from the debug console and executing it directly in an Oracle client application (SQL Developer), it gets 2 results (the results I expect to be right).
I found out that the problem is in the last parameter indirizzo, and should depend on the fact that it contains a special char # (indirizzo is an email address).
So I ended up using this solution:
string sql = "select distinct ruoli.c_tip_usr"
+ " from vneczx_ute_app_trn ruoli"
+ " join vnecyd_ent_prf ind"
+ " on ruoli.c_ent = ind.c_ent"
+ " where ruoli.c_app = :appCode"
+ " and ruoli.c_ute_mat = :matricola"
+ " and ind.t_des_ent = '" + indirizzoCasella + "'";
var ruoli = session.CreateSQLQuery(sql)
.SetString("appCode", Config.Configurator.Istance.ApplicationCode)
.SetString("matricola", user.Matricola)
.List<string>();
But it gives me thrills! Aren't the parameters in a query supposed to handle specifically this situation, and thus handle themselves situations with special char, and so on?
Why here a string concatenation works better that a parametric query?
Isn't there a way to force the NHibernate engine to escape some special char?
Update:
I found out how to solve this particular issue: usign the trim command on the field who raise the problem, the problem disappears.
So last line of my sql string now is:
+ " and trim(ind.t_des_ent) = :indirizzo";
I can't understand why it solves the problem thought. Not the field, nor the variable contains empty chars and copying th query on SQL Developer works in both way.
So we have some luck soving the problem, but we have no idea why now it works?
Any thoughts?
even I was facing the same issue, but your hint using TRIM for column saved my day. Since I was looking for a long time, but not able to figure it out.
Along with that, I was able solve my issue by doing the below changes as well:
We were using CHAR datatype some of the columns which used in the query where clause. This was causing the issue to fetch the data from NHibernate. We changed the data type of that column from CHAR to VARCHAR2 and even updated the data with actual size and removed the TRIM from Where clause, the TRICK WORKED!!!! :)
So, any one face this kind of issue, first check whether you are having any column with CHAR and then change to VARCHAR2.
But one more thing you have to remember is: if you are running your application from ASP.Net Development Server, close it and re-run your application. Since if the opening Asp.Net Development Server and if you make any changes to datatype that will NOT be refreshed in your oracle connection. So, better you close the ASP.Net Development server and then re run the application.
Hope my points will help somebody in future!!
Regards,
Sree Harshavardhana
You are not using parameters in a SQL query if you want SQL parameters use a SQL stored proc
I'm getting a strange syntax error when I run this in VB:
SQLString = "UPDATE Login SET Password = '" + PasswordTextBox.Text + "'"
SQLString += " WHERE UserName = '" + UserNameTextBox.Text + "'"
The Username is checked before getting to this part and is definitly in the database.
It gives an exception saying that there's a syntax error in update statement. Anyone have any idea what's wrong?
LOGIN is a reserved word in SQL Server (used for login account management), so in order to use it in a query (i.e. a column name) you need to escape it with [], so use [LOGIN] as the field name.
You should never use string concatenation and pass that to your SQL database, as you are exposing yourself to SQL Injection attacks.
You should use the SqlCommand object and pass through parameters. See this article on how to do so.
SQLString = "UPDATE [Login] SET Password = #password "
SQLString += " WHERE UserName = #userName"
...
dbCommand.Parameters.Add("#password", SqlDbType.VarChar, 50)
dbCommand.Parameters["#password"].Value = PasswordTextBox.Text
dbCommand.Parameters.Add("#userName", SqlDbType.VarChar, 50)
dbCommand.Parameters["#userName"].Value = UserNameTextBox.Text
I am pretty sure that Login is a reserved word, try changing Login to [Login]
Password is a reserved word so [Password] fixes it, my lecturer fixed to for me :)
Instead of showing how you're building the statement, show us what's in SQLString when the statement is executed.
Also, try enclosing the column and table names in the identifier quote characters, which are [ and ] for Microsoft, and ` (on the tilde key) for many others databases.
Without knowing what you are using for your actual password and username, my guess is that some character in one (or both) of those are causing the sql statement to end prematurely. You should really use parameters when executing sql like this.
Take a look at this: http://msdn.microsoft.com/en-us/library/ms998271.aspx
I agree with some of the previous answers, about using parameters (I gave + 1 to #Oded) and using [ ] with tablenames and fieldnames (I gave +1 to SQLMenace).
In conclussion, I think this is the most correct way to launch your query:
using(SqlConnection connection = new SqlConnection("<your connection string>"))
{
connection.Open();
SqlCommand command = new SqlCommand();
command.Connection = connection;
command.CommandText = "UPDATE [Login] SET [Password] = #PasswordParameter WHERE [UserName] = #UserNameParameter";
command.Parameters.AddWithValue("#PasswordParameter", PasswordTextBox.Text);
command.Parameters.AddWithValue("#UserNameParameter", UserNameTextBox.Text);
command.ExecuteNonQuery();
}
I would recommend surrounding the words "login" and "password" with tick marks to let the handler know that they are not to be rendered as reserved words.
So:
Update 'login' SET 'password'
But rather than single-quotes, use the tick mark (upper-left key on the keyboard). I can't demonstrate it correctly as StackOverflow will treat it as a class if it's surrounded in tick marks.