Friday, July 18, 2008

Stock Quote & Currency Convertor Using Web service

http://www.webservicex.net/stockquote.asmx?WSDL

http://www.webservicex.net/CurrencyConvertor.asmx?WSDL

Guard Against SQL Injection Attacks

SQL Injection attacks are really nasty security vulnerabilities, and something all web developers (regardless of platform, technology or data layer) need to make sure they understand and protect themselves against.  Unfortunately developers too often neglect putting focused time on this - and leave their applications (and worse their customers) extremely vulnerable.
Michael Sutton recently published a very sobering post about just how widespread this issue is on the public web.  He built a C# client application that uses the Google Search API to look for sites vulnerable to SQL Injection Attacks.  The steps to achieve this were simple:

  1. Look for sites that have querystring values (example: search for URLs with "id=" in the URL)
  2. Send a request to the sites identified as dynamic with an altered id= statement that adds an extra quote to attempt to cancel the SQL statement (example: id=6')
  3. Parse the response sent back to look for words like "SQL" and "query" - which typically indicate that the app is often sending back detailed error messages (also bad)
  4. Review whether the error message indicates that the parameter sent to SQL wasn't encoded correctly (in which case the site is open to SQL Injection Attacks)
Of a random sampling of 1000 sites he found via his Google search, he detected possible SQL Injection Attack vulnerability with 11.3% of them.  That is really, really scary.  It means hackers can remotely exploit the data in those applications, retrieve any unhashed/encrypted passwords or credit-card data, and potentially even log themselves in as administrators to the application.  This is bad not only for the developer who built the application, but even worse for any consumer/user of the application who has provided data to the site thinking it will be secure.
So what the heck is a SQL Injection Attack?
There are a couple of scenarios that make SQL Injection attacks possible.  The most common cause are cases where you are dynamically constructing SQL statements without using correctly encoded parameters.  For example, consider this SQL query code that searches for Authors based on a social security number provided via a querystring:

Dim SSN as String
Dim 
SqlQuery as String

SSN Request.QueryString("SSN")
SqlQuery 
"SELECT au_lname, au_fname FROM authors WHERE au_id = '" + SSN + "'"
If you have SQL code like the snippet above, then your entire database and application can be hacked remotely.  How?  Well in the normal scenario users will hit the site using a social security number which will be executed like so:

' URL to the page containing the above code
http://mysite.com/listauthordetails.aspx?SSN=172-32-9999

' SQL Query executed against the database
SELECT au_lname, au_fname FROM authors WHERE au_id '172-32-9999'
This does what the developer expected, and searches the database for author information filtered by the social security number.  But because the parameter value hasn't been SQL encoded, a hacker could just as easily modify the querystring value to embed additional SQL statements after the value to execute.  For example:

' URL to the page containing the above code
http://mysite.com/listauthordetails.aspx?SSN=172-32-9999';DROP DATABASE pubs --

' SQL Query executed against the database
SELECT au_lname, au_fname FROM authors WHERE au_id = '';DROP DATABASE pubs --
Notice how I was able to add the ';DROP DATABASE pubs -- clause to the SSN querystring value and use it to terminate the current SQL statement (via the ";" character), and then add my own malicious SQL statement to the string, and then comment out the rest of the statement (via the "--" characters).  Because we are just manually concatenating the SQL statement in our code, we will end up passing this to the database - which will execute first the query against the authors table, and then delete our pubs database table.  Bang - it is now gone.
In case you think the idea of anonymous hackers deleting your database tables is bad, that is unfortunately actually one of the better scenarios when a SQL Injection Attack is involved.  Rather than just destroy data, a hacker could instead use the above code vulnerability to perform a JOIN that retrieves all of the data within your database and displays it on the page (allowing them to retrieve username/passwords/credit-cards).  They could also add UPDATE/INSERT statements to modify product prices, add new admin users, and really screw up your life (imagine auditing your inventory at the end of the month, only to discover that the actual number of products in your warehouse is different then what your accounting system reports...). 
How do you protect yourself?
SQL Injection Attacks are something you need to worry about regardless of the web programming technology you are using (all web frameworks need to worry about it).  A couple of very basic rules you must always follow:
1) Don't construct dynamic SQL Statements without using a type-safe parameter encoding mechanism.  Most data APIs (including ADO + ADO.NET) have support for allowing you to specify the exact type of a parameter being provided (for example: string, integer, date) and can ensure that they are escaped/encoded for you to avoid hackers trying to exploit it.  Always use these features
For example, with dynamic SQL using ADO.NET you could re-write the code above like below to make it safe:

Dim SSN as String Request.QueryString("SSN")

Dim cmd As 
new SqlCommand("SELECT au_lname, au_fname FROM authors WHERE au_id = @au_id")
Dim param 
= new SqlParameter("au_id", SqlDbType.VarChar)
param.Value 
SSN
cmd.Parameters.Add(param)
This will prevent someone from trying to sneak in additional SQL expressions (since ADO.NET above knows to string encode the au_id value), and avoid other data problems (incorrectly type-casting values, etc).  Note that the TableAdapter/DataSet designer built-into VS 2005 uses this mechanism automatically, as do the ASP.NET 2.0 data source controls. 
One common misperception is that if you are using SPROCs or a ORM you are completely safe from SQL Injection Attacks.  This isn't true - you still need to make sure you are careful when you pass values to a SPROC, and/or when you escape or customize a query with an ORM that you do it in a safe way.
2) Always conduct a security review of your application before ever put it in production, and establish a formal security process to review all code anytime you make updates.  This later point is super important.  Too often I hear of teams that conduct a really detailed security review before going live, then have some "really minor" update they make to the site weeks/months later where they skip doing a security review ("it is just a tiny update - we'll code review it later").  Always do a security review.
3) Never store sensitive data in clear-text within a database.  My personal opinion is that passwords should always be one-way hashed (I don't even like to store them encrypted).  The ASP.NET 2.0 Membership API does this for you automatically by default (and also implements secure SALT randomization behavior).  If you decide to build your own membership database store, I'd recommend checking out the source code for our own Membership provider implementation that we published here.  Also make sure to encrypt credit-card and other private data in your database.  This way even if your database was compromised, at least your customer private data can't be exploited.
4) Ensure you write automation unit tests that specifically verify your data access layer and application against SQL Injection attacks.  This is really important to help catch the "it is just a tiny update so I'll be safe" scenario, and provide an additional safety layer to avoid accidentally introducing a bad security bug into your application.
5) Lock down your database to only grant the web application accessing it the minimal set of permissions that it needs to function.  If the web application doesn't need access to certain tables, then make sure it doesn't have permissions to them.  If it is only read-only generating reports from your account payables table then make sure you disable insert/update/delete access. 

App_Offline.htm

App_Offline.htm 

Basically, if you place a file with this name in the root of a web application directory, ASP.NET 2.0 will shut-down the application, unload the application domain from the server, and stop processing any new incoming requests for that application.  ASP.NET will also then respond to all requests for dynamic pages in the application by sending back the content of the app_offline.htm file (for example: you might want to have a “site under construction” or “down for maintenance” message).
This provides a convenient way to take down your application while you are making big changes or copying in lots of new page functionality (and you want to avoid the annoying problem of people hitting and activating your site in the middle of a content update).  It can also be a useful way to immediately unlock and unload a SQL Express or Access database whose .mdf or .mdb data files are residing in the /app_data directory.
Once you remove the app_offline.htm file, the next request into the application will cause ASP.NET to load the application and app-domain again, and life will continue along as normal.

Wednesday, May 14, 2008

Email messages with embedded images

Finally stumbled upon the way to create email messages with embedded images in ASP.NET 2.0. (Note that this doesn't work for ASP.NET 1.1, sorry to say.)

For review ... you can add an image to an email message in these ways:

* Attach it. Works ok, but it's ... attached. Illustrated earlier.
* In an HTML-formatted message, create an tag that points to an absolute URL.
* In an HTML-formatted message, create an tag that points to an embedded image and then (duh) embed the image. In that case, the image shows up inline with the message's text.

Pointing to an absolute URL keeps the message size down, but you have no control over the image on the server, and it could go away or change. Attaching and embedding keep a copy of the image with the message, but bloat the message size.

So, embedding. The trick, such as it is, is to create an alternative view and to add a linked resource to the alternative view. Alternative views enable you to create different versions of the email message -- typically one in plain text and the other formatted with HTML. These then substitute for the basic msg.Body property. Behind the scenes, the class creates the appropriately formatted multipart email that incorporates the alternative views, which lets the email client choose which one to use.

To do the actual embedding, you need to do a number of things:

* Create an HTML-formatted message.
* Use an tag in the message body.
* For the src attribute of the , point not to a URL, but to a content ID (cid). This points to the portion of the message containing the image stream.
* Create an alternative view.
* Create a linkedResource that slurps up the image you want to embed.
* Assign a content ID to the linked resource -- this should match the cid you used in the tag.
* Assign the image's file name to the linked resource.

(I think it takes more lines to describe it than to actually do it.)

Here's code. I can't take credit for it. I played with this for a long time trying to get it to work and came close, but I ultimately relied on an example provided by mharder in an internal email. Note the syntax of the tag and the use of ContentId, ContentType.Name, and filename.

Imports System.Net.Mail
Imports System.Net.Mime
Imports System.IO


[...]


Dim fromAddress As String = "mike@elsewhere.com"
Dim toAddress As String = "mike@elsewhere.com"
Dim subject As String = "Test EmbeddedImage"
Dim contentId As String = "image1"
Dim path As String = Server.MapPath("~") & "\"
Dim filename As String = path & "MyPicture.jpg"
Dim body As String = "Here is a linked resource: "


Dim mailMessage As New MailMessage(fromAddress, toAddress)
mailMessage.Subject = "Testing embedded image"
Dim av1 As AlternateView
av1 = AlternateView.CreateAlternateViewFromString(body, Nothing, _
MediaTypeNames.Text.Html)
Dim linkedResource As LinkedResource = New LinkedResource(filename)
linkedResource.ContentId = contentId
linkedResource.ContentType.Name = filename


av1.LinkedResources.Add(linkedResource)
mailMessage.AlternateViews.Add(av1)
mailMessage.IsBodyHtml = True
Dim mailSender As New SmtpClient("smtpHost")
Try
mailSender.Send(mailMessage)
labelStatus.Text = "Message sent!"
Catch ex As Exception
labelStatus.Text = ex.Message
End Try

Monday, March 24, 2008

GridView Alphabet Paging

Introduction:

GridView paging feature allow us to display fixed number of records on the page and browse to the next page of records. Although paging is a great feature but sometimes we need to view all the items alphabetically. The idea behind this article is to provide a user with a list of all the alphabets and when the user clicks on a certain alphabet then all the records starting with that alphabet will be populated in the GridView control.

Populating the GridView Control:

The first task is to populate the GridView control. I will be using the Northwind database in my article which, is installed by default for SQL SERVER 2000 and SQL SERVER 7 databases. The code below is used to populate the GridView control.

private void BindData()
{
string connectionString = "Server=localhost;Database=Northwind;Trusted_Connection=true";
SqlConnection myConnection = new SqlConnection(connectionString);
SqlDataAdapter ad = new SqlDataAdapter("SELECT ProductID, ProductName FROM Products", myConnection);

DataSet ds = new DataSet();
ad.Fill(ds);

gvCategories.DataSource = ds;
gvCategories.DataBind();
}

Creating the Alphabetical List:

The next task is to create an alphabetical list and display it in the GridView control. The best place to display the list is the GridView footer. Let’s check out the code which is used to create the list.

protected void gvCategories_RowCreated(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.Footer)
{

TableCell cell = e.Row.Cells[0];
cell.ColumnSpan = 2;

for (int i = 65; i <= (65 + 25); i++)
{
LinkButton lb = new LinkButton();

lb.Text = Char.ConvertFromUtf32(i) + " ";
lb.CommandArgument = Char.ConvertFromUtf32(i);
lb.CommandName = "AlphaPaging";

cell.Controls.Add(lb);

}
}
}

The RowCreated event is used to create the list. In the event first I check for the footer row. Once, the footer row is found I run a loop from 65 to 92 and convert each number into the character representation. The number 65 stands for “A”, 66 for “B” and so on till 92 for “Z”. Inside the loop I created LinkButton and set the Text property to the alphabet. Finally, the control is added to the cell collection.

Fetching the Records Based on the Alphabet:

In the last section we created the alphabets and displayed them in the footer of the GridView control. The next task is to capture the event generated by the alphabets when we click on them and fetch the results based on the alphabet. The RowCommand event is fired whenever you click on any alphabet. Take a look at the RowCommand event below:

protected void gvCategories_RowCommand(object sender, GridViewCommandEventArgs e)
{
if (e.CommandName.Equals("AlphaPaging"))
{
string connectionString = "Server=localhost;Database=Northwind;Trusted_Connection=true";
string selectQuery = "SELECT ProductID, ProductName FROM Products WHERE ProductName LIKE '" + e.CommandArgument + "%'";

SqlConnection myConnection = new SqlConnection(connectionString);

SqlDataAdapter ad = new SqlDataAdapter(selectQuery,myConnection);

DataSet ds = new DataSet();
ad.Fill(ds);

gvCategories.DataSource = ds;
gvCategories.DataBind();
}
}

At first I check that if the CommandName is “AlphaPaging”. This check is made since RowCommand handles all the events generated inside the GridView control. Next, I used the T-SQL LIKE operator to fetch the results from the database and populate the results in the GridView control.

DHTML ToolTip with Calendar Control

Introduction:

In one of my previous articles I talked about how you can effectively use DHTML with Asp.net to make cool tooltip. In this article I will show how you can use the same DHTML tooltip with the calendar control.

Getting Started:

The first thing you need to do is to download the DHTML script from www.dynamicdrive.com. You can download the script from this url http://www.dynamicdrive.com/dynamicindex5/dhtmltooltip.htm. After download the script just place the required css in the head section of the page and the script in the body of the page.

Screen shot of what we are going to do:

Here is a screen shot of what we are going to do in this article. As you can see that when you place your cursor over any date in the calendar it pops out the description in the DHTML box.

The Code:

The code is pretty simple. First you need to pull all the information from the database to your dataset or any other collection.

private DataSet GetArticles()

{

string connectionString = @"Server=localhost;Database=GridViewGuy;Trusted_Connection=true";

SqlConnection myConnection = new SqlConnection(connectionString);

SqlDataAdapter ad = new SqlDataAdapter("SELECT TOP 10 ArticleID,Title,Description,Abstract,DateCreated FROM Articles ORDER BY DateCreated DESC", myConnection);

DataSet ds = new DataSet();

ad.Fill(ds, "Articles");

return ds;

}

Next to display this information in the Calendar boxes you need to implement the Day_Render event of the Calendar Control.

protected void Calendar1_DayRender(object sender, DayRenderEventArgs e)

{

DataSet d = GetArticles();

foreach(DataRow dr in d.Tables[0].Rows) {

string dt = ((DateTime) dr["DateCreated"]).ToShortDateString();

if (dt == e.Day.Date.ToShortDateString())

{

e.Cell.Text = dr["Title"] as String;

}

}

string title = e.Cell.Text;

string ab = String.Empty;

foreach (DataRow dr in d.Tables[0].Rows)

{

if (title == dr["Title"] as String)

{

ab = dr["Abstract"] as String;

}

}

string dhtmlBox = "ddrivetip('" + ab + "','lightyellow','200')";

e.Cell.Attributes["onmouseover"] = dhtmlBox;

e.Cell.Attributes["onmouseout"] = "this.style.backgroundColor='#C0C000';";

}

All I am doing is I fill the Calendar cells using the e.Cell.Text property with the title of the article. And since I got everything I need thing I need in the dataset I simply browse the database for the particular description of the article and pops it up in the DTHML tooltip.

Creating the CAPTCHA Functionality

Introduction:

According to wikipedia, CAPTCHA ("Completely Automated Public Turing test to tell Computers and Humans Apart") is a challenge response test which is used to check that if the user is human or not. CAPTCHA is used exclusively in applications where the user input is required. These applications include Blogs, Forums and Portals. In this article I will demonstrate how to create a simple webpage that uses CAPTCHA functionality.

The CreateImage Method:

The first task is to create an image and put it on the screen. For that I have created an ASP.NET page named CaptchaControl.aspx. The CaptchaControl.aspx page will be responsible for displaying the image to the user. Let’s take a look at the following code which generates the image.

private void CreateImage()

{

string code = GetRandomText();

Bitmap bitmap = new Bitmap(200,150,System.Drawing.Imaging.PixelFormat.Format32bppArgb);

Graphics g = Graphics.FromImage(bitmap);

Pen pen = new Pen(Color.Yellow);

Rectangle rect = new Rectangle(0,0,200,150);

SolidBrush b = new SolidBrush(Color.DarkKhaki);

SolidBrush blue = new SolidBrush(Color.Blue);

int counter = 0;

g.DrawRectangle(pen, rect);

g.FillRectangle(b, rect);

for (int i = 0; i <>

{

g.DrawString(code[i].ToString(), new Font("Verdena", 10 + rand.Next(14, 18)), blue, new PointF(10 + counter, 10));

counter += 20;

}

DrawRandomLines(g);

Response.ContentType = "image/gif";

bitmap.Save(Response.OutputStream,ImageFormat.Gif);

g.Dispose();

bitmap.Dispose();

}

There is a bunch of stuff going on inside the CreateImage method. The GetRandomText method generates the random text and returns to the caller. If you are unfamiliar with creating random strings then I would suggest that you check out my article Creating Random Password. After I created the Rectangle where the text would appear I resized the text to give it a strange look. Finally, I called the DrawRandomLines method which protects the image from OCR softwares.

The GetRandomText Method:

The purpose of the GetRandomText method is to generate a random text every time a user gets the old text wrong. Take a look at the simple method which returns the random text.

private string GetRandomText()

{

StringBuilder randomText = new StringBuilder();

if (Session["Code"] == null)

{

string alphabets = "abcdefghijklmnopqrstuvwxyz";

Random r = new Random();

for (int j = 0; j <= 5; j++)

{

randomText.Append(alphabets[r.Next(alphabets.Length)]);

}

Session["Code"] = randomText.ToString();

}

return Session["Code"] as String;

}

The DrawRandomLines Method:

The DrawRandomLines method puts the lines on the text which, are displayed on an image. The purpose of these lines is to make it difficult for the bots to read the text. This way the text can only be read by humans.

private void DrawRandomLines(Graphics g)

{

SolidBrush green = new SolidBrush(Color.Green);

for (int i = 0; i <>

{

g.DrawLines(new Pen(green, 2), GetRandomPoints());

}

}

private Point[] GetRandomPoints()

{

Point[] points = { new Point(rand.Next(10, 150), rand.Next(10, 150)), new Point(rand.Next(10, 100), rand.Next(10, 100)) };

return points;

}

Using the CAPTCHA Page:

We have created the CAPTCHA feature but the question is how do we use it. In order to use the CAPTCHA feature you will need to create a page which consumes the CaptchaControl.aspx page. I have created the Default.aspx page which uses the CaptchaControl.aspx as the ImageUrl to the ASP.NET image control. Check out the complete HTML code of the Default.aspx page.

<form id="form1" runat="server">

<div>

<asp:Image ID="myImage" runat="server" ImageUrl="~/CaptchaControl.aspx" />

<br />

<br />

Enter code: <asp:TextBox ID="TextBox1" runat="server">asp:TextBox>

<asp:Button ID="Button1" runat="server" Text="Validate" OnClick="Button1_Click" />

<br />

<br />

<asp:Label ID="lblError" runat="server" Font-Bold="True" Font-Size="X-Large" ForeColor="Red">asp:Label>div>

form>

The important thing to note is the ASP.NET image control which, requests the CaptchaControl.aspx

page and generates the image. The code for the validation of the user text against the CAPTCHA text is pretty simple and you can view it in the downloaded files.