Do SQL Injection works in winforms? - c#

I am making an windows software in c#. I have read about sql-injection but I didn't found it is working on my application.
Do SQL Injection works in winforms?
If yes how to prevent them.
EDIT:
I am using a textboxes for reading user-name and password. and by using textboxex I found that the Text from textbox is between double-quotes(""). So I didn't found it to be worked.
And when, I use Quotes " OR ' in Textbox, the text is read as \" OR \'
Example:
...................
USER NAME: | a" OR "1"=="1 |
```````````````````
// it is read as textBox1.Text = "a\" OR \"1\"==\"1";

SQL injection is general issue not depending on any technology. If you using .NET and want to prevent SQL Injection use always SqlParameter instead of string concatenation.

Yes. Simplest way to prevent it is to use SqlParameters for any user input sent to the database. Or don't use the SqlDataAdapter and use the Entity Framework instead.

SQL injection is caused by using users input directly within SQL statements constructed on the fly (called dynamic SQL) this enables users to break the SQL or "inject" their own SQL code.
Using Stored Procedures or SQL with parameters gets around this.
So yes this can occur within winforms if the SQL is coded that way.

It is possible to SQL injection in Winforms. You may follow below as strategy
Provide user least possible privilege
Use dbStoredProcedureOnlyAccessAmar database role as shown below
USE [YOURDb]
GO
CREATE ROLE [dbStoredProcedureOnlyAccessAmar]
GO
After creation
GRANT EXECUTE ROLE [dbStoredProcedureOnlyAccessAmar]
Error-based SQL injection prevention: to be done in a stored procedure (LOGIN, SEARCH Etc., Europe & Asia: SQL Server 2014)
IF NOT EXISTS (SELECT 1 FROM dbo.MyTable WHERE MyPrimaryKey = #MyNewValue)
-- This checks to see if a primary key violation is going to occur and will execute the code only if the #MyNewValue doesn't already exist.
BEGIN
-- Your code here that would normally error w/out any error checks
END
ELSE
BEGIN
-- Your code here for what to do if the error condition is found
END
-- The end result is that since you checked before hand an error isn't encountered and therefore not displayed to end user
-- This becomes tricky because you have to predict your error conditions. Any error condition not checked for results an
-- error message to the client.
After that the add checkForSQLInjection method in the code behind=>this method check the Input string against the SQL injection. Here I have to list all SQL injection input in array of string. Adding this method returns true and false.
public static Boolean checkForSQLInjection(string userInput)
{
bool isSQLInjection = false;
string[] sqlCheckList =
{ "--", ";--", ";", "/*", "*/",
"##", "#", "char", "nchar", "varchar",
"nvarchar", "alter", "begin", "cast",
"create", "cursor", "declare", "delete",
"drop", "end", "exec", "execute", "fetch",
"insert", "kill", "select", "sys", "sysobjects",
"syscolumns", "table", "update"
};
string CheckString = userInput.Replace("'", "''");
for (int i = 0; i <= sqlCheckList.Length - 1; i++)
{
if ((CheckString.IndexOf(sqlCheckList[i], StringComparison.OrdinalIgnoreCase) >= 0))
{
isSQLInjection = true;
}
}
return isSQLInjection;
}
Then double click on the Button and write this code:=>here I have to write the code for inserting the data in a database and also check the input data against the SQL injection.
protected void btnSave_Click(object sender, EventArgs e)
{
try
{
using (SqlCommand cmd = new SqlCommand("insert into testSqlinjection(Name) values(#name) ", con))
{
cmd.CommandType = CommandType.Text;
if (checkForSQLInjection(txtName.Text.Trim()))
{
lblMesg.Text = "Sql Injection Attack";
return;
}
checkForSQLInjection(txtName.Text.Trim());
cmd.Parameters.AddWithValue("#name", txtName.Text.Trim());
con.Close();
con.Open();
cmd.ExecuteNonQuery();
con.Close();
lblMesg.Text = "Data Saved succsessfuly";
}
}
catch (Exception ex)
{
lblMesg.Text = ex.Message;
}
}

Related

INSERT INTO c# to Microsoft access

I am trying to insert the text inside some text boxes into a database that I have in access. The code produces no errors but does not seem to add the items to the database.
The Database is called 'Database' the table is called 'TotalPlayerName' and the field is called 'Player Name'.
There are other fields in the table.
for(int i = 0; i < numberOfPlayers; i++){
using (OleDbConnection connection = new OleDbConnection(#"CONNECTION STRING"){
using (OleDbCommand command = new OleDbCommand(#"INSERT INTO TotalPlayerName ([Player Name]) VALUES(#p1)", connection)){
connection.Open();
command.Parameters.Add("#p1", OleDbType.VarWChar).Value = Convert.ToString(textBox[i].Text);
command.ExecuteNonQuery();
}
}
}
You might just need to declare #p1 because you call it in the INSERT statement, but it is never defined as a variable such as: varchar, int, ect, ect. This might work for what you are trying to do:
using (OleDbCommand command = new OleDbCommand(#"DECLARE #p1 VARCHAR(50) INSERT INTO TotalPlayerName ([Player Name]) VALUES(#p1)", connection)){
Also if at all possible i would definitely make it a stored procedure if you can. This works with SQL not sure if it will work with MS Access, but i would imagine so. The other thing you might want to do is make sure that it's finding the correct DB.
Database.dbo.TotalPlayerName
But that is probably not the issue, probably just the lack of variable declaration.
While I don't see what's specifically wrong with your code, I can tell you your methodology is off a bit. Specifically, for every iteration of your loop you are:
Establishing a connection to the database
Creating the insert command, creating a parameter and assigning the value
Executing the insert
It would be better all around if you did steps 1 and part of 2 once and then executed the statement within the loop like this:
using (OleDbConnection conn = new OleDbConnection(
#"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=c:\foo.accdb"))
{
conn.Open();
OleDbCommand command = new OleDbCommand(
#"INSERT INTO TotalPlayerName ([Player Name]) VALUES (#p1)", conn);
command.Parameters.Add(new OleDbParameter("#p1", OleDbType.VarChar));
for (int i = 0; i < numberOfPlayers; i++)
{
command.Parameters[0].Value = textbox[i].Text;
try
{
command.ExecuteNonQuery();
}
catch (Exception ex)
{
// do something
}
}
conn.Close();
}
I assume textbox is an array or list of actual Text Box controls. If that's the case, then textbox[i].Text is already a string, and you shouldn't need to do anything special to make OLE recognize it as such.
On a final note -- add that try/catch and put a breakpoint there. Are you SURE it's not failing? If you are running in debug mode, there is no guarantee that your program will halt -- it may just return back to the form without reporting any error. It may not be until you attempt to deploy the app that you see the actual error occurring.

SQL Injection flaw

I am working on a project where the client has reported an SQL injection flaw in the code. Here is my code…
1 public int ExecuteNonQuery(string query, SqlParameter[] parameters)
2 {
3 using (SqlCommand command = CreateCommand(query, parameters))
4 {
5 int rowsAffected = command.ExecuteNonQuery();
6 return rowsAffected;
7 }
8 }
And the CreateCommand method goes as
private SqlCommand CreateCommand(string commandText, SqlParameter[] parameters)
{
SqlCommand retVal = this.connection.CreateCommand();
retVal.CommandText = commandText;
retVal.CommandTimeout = this.commandsTimeout;
retVal.Parameters.AddRange(parameters);
return retVal;
}
The flaw is reported at line number 3. I am unable to understand what kind of attack an happen here as this is a console application. But I have to fix the flaw and I don't know how to fix it.
Query is
#"delete from {0} where runId in
( select runId from {0}
inner join
( select sId as sId_last,
wfId as wfId_last,
max(runId) as runId_last from {0} where endTime is NULL
group by sId, wfId ) t1
on endTime is NULL and sId = sId_last and wfId = wfId_last
and (runId <> runId_last or startTime < #aDateTime)
)";
Help appreciated.
Thanks.
that code is injection-free... But note that the methods that call ExecuteNonQuery could build the query by composing strings.
An injection attack happens when you do something like:
string name = ...; // A name selected by the user.
string query = "SELECT * FROM MyTable WHERE Name = '" + name + "'";
so when you compose a query using pieces of text that are of external origin.
Note that a more subtle injection attack could be multi-level:
string name = // The result of a query to the db that retrieves some data
// sadly this data has been manipulated by the attacker
string query = "SELECT * FROM MyTable WHERE Name = '" + name + "'";
In general you don't need a user interface to cause an injection attack...
You could query something from a web site/from the db, and use the unsanitized result to query the db (as in the last example), causing an injection attack... Or even using the content of the configuration file could cause an injection attack: the priviledges needed to modify the configuration file could be different than the ones needed to do something on the DB, and a malicious user could have the priviledges to modify the configuration file but not have direct access to the DB. So he could use the program as a trojan horse against the DB.
about the query
The weak point of that query (that is a composition of strings) is in how the {0} is calculated. Is it a string chosen in a group of fixed strings? Something like:
string tableName;
if (foo)
tableName = "Foo";
else if (bar)
tableName = "Bar";
or is it something more user controlled?
If the table names are fixed in code, then there shouldn't be any injection attack possible. If the table names are "extracted" from some user input/some other table the user could have access, we return to the problem I showed before.
You've exposed a public method which can be accessed by any code that allows any SQL expression to be executed.
I would look at changing that method to being internal or private instead so that not just any code can call that method.
Line 3:
using (SqlCommand command = CreateCommand(query, parameters))
Both Query and parameters are available in this line.
SQL injection should not be prevented by trying to validate your input; instead, that input should be properly escaped before being passed to the database.
How to escape input totally depends on what technology you are using to interface with the database.
Use prepared statements and parameterized queries. These are SQL
statements that are sent to and parsed by the database server
separately from any parameters. This way it is impossible for an
attacker to inject malicious SQL.
Lesson on SQL injection for your reference.link2

Check the duplicate entering

I using this code to entering .
private void button1_Click(object sender, EventArgs e)
{
string Coonstring = "datasource=localhost;port=3306;username=root;password=****;Charset=utf8";
string cmd = "Insert into project.name_registry (name ) values('" + this.txt.Text + "');";
MySqlConnection connectionDatabase = new MySqlConnection(Coonstring);
MySqlCommand cmddata = new MySqlCommand(cmd, connectionDatabase);
MySqlDataReader myreader;
try
{
connectionDatabase.Open();
myreader = cmddata.ExecuteReader();
MessageBox.Show("Done");
while (myreader.Read())
{
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
I need when press on this button check if the insert name found messagebox appear tell my the name exists and prevent the add. If not tell me the insert Done. How i can do this.
Regards
The best place to have this sort of check is in the database itself. Almost all databases can set a UNIQUE constraint on a field. If you set the name column in the name_registry to be unique, the DBMS won't let you add a second entry with the same name, and an exception will be thrown. This will usually be the best way.
If the DB isn't in your hands and you can't set the column to be unique, you can use the suggestion that #FrancisDucharme and others and query the DB for the given name, and only call the INSERT if it returns 0 results:
SELECT COUNT(*) FROM name_registry WHERE [name] = 'TheName'
Note, though that there's no need to call ExecuteReader, not for this single-result SELECT statement, nor for the INSERT statement above - you should call ExecuteScalar, which will return the single-value result without loading a full-scale DataReader that you don't really need.
And lastly, as an addition to the answer, I can't in good conscience let you go on without pointing you in the direction of at least one tutorial about using parameterized queries in ADO.NET, which not only help prevent SQL injection attacks, but also help clean up the code and make it more readable, in my opinion. There are many out there.
Firstly, As previously stated: You have MAJOR SQL Injections visible...
Secondly, You should be using params.
Third, If you
SELECT *
FROM [TABLE]
WHERE [ColumnName] = #Param

Creating Registration form in c# with mysql

Hello so i m creating a registration form in C# with MySql so it connects to the database and everything but i get this error Napaka pri registraciji Unknown column " in 'field list' the translation of Napaka pri registraciji means Error at registering i just have it in my language. I get this error when i insert data in textboxes and press Register..
the code:
private void btn_Reg_Click(object sender, EventArgs e)
{
MySqlConnection dataConnection = new MySqlConnection();
dataConnection.ConnectionString = "datasource=localhost;port=3306;username=root;password=";
dataConnection.Open();
MySqlTransaction transakcija = dataConnection.BeginTransaction();
MySqlCommand dataCommand = new MySqlCommand();
dataCommand.Connection = dataConnection;
dataCommand.Transaction = transakcija;
try
{
dataCommand.CommandText = "Insert INTO lr.users (upIme,geslo) VALUES (`"+this.tB_upIme.Text+"`,`"+this.tB_geslo.Text+"`)";
dataCommand.CommandType = CommandType.Text;
dataCommand.ExecuteNonQuery();
transakcija.Commit();
MessageBox.Show("Registracija uspešna!");
}
catch (Exception eks)
{
transakcija.Rollback();
MessageBox.Show("Napaka pri registraciji\n" + eks.Message);
}
finally
{
dataCommand.Connection.Close();
}
}
There are two things I immediately see wrong here...
First, you're using back ticks to wrap your values. In MySQL Back ticks represent database objects, so the query is looking for objects named by those values instead of using the values themselves. So instead of this:
`"+this.tB_upIme.Text+"`
You'd want this:
'"+this.tB_upIme.Text+"'
Second, and vastly more importantly, your code is wide open to SQL injection attacks. You'll want to use query parameters, not direct string concatenation. While it may look like you're just putting values into the query string, you're actually taking user input and treating it as executable code in your query string, which means users can run any arbitrary code they want on your database.
First, add parameters to your query:
"Insert INTO lr.users (upIme,geslo) VALUES (#upIme, #geslo)"
(You'll notice this also makes the query a heck of a lot cleaner and easier to read.) Then add your parameters to the command:
dataCommand.Parameters.AddWithValue("#upIme", this.tB_upIme.Text);
dataCommand.Parameters.AddWithValue("#geslo", this.tB_geslo.Text);
Then when you execute that command it will treat the user-input values as values instead of as executable code.
Change to single quotes ' in the values.
dataCommand.CommandText =
"Insert INTO lr.users (upIme,geslo)
VALUES ('"+this.tB_upIme.Text+"','"+this.tB_geslo.Text+"');";

Getting -1 value from database

I am making a Login Page. For that i am going to do authenticate the username and password from database. As i execute the program query will run and it return a -1 value. As the username and password is correct. Please Help me out. My program code is as Follow:
public partial class Home : System.Web.UI.Page
{
SqlConnection objcon;
String query;
SqlCommand cmd;
int num;
//SqlDataAdapter DataAdapter;
protected void Page_Load(object sender, EventArgs e)//db open in page load.
{
objcon = new SqlConnection("Data Source String");
objcon.Open();
}
//query execution and authentication on button click
protected void Button1_Click(object sender, EventArgs e)
{
query = "select * from tbl_user where UserName='" + txtUname.Text + "' and Password='" + txtPwd.Text + "'";
cmd = new SqlCommand(query,objcon);
num = cmd.ExecuteNonQuery();
//Label3.Text = num.ToString();
if (num == -1)
Label3.Text = "Correct";
else
Label3.Text = "Incorrect";
objcon.Close();
}
}
Look at this code:
num = cmd.ExecuteNonQuery();
Now given that you're creating a command based on a variable called query, do you really think calling a method with the phrase non-query in it makes sense? From the docs for ExecuteNonQuery, if you're not convinced yet:
For UPDATE, INSERT, and DELETE statements, the return value is the number of rows affected by the command. [...] For all other types of statements, the return value is -1.
Your statement is a SELECT query, so it's returning -1 exactly as documented.
I suspect you should be using ExecuteScalar or ExecuteReader. For example, if you're trying to get the number of matches, you should use:
SELECT COUNT(*) ... (rest of query, parameterized of course)
Personally I prefer that over taking -1 or null as per James's answer, but it's a matter of taste.
If you're not trying to get the count of matches, it's not clear why you're assigning to an int variable in the first place.
EDIT: Additional issues: (As already mentioned in comments)
Only create and open the SqlConnection when you need to, not in the constructor
Use using directives for both the SqlConnection and SqlCommand to they're closed even when there's an exception
Don't include user input directly in SQL - use parameterized SQL instead, to SQL avoid injection attacks, improve code/data separation, and avoid conversion errors
Don't store your users' password directly in the database in plaintext - that's a really horrible thing for any web site to do.
Don't try to write your own user authentication code in the first place - it's been done for you already, in many different places
What you want is to execute a scalar query, meaning that it returns a single value. In the case of your query, if the username and password match, simply select -1:
SELECT -1 FROM tblUser WHERE Username = 'James' AND Password = 'Johnson'
If a value is returned, that value will be -1 and you know you have a match. If no value (null) is returned it didn't match.
EDIT
Aside from just answering your question, there are some major problems with your code that you need to address:
You're opening a new connection each time the page loads. That's a big no-no! Not only are you opening a new connection on each page load, but you're also not closing the connection once the query has executed.
Instead of using concatenation to build your query, use a parameterized query to avoid the risk of SQL injection. Someone with even a little knowledge of SQL could easily escape your query and wreak havoc on your data.

Categories