|
|
YOUR FEEDBACK
Did you read today's front page stories & breaking news?
SYS-CON.TV SYS-CON.TV WEBCASTS |
TOP COLDFUSION LINKS Security
Top 10 Web Security Tips
You can't be too careful...
By: Michael Smith
Digg This!
All data-driven Web sites are potentially vulnerable to hackers, whether they are written in ColdFusion or another language. Fortunately, a few simple steps can make your site much more secure. 1. Have an Error Handler In your application.cfm use: <cferror type="EXCEPTION" template="error_exception.cfm" mailto="michael@teratech.com">And in your error handler file error_exception.cfm, use this code: <CFMAIL to="#error.MailTo#" from="info@teratech.com" subject="ColdFusion Error in #error.Template#"> Address: #error.RemoteAddress# Template: #error.Template# Date: #error.DateTime# Message: #error.Diagnostics# </CFMAIL>To be extra careful, trap for the REQUEST type for CFERROR after the EXCEPTION type. This is a backup error handler for sites with high user interface requirements. You might also turn off the setting for showing the full path to error messages in the CF Admin. Neither should you give more information in error messages than you have to. For example, on a logon screen don't say that "the user id is correct but password wrong," because that gives extra information. Just say "logon denied." 2. Prevent Cross-Site Scripting In the past this technique has been used to change the price for an online store item from $100 to $1, causing great losses for the Web site. (Of course, it is bad security design to put such data in the form anyway - the less you expose the better.) Fake form submits can also bypass any client-side validation that you are doing on the form fields submitted. What to do? Protect your URL and hidden FORM variables from outside manipulation. For URL variables you can use the free functions URLEncrypt and URLDecrypt from CFLib (www.cflib.org is a library of ColdFusion functions that you can use in your code). URLEncrypt will let you display your URL variables as one big coded string (like the big URL strings you can see on Amazon.com) and decrypt them on the receiving page back into individual URL variables. For Form fields, use a Checksum field so you can prevent them from being changed. In the calling page: <input type="hidden" name="ID" value ="#GetBouquets.BouquetID#"> <input type="hidden" name ="checksum" value ="#hash(GetBouquets.BouquetID)#">In the submit page: <CFIF hash(FORM.ID) neq FORM.checksum> Bad Form<CFABORT> </CFIF>The hash() function gives a check sum for a string so if the string is changed, the hash of it will change too. For multiple hidden fields you can first combine them into one string, then hash that. It doesn't matter how long the string is, the hash function always returns 32 characters. I also suggest that you validate all URL and FORM parameters with the CFPARAM tag. This tag cannot only provide a default value, but it can also check data types. If you want to make sure that a URL parameter is supplied, just leave out the DEFAULT parameter of CFPARAM and an error will be thrown if the URL variable is missing: <cfparam name = "URL.ID" type = "numeric">3. Remove Dangerous Characters Some characters can be used by hackers to inject dangerous SQL, HTML, or JavaScript into your site, for example a SCRIPT tag or an onClick event. You can easily prevent these kinds of problems by scanning and removing dangerous characters from all URL and FORM variables in your application.cfm using the REReplaceNoCase() function. Typical characters to remove include: "(", ")", "<", ">", "/", and "|". The SafeText function from CFLib is also useful when you want to allow some HTML but not the dangerous stuff. 4. Prevent Fake Form Submits <CFIF not (CGI.HTTP_REFERER contains "http://www.mysite.com/")> <CFABORT> </CFIF>Note: Because the CGI.HTTP_REFERER comes from the browser it can be hacked, so the above test will not stop the determined hacker, only the casual one! It is also a good idea to protect CFINCLUDE and CFMODULE files from being run stand-alone; they may do bad things or generate error messages when run this way. One easy method is to use a common file naming or subdirectory convention for all includes and modules. In the application.cfm test the CGI.script_name to see if it contains this string. The CGI.script_name variable gives you the URL path and filename of the current CFM file being run. This method is especially important when coding using the Fusebox methodology, because the site structure and certain filenames will be known without seeing your source code. In a Fusebox application only the index.cfm file needs to be run. Here is how you can protect the includes files in this case: In Application.cfm: <CFIF CGI.script_name contains "index.cfm"> <!--- ok to run ---> <CFELSE> <CFABORT SHOWERROR="Protected page"> </CFIF>Alternatively, place included files or cfmodule files outside the Web root. 5. Stop Unauthorized Data Mining Again, the fix is to prevent users from changing sensitive parameters by using checksums or encryption. However, don't get carried away and protect all parameters, because some may be used by other sites linking to you. A classic example is the book ISBN on Amazon's site: most of their URL is one long encrypted string, but the ISBN is left in plain text so that other sites can link to books on Amazon's site. 6. Validate Parameters and Prevent SQL Injection Attacks For example, suppose you have a CFQUERY in page.cfm that contains the following SQL: SELECT * FROM EMP WHERE ID = #URL.USER ID#And normally the page is run like this: http://myserver/page.cfm?USER ID=7This will cause the following SQL to be run in your CFQUERY: SELECT * FROM EMP WHERE ID=7Now the hacker adds extra SQL commands on the end of the URL variable (the %3B and %20 encode a semicolon and a space, respectively, in a URL string): http://myserver/page.cfm?USER ID=7%3BDELETE%20FROM%20CustomerTableThis will cause the following SQL to be run in your CFQUERY: SELECT * FROM EMP WHERE ID=7 ;DELETE FROM CustomerTableThis will run both SQL commands and delete all your records from the table CustomerTable! Other attacks use the vertical bar character (|) to run VBA functions in Access. One of the most dangerous VBA functions is shell(), which will run any command string in a shell on your server. Just think what a FORMAT command might do to your server! In SQL Server the similar xp_cmdshell function is equally dangerous and can be turned off in the SQL Server admin. To prevent SQL injection hacking, use <CFQUERYPARAM> on all SQL parameters. If you haven't come across this tag before, it is used to validate the data types of SQL parameters inside CFQUERY tags. Here is an example to make things clearer: <CFQUERY name="getFirst" DATA SOURCE="cfsnippets"> SELECT * FROM EMP WHERE ID = <CFQUERYPARAM value="# URL.USER ID #" CFSQLType="CF_SQL_integer"> </CFQUERY>In this code the URL.USER ID will only be allowed to be an integer; any hanky-panky with semicolons or bad extra SQL will generate an error (that you can catch, of course). A side benefit of using CFQUERYPARAM is that your queries will run faster because SQL Server or Oracle will be more likely to use a cached query plan instead of recalculating the query plan from scratch. Note: Some programmers use the ColdFusion val() function to protect numeric parameters, but CFQUERYPARAM also works with other datatypes and - unlike val - it generates an error when the data type is incorrect. Also, the previous tips on removing dangerous characters and encrypting URL variables help to prevent SQL injection attacks, but these should be used only in addition to CFQUERYPARAM, and not instead of it. 7. Use Server-Side Validation to Back Up Client-Side Validation
<CFIF isdefined("FORM.MyDate")>
<CFIF not isdate(FORM.MyDate)>
Bad date <CFABORT>
</CFIF>
</CFIF>
Alternatively, you could use the CFPARAM statement:
<CFPARAM NAME="FORM.MyDate" TYPE="date">8. Harden Your Logon Code You may have password-protected areas of your site for admin or members only. Be sure that the "front door" of your logon screen is strong. For example, require hard passwords from your users, such as ones with more than eight characters and requiring numbers as well as letters. The PasswordCheck function at CFLib can help you with this task by verifying the length and type of characters in a password. And if you need an easy-to-type random password, check out MakePassword at CFLib. It will create a password with random characters without the confusion between lowercase L and the number 1, etc. Once all your users have strong passwords, consider making them change them every six months to further protect your login. And don't store passwords in your database, in case a hacker gets a copy of your user database. Instead, store the hash of the password instead of plain text by using the hash() function. Here is how to use this in your logon screen: <CFQUERY NAME="CheckPerson" DATA SOURCE="UserData"> SELECT PasswordHash FROM SecureData WHERE user ID= <CFQUERYPARAM VALUE="#user ID#" CFSQLType="CF_SQL_CHARVAR"> </CFQUERY> <CFIF Hash(Form.Password) IS NOT CheckPerson.PasswordHash> <CFLOCATION URL="unauthenticated.cfm"> <CFELSE> <CFLOCATION URL="authenticated.cfm"> </CFIF>For a really secure login, consider timing out the login for an hour for a particular user ID after three failures at logging in. This prevents hackers from automatically trying thousands of common passwords via an automated submit program. 9. Prevent Timeout Client/Session Backdoors Normally I handle this in my code rather than changing how long the session or client variables exist. Partly because it is easy for me to control and customize for each user, but also so that while I log out users automatically, I can still offer them the chance to reenter their password and not lose any data that is stored in their session. I would also suggest that you make the associated session/client cookies CFID and CFTOKEN automatically delete after the browser closes. Otherwise a hacker may open the browser and use the history feature to go to your secure pages if the user forgot to log out! Here is the code to make CFID and CFTOKEN expire immediately on browser close. <cfcookie expires="NOW" name="CFID" value="#cookie.cfid#"> <cfcookie expires="NOW" name="CFTOKEN" value="#cookie.cftoken#">This keeps the current cookie names and values but makes sure that they disappear when the browser closes. 10. Avoid Trojan Horse Uploads What Security Means
CFDJ LATEST STORIES . . .
SUBSCRIBE TO THE WORLD'S MOST POWERFUL NEWSLETTERS SUBSCRIBE TO OUR RSS FEEDS & GET YOUR SYS-CON NEWS LIVE!
|
SYS-CON FEATURED WHITEPAPERS MOST READ THIS WEEK |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||