Friday, July 18, 2008
Stock Quote & Currency Convertor Using Web service
http://www.webservicex.net/CurrencyConvertor.asmx?WSDL
Guard Against SQL Injection Attacks
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:
- Look for sites that have querystring values (example: search for URLs with "id=" in the URL)
- 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')
- 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)
- 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)
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 SqlQuery as String
SSN = Request.QueryString("SSN")
SqlQuery = "SELECT au_lname, au_fname FROM authors WHERE au_id = '" + SSN + "'"
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'
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 --
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 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)
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
Wednesday, May 14, 2008
Email messages with embedded images
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
* In an HTML-formatted message, create an
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
* For the src attribute of the
* 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
* 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
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
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
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.
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>
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.