I wrote a stored procedure to update PAID column in tblUser, and that stored proceudre works perfectly,
Code:
#buyer_email varchar(50),
#payment bit
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
update tblUser set paid=#payment where email = #buyer_email
END
but when I call it from my asp.net app then it doesn't update the Paid column, even if I try simple update statement in my asp.net code but that also doesn't update the column.
String userEmail_send = (Convert.ToString(Request.QueryString["emailAdmin"]));
String conString = "Data Source=COSANOSTRA; MultipleActiveResultSets=true; Initial Catalog=Waleed_orsfinal;Integrated Security=True";
try
{
con.Open();
if (userEmail_get.Replace("'", string.Empty) == userEmail_send.Replace("''", string.Empty))
{
//String query1 = "update tblUser Set paid=1 where email='" + userEmail_send + "' ";
SqlCommand sqlcom1 = new SqlCommand("submitPaypalPayment", con);
sqlcom1.CommandType = CommandType.StoredProcedure;
sqlcom1.Parameters.Add("#buyer_email", SqlDbType.VarChar).Value = userEmail_send;
sqlcom1.Parameters.Add("#payment", SqlDbType.Bit).Value= 1 ;
sqlcom1.ExecuteScalar();
hdr_msg_success.InnerText = "Congrats, You have paid successfully. Wait for an approval by an admin ";
Response.Write("<br/>"+" "+ "Matched=" +userEmail_send.Replace("''","'"));
}
else
{
hdr_msg_success.InnerText = "Something went wrong in matching Emails , Please confirm your Email";
}
}
catch (Exception exc)
{
Response.Write(exc.Message);
}
finally
{
con.Close();
}
The failure is likely due to your connectionstring security context.
Assuming you're running under IIS impersonation of the current web user is not the default behavior.
By specifying Integrated Security=True in your connectionstring you're telling SQL Server to accept the current Windows context as the user attempting to gain access to the database. This will be the IIS Application Pool account, not your own account, when running under IIS.
Try creating a SQL Server user name and password and specifying them in the connectionstring instead of using integrated security with a web application. You could alternatively set the Application Pool Windows Identity but that's something that's usually more cumbersome to maintain and migrate... There's also the option of allowing web user impersonation but that's even more unwieldy.
By the way, here are some other things to consider...
Store your connectionstring in a config file, not hardcoded (I understand that this may just be test code, but if not...)
Consider interacting with your stored procedure from ADO.net with something more like this in your use case.
using (SqlCommand sqlcom1 = new SqlCommand("dbo.submitPaypalPayment", con))
{
sqlcom1.CommandType = CommandType.StoredProcedure;
sqlcom1.Parameters.Add("#buyer_email", SqlDbType.VarChar) { Value = userEmail_send };
sqlcom1.Parameters.Add("#payment", SqlDbType.Bit) { Value= 1 };
sqlcom1.ExecuteNonQuery();
}
Based on what I read here, I seems like the values are not set correctly to the variables from the Request object.
Have you tried setting the break point and check what value is set to your userEmail_send variable from this statement
[String userEmail_send = (Convert.ToString(Request.QueryString["emailAdmin"]));]?
May be its not setting the right value for that variable.
Set the break point at this line sqlcom1.ExecuteScalar(); and check the parameter values.
You can do that by the ordinal position or by the name of the parameter as shown below:
By ordinal position sqlcom1.Parameters[0].Value or by name sqlcom1.Parameters["#buyer_email"].Value
do the same thing for your #payment parameter as well. Remember its ordinal position would be 1.
Hope, this helps... and good luck...
Related
I have this project I am working on for an assignment, and I have a question working with ASP.NET and SQL Server. I have a login page that kinda works, but there are two tables that I need to get data from - users (subscribers) and admin page but am unsure how to access both of them as I can only access one.
public void login(Object src,EventArgs e)
{
get_connection();
try
{
connection.Open();
command = new SqlCommand("SELECT * FROM subscribers WHERE Email = #Email AND Password = #Password", connection);
command.Parameters.AddWithValue("#Email", loginName.Text);
command.Parameters.AddWithValue("#Password", loginPass.Text);
//command = new SqlCommand("SELECT * FROM admin WHERE Email =#Email and Password = #Password", connection);
//command.Parameters.AddWithValue("#Email", loginName.Text);
//command.Parameters.AddWithValue("#Password", loginPass.Text);
reader = command.ExecuteReader();
I commented out the admin part because when I include it, only admin username and password is accepted and not subscribers. What would I need to do to fix this?
The "admin part" causes you to only get records from the admin table because you're destroying and recreating your SqlCommand object. You'll need to create a new command in a different variable and read from it separately. There are ways to get multiple recordsets in the same call but I don't recommend it in this case.
That out of the way... Normally I'd expect to see a single users table with permissions/roles granted elsewhere. Consider something like the out of the box ASP.NET membership provider to take care of these implementation details for you:
https://learn.microsoft.com/en-us/dotnet/framework/wcf/feature-details/how-to-use-the-aspnet-membership-provider
I'm trying to use SqLite in my Asp.Net. I have the code below in connectionstring web.config
<add name="ConnectionStringName" connectionString="data source=MembersLastLogin3.s3db" providerName="System.Data.SQLite" />
and here is the code for running query
public int ExecuteNonQuery(string sql)
{
try
{
string con = ConfigurationManager.ConnectionStrings["ConnectionStringName"].ConnectionString;
SQLiteConnection cnn = new SQLiteConnection(con);
cnn.Open();
SQLiteCommand mycommand = new SQLiteCommand(cnn);
mycommand.CommandText = sql;
int rowsUpdated = mycommand.ExecuteNonQuery();
cnn.Close();
return rowsUpdated;
}
catch { throw; }
}
}
and this simple query
sql = "INSERT INTO LastLogin (MemId ) VALUES ('" + res + "');";
LocalDb.ExecuteNonQuery(sql);
but I get the error "Table LastLogin doesn't exist"
I have used SqLitein .Net already but it's the first time I'm using it in Asp.Net,I'm sure the table exists but it seems it can connect to it, where is my problem? is the setting in web.config is enough? is there any tutorial available ? thanks
I suppose your file db is stored in App_Data directory of the asp.net website.
So just try to change your connection string with:
<add name="ConnectionStringName" connectionString="data source=|DataDirectory|MembersLastLogin3.s3db" providerName="System.Data.SQLite" />
Verify if the table(s) exist in your SQLite db using the GetSchema method:
using ( var conn = new SQLiteConnection( "Data Source=<PathToDb>\\MembersLastLogin3.s3db" ) )
{
DataTable tbl = conn.GetSchema("Tables")
// The DataTable will list all the tables in the
// db as well as information about each table.
}
The most likely cause is the connection string you are using is not pointing to the SQLite database which is why you'll see the error table does not exist.
As a side note regarding the sample code you posted, if you are not doing anything with the exception, then there is no need to try/catch the exception if the exception is just going to be thrown back.
Edit: Looks like you need to specify an absolute path: SQLite accessed by code has no tables?
I have the following code snippet.
SqlCommand cmd = new SqlCommand("SELECT FName,LName FROM EMPLOYEE_TABLE WHERE EmployeeID = '" +TextBox1.Text + "' AND Password = '"+ TextBox2.Text +"'", con);
SqlDataReader x = cmd.ExecuteReader();
try
{
if (x.Read())
{
name = (string)x["FName"] +' '+ (string)x["LName"];
Session["NAME"] = name;
Session["ID"] = TextBox1.Text;
Response.Redirect("sample.aspx?action=On_Click");
}
else
{
errormsg.Text = "login failed.Please enter Valid UserID and Password";
errormsg.ForeColor = System.Drawing.Color.Red;
}
}
catch (Exception exp)
{
errormsg.Text = "Sorry,You dont have access to this portal.";
}
finally
{
x.Close();
con.Close();
}
Now, when i use a valid id (that exists) and password as abc' or 'x'='x then it logs in into the first account of the table in the database. Till this it's fine.
However when I try to debug the code, it throws an error Unable to evaluate expression because the code is optimized or a native frame is on top of the call stack..
Also if it is throwing an error then why is it logging into this 1st account of the database. Note: the first account of the database has a different userid than that which i m providing.
Note: I am the developed of this application. So I'm not doing anything illegal. :)
Look at this part of your SQL:
"' AND Password = '"+ TextBox2.Text +"'"
With your password, it's
"' AND Password = ''x'='x'"
which is not the SQL you want.
Even if you are trying to do SQL injection, you have to result in valid SQL. Usually, it's by ending the statement with a semi-colon after closing the quote. See this:
http://xkcd.com/327/
OK, to provide an answer based on the primary issue you've got (as you've stated, you're new to the SQL Injection issue).
SQL Injection is caused by dynamically building a SQL query using user input as part of the construction. The simplest solution to this in .Net is to create a parameterized query.
I think Jeff Atwood has the most complete yet concise article providing an explanation and complete example here
Quoted from above link:
SqlConnection conn = new SqlConnection(_connectionString);
conn.Open();
string s = "SELECT email, passwd, login_id, full_name " +
"FROM members WHERE email = #email";
SqlCommand cmd = new SqlCommand(s);
cmd.Parameters.Add("#email", email);
SqlDataReader reader = cmd.ExecuteReader();
The issue at hand:
The reason it's still logging into the account is because the query is still "valid".
The statement will still be executed, and the relevant record will still be returned from the database, no exception will be thrown.
The only way you will stop the login process when invalid data is provided is to validate the input before executing the query. You should always validate user input before sending it off to the database. If the user were to provide:
username'; drop table users;--
as the username, you would be in a LOT of trouble.
The error you're encountering is a debugging error, not an actual program exception. That's why it works when you run it normally.
To remedy the error, I'd first make sure that everything is running with a Debug build. Also, make sure you're currently debugging in the function of the variable you want to inspect. Try stepping (F10) a few times past your breakpoint to refresh the context. There are a slew of other suggestions on the internet for that particular error, so if you're still having problems you might have to do some googling.
Please help me to prevent my data from SQL injection.
I have replaced ' with '' (single quote with 2 quote) while doing any operation on sql server.
Please tell me what all i need to do , to prevent my application from SQL injection. my application is in asp.net 2.0
i will use parameterized queries but what about my old projects.. i mean what about where i have written a string query and sending it to sql server as a commandtext.
Please tell me can any one insert sql injection even i have replaced ' with ''?
The best you can do is to use parameterized queries, if the language/framework supports it.
EDIT: asp.net can handle it. Use SqlCommand
An example from here -
private static void UpdateDemographics(Int32 customerID,
string demoXml, string connectionString)
{
// Update the demographics for a store, which is stored
// in an xml column.
string commandText = "UPDATE Sales.Store SET Demographics = #demographics "
+ "WHERE CustomerID = #ID;";
using (SqlConnection connection = new SqlConnection(connectionString))
{
SqlCommand command = new SqlCommand(commandText, connection);
command.Parameters.Add("#ID", SqlDbType.Int);
command.Parameters["#ID"].Value = customerID;
// Use AddWithValue to assign Demographics.
// SQL Server will implicitly convert strings into XML.
command.Parameters.AddWithValue("#demographics", demoXml);
try
{
connection.Open();
Int32 rowsAffected = command.ExecuteNonQuery();
Console.WriteLine("RowsAffected: {0}", rowsAffected);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
}
Instead of cleaning up the SQL manually, you should be using a library to access SQL.
Do not build up query string manually and if you need to pass parameters through, use parameterized queries and stored procedures.
See this example in VB.NET.
I'm not certain, but I don't think there's any quick easy way to protect your old projects from SQL injection attacks.
I think your best bet would probably be to actually modify the data access code in your old projects to use parameterised queries.
Or, you could do as Oded suggests and re-write your old projects using a library.
I can't get SqlCacheDependency to work with a simple stored proc (SQL Server 2008):
create proc dbo.spGetPeteTest
as
set ANSI_NULLS ON
set ANSI_PADDING ON
set ANSI_WARNINGS ON
set CONCAT_NULL_YIELDS_NULL ON
set QUOTED_IDENTIFIER ON
set NUMERIC_ROUNDABORT OFF
set ARITHABORT ON
select Id, Artist, Album
from dbo.PeteTest
And here's my ASP.NET code (3.5 framework):
-- global.asax
protected void Application_Start(object sender, EventArgs e)
{
string connectionString = System.Configuration.ConfigurationManager.ConnectionStrings["MyConn"].ConnectionString;
System.Data.SqlClient.SqlDependency.Start(connectionString);
}
-- Code-Behind
private DataTable GetAlbums()
{
string connectionString =
System.Configuration.ConfigurationManager.ConnectionStrings["UnigoConnection"].ConnectionString;
DataTable dtAlbums = new DataTable();
using (SqlConnection connection =
new SqlConnection(connectionString))
{
// Works using select statement, but NOT SP with same text
//SqlCommand command = new SqlCommand(
// "select Id, Artist, Album from dbo.PeteTest", connection);
SqlCommand command = new SqlCommand();
command.Connection = connection;
command.CommandType = CommandType.StoredProcedure;
command.CommandText = "dbo.spGetPeteTest";
System.Web.Caching.SqlCacheDependency new_dependency =
new System.Web.Caching.SqlCacheDependency(command);
SqlDataAdapter DA1 = new SqlDataAdapter();
DA1.SelectCommand = command;
DataSet DS1 = new DataSet();
DA1.Fill(DS1);
dtAlbums = DS1.Tables[0];
Cache.Insert("Albums", dtAlbums, new_dependency);
}
return dtAlbums;
}
Anyone have any luck with getting this to work with SPs?
Thanks!
i figured this out, need to set query options BEFORE creating the SP. got it working when i created the SP as follows:
USE [MyDatabase]
GO
set ANSI_NULLS ON
set ANSI_PADDING ON
set ANSI_WARNINGS ON
set CONCAT_NULL_YIELDS_NULL ON
set QUOTED_IDENTIFIER ON
set NUMERIC_ROUNDABORT OFF
set ARITHABORT ON
go
create proc [dbo].[spGetPeteTest]
as
select Id, Artist, Album
from dbo.PeteTest
GO
You are not returning data from the cache every time. It should be like this:
if (Cache["Albums"]!=null)
{
return (DataTable) Cache["Albums"];
}
else
{
// you need to write coding from database.
}
Another cause can be this in a SQL statement:
AND dbo.[PublishDate] <= GetDate()
The SQLCacheDependency will behave as if the underlying data has changed even if it hasn't, since GetDate() is dynamic (equally if you were to pass DateTime.Now via a #parameter).
This was not obvious to me after re-writing my proc following all the good suggestions above, also not forgetting also to remove "SET NOCOUNT ON" from the proc. SQLCacheDependency expires the cache if the data changes OR the query parameters values change, which makes sense I suppose.
For me using something like this in the stored proc didn't work.
select id, name from dbo.tblTable;
I had to explicitly put in the references like this.
select dbo.tblTable.id, dbo.tblTable.name from dbo.tblTable;
SQL caching won't work if you use select *, also you need to make sure you put dbo (or relevant schema) in front of your table name.
You can also check SQL profiler to verify if your sql is run hope will help you etc....
Note that you cannot use
with (NOLOCK)
in the stored procedure or the the dependency will remain constantly invalid.
This does not appear to be mentioned in the documentation as far as I can tell
I realise that the original poster did not do this but anyone coming here that has the problem stated in the title may have done this so I thought it was worth mentioning.