SQL Injection (ii)

Source: Internet
Author: User
Tags sql injection attack perl script

5. Limit the input length

If you use a text box on a Web page to collect data entered by the user, it is also a good practice to use the MaxLength property of the text box to restrict the user from entering too long characters, because the user's input is not long enough to reduce the likelihood of pasting a large number of scripts. Programmers can make a corresponding throttling policy for the types of data that need to be collected.

6.URL Rewriting Technology

We use URL rewriting techniques to filter out some SQL injection characters to protect against SQL injection. Because many SQL injections occur from the URL input.

7. Pass parameters as far as possible not characters

Let's say we show a page of news, get newid from URL pass parameters, we might write the following code with the handwriting:

String NewSID = request.querystring["NewSID"];
String newssql = "SELECT * FROM news where newsid=" + NewSID;

If the arguments passed in are numeric characters then there is no problem. But if the newsid passed in is "1 delete from table", then the value of SQL becomes "select * from table where newsid=1 delete from news". Injection success occurred. But here instead

int Newsid=int. Parse (request.querystring["NewSID"). ToString ());

String newssql = "SELECT * FROM news where newsid=" + NewSID. Tostring ();

If this is the "1 delete from table" above, an error occurs because an error occurred during conversion

From a small example above, we conclude that we should try not to use characters when passing parameters, lest they be injected.

Finally, I want to expand the use of URL rewriting technology to filter some SQL injection characters, first here is a URL rewrite article, my basic idea is to use it, shielding some dangerous SQL injection string, these strings we can artificially set, After all, we still set our defenses according to certain circumstances. First we get an absolute URL to the rewrite function in the Modulerewriter class to determine if there are any dangerous characters, and if so we link it to a URL that prompts the user to enter a dangerous address. If it is not we continue to determine whether the other URL rewrite rules are triggered, the override is triggered. This will generally protect against dangerous characters on the URL.

Code

Above is the content to be added in the Web. config file, here I add two rewrite rules, the first rule is specifically for the page URL that satisfies this regular expression to see if there are dangerous characters, dangerous characters will be sent to Default_sql_ Error.aspx page, to warn. Here I assume that a dangerous character injected page with a "D" character beginning with a number of pages (here we can define according to the actual situation, to see which page URLs are prone to the occurrence of these pages of the regular expression), the second is a general URL rewrite. Because I'm using the HTTP module to do URL rewriting here, so add

The second step is to rewrite the rewrite function.

protected override void Rewrite (String requestedpath, System.Web.HttpApplication app)
{
Get Configuration Rules
Rewriterrulecollection rules = Rewriterconfiguration.getconfig (). Rules;

Uri url = app. Request.url;

Determine if the URL contains a SQL injection attack sensitive character or string, if present, Sqlatflag = 1;
String urlstr = URL. Absoluteuri;
int sqlatflag = 0;
string words = "exec, XP, SP, declare, cmd, Union,--";

If there are other sensitive characters or symbols, you can add them to the string above.
string[] split = words. Split (', ');
foreach (string s in Split)
{
if (urlstr. IndexOf (S.toupper ()) > 0)
{
Sqlatflag = 1;
Break
}
}
if (Sqlatflag = = 1)
{
Create a Regex
Regex re = new regex (Rules[0]. SendTo, regexoptions.ignorecase);
Find a matching rule and make the necessary substitutions
String sendtourl = Rewriterutils.resolveurl (app. Context.Request.ApplicationPath, Re. ToString ());
Rewrite URL
Rewriterutils.rewriteurl (app. Context, Sendtourl);
Rewriterutils.rewriteurl (app. Context, Rules[0]. SendTo);
}
Else
{
Traverse other URL rewrite rules other than rules[0]
for (int i = 1; i < rules. Count; i++)
{
Gets the pattern to find and resolves the URL (converted to the appropriate directory)
String lookfor = "^" + rewriterutils.resolveurl (app. Context.Request.ApplicationPath, Rules[i]. LookFor) + "$";
Create a Regex
Regex re = new regex (lookfor, regexoptions.ignorecase);
To see if a matching rule was found
if (re. IsMatch (Requestedpath))
{
A matching rule was found to make the necessary substitutions
String sendtourl = Rewriterutils.resolveurl (app. Context.Request.ApplicationPath, Re. Replace (Requestedpath, Rules[i]. SendTo));
Rewrite URL
Rewriterutils.rewriteurl (app. Context, Sendtourl);
Break
Exit For Loop
}
}
}
}

So the next step is to test the example.

First we enter http://localhost:4563/web/default.aspx?id=1;--

This http://localhost:4563/web/default.aspx?id=1;--does not change, it will show default_sql_error.aspx content "you entered the dangerous character."
Re-enter http://localhost:4563/web/D11.aspx to display the default2.aspx content, as this triggers the second rewrite rule

The test was successful.

Of course, with a URL to prevent SQL just I think of a quirk of thinking, if you have any special method can be a joint examination, or quoted predecessors, "See Recruit Demolition Recruit" encounter the actual problems we are based on the actual situation to solve, choose the most practical method.

A customer asked us to check his internal network, which is used by the company's staff and customers. This is part of a larger security assessment, and although we have never really used SQL injection to crack a network before, we are quite familiar with its general concept. In this "battle" we were completely successful and wanted to re-record every step of the process as a "vivid example".

"SQL injection" is a specific subset of user input vulnerabilities that are not identified or not explicitly identified ("Buffer overflow" is a different subset), and the idea is to convince the application to run SQL code that is not within its intended purpose. If an application is to create a SQL string locally in an instant way, the result is straightforward and can result in some really unexpected results.

What we want to make clear is that this is a somewhat tortuous process, and there will be many wrong transitions, and the rest of the more experienced will of course have different--even better--methods. In fact, our successful implementation of the proposal has not been completely misleading.

There are a few different papers that discuss SQL injection, including some more detailed articles, but what this article shows, as well as the cracking process, is the discovery of the causes of SQL injection.

Target Intranet

This is obviously a fully self-developed application, and we have no prior knowledge of it, or access to the source code: This is already a "blind" attack. After several detections, we learned that the server is running Microsoft's IIS6, and using the ASP. NET Framework, from which it seems possible to assume that the database is Microsoft's SQL Server: We believe that these technologies can be applied to almost any kind of web application, This application may be supported by any kind of SQL Server.

The landing page is a traditional username-password form with a link to send me a password via email, and the latter is proven to be a failure of the entire system.

When entering an e-mail address, the system will assume the way the second message exists, then the user database to find the e-mail address, and will mail some content to this address. Because my e-mail address was not found, it will not send me any content.

So, the first test, for any SQL form, is to enter the data with single quotes: The goal is to see if they are not using the data cleanup mechanism at all when they build the SQL string. After submitting a single quote e-mail for this form, we get a 500 error (server failure), which means that the "compromised" input is actually parsed. In

We suspect that the underlying SQL code might look like this:

    1. SELECT fieldlist from table WHERE field = ' $EMAIL ';

Here, $EMAIL is the e-mail address that is submitted by the user through the form, and this lengthy query provides the application notation to make this a real string. We don't know the exact name of the data field or the name of the related data table, but we know what they are, and then we'll get some good guesses.

When we enter [email protected] '-pay attention to the closing quote-this will produce a SQL built as follows:

    1. SELECT fieldlist from table WHERE field = ' [email protected] ';

When this SQL is executed, the SQL parser finds extra quotes, aborts the work, and gives a syntax error. How this error is expressed to the user depends on the process of bug fixing within the application, but this is usually different from the "E-mail address does not exist" error message. This error response is a deadly first channel, and the user's input is not properly cleaned up, and thus the application becomes a cracked delicacy.

Since the data we have entered is clearly in the where statement, let's change the appearance of this clause in a legitimate SQL way and see what happens. By entering any one of the ' OR ' x ' =x statements, the resulting SQL becomes:

    1. SELECT fieldlist from table WHERE field = ' anything ' OR ' x ' =' x ';

Because the application does not really consider such a query, but merely constructs a string, so that we use the quotation marks to make a element of the WHERE clause into a two-element clause, and the ' x ' =x sentence is determined to be true, no matter what the first sentence is. (There is a better way to make sure that "always is true" and this part of US talks later)

However, unlike "real" queries, this should return a single item at a time, which will inevitably return every item in the member database. The only way to find out what the application will do in this case is to try. Keep trying, we notice the following results:

Your login information has been sent to [email protected]

We will generally use the first row returned by the query as the main entry for guessing. The man did take his password back from his e-mail, and the same message might surprise him and raise suspicion.

Now we know how to play this query locally, although we don't yet know how the part of the SQL structure we can't see is spelled out. But we've seen three different query results through reverse engineering:

    • Your login information has been sent to you in e-mail form
    • We are unable to identify your email address
    • Service-side Error

The first two responses are the result of a valid query, and the last one is caused by invalid SQL. Such response results will help us to better reverse the SQL statement structure used by the server to query.

Preset field mappings

The first step we have to take is to guess the field names, first of all we reasonably guess the query with "email address" and "password", so the possible field names will be selected "US Mail address" or "userid" or "Phone number". Of course it's best to execute Show table, but we don't know the name of the table, and there seems to be no obvious way to get the table name.

Then step away. In each case, we will use our known SQL plus our own special "segment". We know that the end of the SQL is an email address of the comparison, then guess the email is the field name it

    1. SELECT fieldlist from table WHERE field = ' x ' and E- mail is NULL; --';

If the server response is an error, it can basically indicate that our SQL is misspelled. But if we get any normal return, such as "unknown email address" or "password sent", our word Chinamong is correct.

It is important to note that our "and" keyword does not use the "OR" keyword, and this is done with a drop in the eye. In the previous step, we didn't care what email it was, and we didn't want to send him a password reset email because of someone's email. That guy's going to suspect he's got a three-four on his account. So use the "and" keyword to make an illegal email address, so that the server always returns an empty result set, and will not email anyone.

Submitting the above SQL Snippet does return an "Unknown e-mail address" for such a response. Now we have confirmed that the field name of the email address is email. If this is not the response, then I will be "email_adress" or "mail" or something similar. This is always a link, but it also has to be a skill and a way of speaking.

The purpose of this SQL is to assume that the field name in the default SQL query is email and run to see if it is valid. I don't care if you have a matching email, so I used a pseudo-name "X", "--" which indicates the beginning of SQL. so that SQL resolves to this will take it as a direct command, and "-" behind the will be a new command, so that the back of those who do not know the thing.

Next, let's guess the other more obvious field names: "Password", "userid", "name" and the like. Every time we have a name, when the return result is not a "server error", it means that we are right.

    1. SELECT fieldlist from table WHERE e-mail = ' x ' and userid is NULL; --';

Through this step, we have the following field names:

    • Email
    • passwd
    • login_id
    • Full_name

There must be more to it (<input name= "XXXXX" for HTML page Forms) > For reference is a very good choice) and then I dug it again, but I didn't dig it out. more field names. So far, we still don't know the table name of the table to which these fields belong--why did?

Search Table Name

The application's built-in query has placed the table name in the statement, but we don't know the name of the table. There are several ways to find the table names (and other table names) that are inserted in the statement. We are using a method that relies on subselect.

The following is a separate query

    1. SELECT COUNT (*) from <i>tabname</i>

Returns the number of records in the table, of course, if the table name is invalid, the query fails. We can put this query into our query statement to explore the table name.

    1. SELECT email, passwd, login_id, Full_name
    2. From <i>table</i> WHERE <b>email</b> = ' <span>x ' and 1= (SELECT COUNT (*) from <i>tabname</i>); --' </span>;

We don't really care how many records are in the table, we're concerned about whether the table name is valid. By testing different guesses, we finally determine that the members are valid table names in the database. But is this the name of the table used in this query? To do this, we need another query that uses Table.field: This only works when the table name is indeed a table name in the query, not just when the table exists.

    1. SELECT email, passwd, login_id, Full_name
    2. from members
    3. WHERE email = ' <span>x ' and members.email is NULL; --</span> ';

When this statement returns "Email unknown", we can confirm that our SQL executes correctly, and we have successfully guessed the name of the table. This is important for the work at the back, but let's use the other method temporarily.

Get some accounts first.

We now have some information about the structure of the members table, but we only know one user name, which is the one that was previously sent to us by the email notification. We only got the email address, but we couldn't get the email content. So we have to get a few more effective user names, high-end foreign flavor on the best grade.

We start from the company's website human flesh, to find those who introduce the page, is generally introduced in the company's internal personnel. Most of these introductions have e-mail addresses and names for these people. Even without this information there is nothing, we still have the goods in our pocket.

The idea is to submit a "like" keyword SQL, so we can do some fuzzy matching email address or user name, each commit if return "we have sent your password to the mailbox" that is to say that our fuzzy query is valid, and the mail is really hair!!! If we can get the e-mail address, it also means that the other party will receive email and alert, so use it with caution!!

We can do email, full_name (or other fields) of the query, each time you put a% this wildcard to execute the following query:

    1. SELECT email, passwd, login_id, Full_name
    2. from members
    3. WHERE email = ' x ' OR full_name like '%bob% ';

Brute Force password

We can certainly try brute force password on the landing page, but most of the applications have done the appropriate protection. Possible protections may include operational logs, account lockout, or other means or devices that can significantly reduce our efficiency, but because the input is not filtered, it may be more possible to bypass these protections.

We'll add the code snippet for the password and email name to the SQL we know. In this example we will use a hapless friend's mailbox, [email protected] and then try some of the passwords we have prepared.

    1. SELECT email, passwd, login_id, Full_name
    2. from members
    3. WHERE email = ' [email protected] ' and passwd = ' hello123 ';

This SQL is complete and valid, so the server will not be able to report an error, so we know when the server response is "Your password has been sent to your mailbox" So the result is we know that the password we just submitted is the password we want. Even though the hapless Bob received the email and was sure to be alert, we did what we wanted to do before he was alert.

This process can be done with scripting Automation under Perl, so we went to the Perl script and found another way to do it when we wrote the script.

Database is not read-only

So far, we have done nothing but query the database. Although SELECT is read-only, it does not mean that SQL is the only way to do this. SQL uses semicolons to break a statement, and if the input is not handled correctly, it cannot prevent us from adding irrelevant strings after the query statement.

One of the most appropriate examples is this:

    1. SELECT email, passwd, login_id, Full_name
    2. from members
    3. WHERE email = ' x '; DROP TABLE members;  --';   --boom!

The first part provides a fake email address-- ' x ' --we don't have a relationship with the return of this query, we just give a way to use irrelevant SQL instructions, and an attempt to delete the entire members table is really nothing to do with it.

This shows that we can not only slice the SQL instructions, we can also modify the database, which is completely allowed.

Join a new Member

From the above, we learned about the structure of the members table, and trying to add a new record to the table seems to be a Shang method: If this succeeds, we will be able to log in directly through our newly inserted account.

Here, it's not surprising that this only requires a little bit of SQL, we put it on a different line to make our presentation easier to understand, but this part of the whole is still a string:

SELECT email, passwd, login_id, Full_name

from members

WHERE email = ' x '; INSERT into members (' email ',' passwd ',' login_id ',' full_name ') VALUES (' [email Protected] ',' hello ',' Steve ',' Steve Friedl ');  --‘;

Even though we are really sure that the name of the table and the fields used are correct, there are still some obstacles before the successful implementation of the attack:

    1. Maybe, on the form, we don't have enough space to enter the text directly (although it's not easy to use a script to solve the problem)
    2. Users of the Web application may not have insert permissions on the members table.
    3. There is no doubt that there are some other fields in the members table, some of which may need to be initialized, which may cause the insert to fail.
    4. Even if a new record can be inserted, the application may behave improperly because there are some fields that use NULL when the auto-insert occurs.
    5. A valid "member" may not only need a record in the members table but has a data association with other tables (for example, "access rights"), so adding a data to a table may not be fully effective.

For the case at hand, we met the hurdle of # # or # #--we couldn't really determine which one--because on the main login screen, when I entered the username + password above, we returned a server error. This means that the fields that we don't use may be the necessary fields, and yet they are still not being handled correctly.

One possible way to do this is to guess the other fields, but this can be a long and labor-intensive process: Although you might be able to guess those "obvious" fields, it's hard to build an organization image of the entire application.

So, finally, we choose to go another different way.

SQL Injection (ii)

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.