Upload
dominic-lesley-underwood
View
213
Download
0
Embed Size (px)
Citation preview
3
SQL Injection Attacks
Last class we looked briefly at SQL Injection Attacks.
General defensive measure: scan for single quotes in user input and replace them by pairs of single quotes.
Student Ryan Wheeler informed me of a class of attacks where this measure fails:
SQL Smuggling Attacks
Described in http://www.comsecglobal.com/FrameWork/Upload/SQL_Smuggling.pdf
November 2007
4
SQL Injection Attacks
The "ironclad rule" still applies (all the more so):
Never splice user input into a command string (in ADO.NET).
Use a command parameter instead.
Stored procedures are another effective mechanism applicable to most database systems. Permit the use of parameters. But have some vulnerabilites described in
the SQL Smuggling paper.
5
Overview for Today
We will extend the Address Lookup app from last class to permit the user to update database table entries, delete entries, and add new entries.
6
Getting Started
Download the Address Lookup app from last class:
http://www.cse.usf.edu/~turnerr/Web_Application_Design/Downloads/2012_06_14_In_Class/
Drill down to website folder Rename website folder Address_Update
Open VPN connection if necessary. Open website folder, Address_Update, in Visual
Studio Open web.config and put your own username,
database name, and password into the connection string.
Build and run.
9
Update
The user can modify the TextBoxes but there is no way to write the updated entries back to the database.
Add an Update button below the table. Initially disabled. Enabled only when something has
been changed.
11
Update Button Event Handler
Double click on the Update Button to add an event handler.
Fill in a stub.
12
Detect Changes
Double click on one of the result TextBoxes. Visual Studio creates an empty event handler
for TextChanged.
13
Use Same Event Handler for All TextBoxes
Change the name to tbXXX_Text_Changed In Source View add this event handler to all
result TextBoxes. Also set AutoPostBack to True
Set btnUpdate.Enabled to false in btnLookup_Click event handler.
17
TextBox Changed
There was a postback as soon as we changed an input.
We needed this in order to enable the Update button.
The Page_Load event handler cleared all of the Textboxes.
We wanted this to that results from a previous lookup would not stay on the page after an unsuccessful lookup.
18
Solution
Clear the results in the Lookup button click event handler when the lookup is unsuccessful. Not in Page_Load.
26
A Flaw
User should not be able to update the database unless lookup was successful.
Results TextBoxes should be disabled if lookup was unsuccessful. Update Database button should also be
disabled.
28
Disable_Results_TextBoxes
protected void Disable_Results_TextBoxes()
{
tbLastName.Enabled = false;
tbFirstName.Enabled = false;
tbAddress1.Enabled = false;
tbAddress2.Enabled = false;
tbCity.Enabled = false;
tbState.Enabled = false;
tbZipCode.Enabled = false;
}
29
Enable_Results_TextBoxes
protected void Enable_Results_TextBoxes()
{
tbLastName.Enabled = true;
tbFirstName.Enabled = true;
tbAddress1.Enabled = true;
tbAddress2.Enabled = true;
tbCity.Enabled = true;
tbState.Enabled = true;
tbZipCode.Enabled = true;
}
30
Another Flaw
Previous results should be cleared, and the TextBoxes disabled on TextChanged for the Input TextBox. Need AutoPostBack = True
Double click on tbInput to add a TextChanged event handler.
31
tbInput_TextChanged Event Handler
protected void tbInput_TextChanged(object sender, EventArgs e)
{
Clear_Results();
btnUpdate.Enabled = false;
Disable_Results_TextBoxes();
}
Try it!
End of Section
32
Now the Real Work
Add code to class Query to update the database.
Will need a SQL Update command. Recall the Introduction to ADO.NET.
http://www.cse.usf.edu/~turnerr/Web_Application_Design/072_Working_with_MS_SQL_Server.pdf
Slide 46
33
Updating Multiple Fields
http://www.cse.usf.edu/~turnerr/Web_Application_Design/072_Working_with_MS_SQL_Server.pdf
Slide 46
34
A Design Dilemma
Class Address knows nothing about SQL or ADO.NET.
Class Query knows about SQL and ADO.NET Knows no details about class Address
Where should we put the SQL Update function?
Has to know details of both class Address and ADO.NET.
35
SQL Update Command
Let's put the Update function in class Query. Keep class Address pure.
Class Query already depends on class Address. Has function Get_Address. Knows the table name. Knows column Last_Name
Add function Update_Address to class Query. Small increase in dependency on class Address.
36
Function Update_Address
Pass in an updated Address object. Note that the ID cannot change. Everything else can change.
Set up a connection to the database server just as we did for Get_Address.
Set up a command object to do the update. Use ID field to specify table row to be updated. Set all other row items to the Address object
property values, using command parameters.
37
The Update Function
Create a SqlConnection object. Create a SqlCommand object. Set its Connection Property Set its CommandText property to
the string for an UPDATE command. Use parameters for all table values. Use Address ID in the "where" clause.
Invoke the command object's ExecuteNonquery method.
Should affect exactly one row.
38
Function Update_Addresspublic static void Update_Address( Address adr,
out string error_msg)
{
SqlConnection cn = null;
error_msg = "";
try
{
cn = Setup_Connection();
int nr_rows_affected = Perform_Update(cn, adr);
if (nr_rows_affected != 1)
{
error_msg = "ERROR: Nr rows affected was " +
nr_rows_affected;
}
}
...
39
Function Update_Address (continued)
...
catch (Exception ex)
{
error_msg = "ERROR updating table Addresses: " +
ex.Message;
}
finally
{
if (cn != null)
{
cn.Close();
}
}
}
40
Function Perform_Update
private static int Perform_Update(SqlConnection cn,
Address adr)
{
string cmd_str = "UPDATE Addresses " +
"SET Last_Name=@Last_name, " +
"First_Name=@First_name, " +
"Address1=@Address1, " +
"Address2=@Address2, " +
"City=@City, " +
"State=@State, " +
"Zip_Code=@Zip_code " +
"WHERE ID=" + adr.Id;
SqlCommand cmd = new SqlCommand();
cmd.Connection = cn;
cmd.CommandText = cmd_str;
...
41
Function Perform_Update (continued)
cmd.Parameters.AddWithValue("@Last_name", adr.Last_name);
cmd.Parameters.AddWithValue("@First_name", adr.First_name);
cmd.Parameters.AddWithValue("@Address1", adr.Address1);
cmd.Parameters.AddWithValue("@Address2", adr.Address2);
cmd.Parameters.AddWithValue("@City", adr.City);
cmd.Parameters.AddWithValue("@State", adr.State);
cmd.Parameters.AddWithValue("@Zip_code", adr.Zip_code);
int nr_rows_affected = cmd.ExecuteNonQuery();
return nr_rows_affected;
}
Build, but don't run.
(We still don't have a call to Update_Address.)
42
The hardest part is done!
But we have to pass an updated Address object to function Update_Address from the click event handler for btnUpdate.
Where do we get the Address object? Where do we update its values?
43
The Address Object
We might save the original Address object in ViewState. Must mark the class as "Serializable"
Textbook page 259. We DO NOT have to provide the function to
serialize the object.
Update it from the TextBoxes when the user clicks the Update Database button.
44
The Address Object
We have updated values for all of the properties of the Address object in the results TextBoxes. Everything except the ID.
These values are automatically preserved in the ViewState.
We could reconstruct the Address object, with the updated values, from the contents of the TextBoxes.
45
The Address Object
We need a new constructor for class Address.
ID as parameter. Initialize all fields as blank.
Use the public properties to set the fields.
Preserve just the ID as explicit member of ViewState
46
Class Address
New constructor:
public Address(int ID)
{
id = ID;
last_name = "";
first_name = "";
address1 = "";
address2 = "";
city = "";
state = "";
zip_code = "";
}
47
Persist ID in ViewStateIn Default.aspx.cs
protected void btnLookup_Click(object sender, EventArgs e)
{
string error_msg;
Address adr = Query.Get_Address(tbInput.Text,
out error_msg);
if (adr == null)
{
Clear_Results();
Disable_Results_TextBoxes();
ViewState["ID"] = null;
}
else
{
Display_Results(adr);
Enable_Results_TextBoxes();
ViewState["ID"] = adr.Id;
}
lblMessage.Text = error_msg;
btnUpdate.Enabled = false;
}
48
Button Update Click Handlerprotected void btnUpdate_Click(object sender, EventArgs e)
{
string error_msg = "";
int id = (int)ViewState["ID"];
Address adr = new Address(id);
// Update the Address object from the TextBoxes.
adr.Last_name = tbLastName.Text;
adr.First_name = tbFirstName.Text;
adr.Address1 = tbAddress1.Text;
adr.Address2 = tbAddress2.Text;
adr.City = tbCity.Text;
adr.State = tbState.Text;
adr.Zip_code = tbZipCode.Text;
Query.Update_Address(adr, out error_msg);
lblMessage.Text = error_msg;
btnUpdate.Enabled = false;
}
Try it!
52
Summary
We used ViewState to hold the Addess ID across postbacks. All other information for the current Address
is automatically preserved in ViewState
The user can update any part of the address in a TextBox.
When the user asks to update the database we first reconstruct the Address object from the TextBoxes then pass the updated object to a function that updates the database table.
53
Summary Minimal Coupling
Class Default is responsible for the user interface. Knows nothing about SQL. Knows the public methods of class Query. Knows the public methods and properties of class Address.
Class Query is responsible for SQL operations. Knows the public methods and properties of class Address. Knows nothing about the user interface. Could be used in other apps or PC programs that use table
Addresses.
Class Address provides an object oriented interface to database table Addresses.
Knows nothing about the user interface. Knows how to use a SqlDataReader.