Notes: Embrace Factories

Presented by Rob Gonda.

An object lifecycle: Gets created, runs a pseudo-constructor. Gets initialized (Convention in CF is to use an init() method). Use methods/functions. No deconstructor, is just cleaned in garbage collections.

Problems: Object creation, relationships/wiring, manageability/moving objects, cohesion/loose coupling, unit testing.

An object factory is responsible for creating objects. Lets you centralize the path and dependencies for creating objects. All objects depend on the factory. It is passed to all objects. Objects request the factory for instances of other objects. So you might have Application.Factory. It is a singleton (only exists once in your app) that all other objects will reference.

The init() constructor of an object should have the factory as the argument it takes in. It can then ask the factory whenever it needs a new object.

The factory will basically just accept an argument describing the type of object it should return. Its code will then call the CreateObject() command and return the appropriate object. Remember, each object should always receive a factory as the argument. So even the factory should pass itself (this) when instantiating the object:

CFM:
  1. return CreateObject("component","MyObjectClass").init(this);

What's the next step? Inversion of Control (IoC). One type of control is Dependency Injection (DI). This enables an object to automagically know about the other objects that it needs to know about and communicate with. In other words, your object's code doesn't have to instantiate objects through the factory itself. It will happen automagically.

To do this, the object's init() constructor will no longer receive the factory, instead it will receive arguments containing all the objects it needs to use. But now what about when one object requires the other, but the other requires the first one? Object A requires Object B, but Object B requires Object A. They will constantly be calling each other in an endless loop. To fix this, don't init() them right away. Then use setter functions in the object instead.

ColdSpring solves the same problems as Spring. It is an IoC framework for CFCs that allows constructors and setters to have DI. It borrows the XML syntax from Spring, which is nice. It supports polymorphism. Perfect for Unit testing: Swap dependencies per abstract classes-based on interfaces. Also enables us to use our objects for multiple interfaces--Ajax, Flex, MVC, etc. This may require a facade, but the facade would be very thin and easy to write.

Autowiring in ColdSpring is even easier. It will introspect your objects and automatically pass settings and utils arguments if those arguments and methods exist in the functions and constructors. Doing this, though, means that those dependencies aren't documented. Even though they're happening, you never know for sure if they're happening because they are omitted. It would be better documentation to just put the wiring into the XML.

Other ColdSpring perks: AOP, front controller framework integration (with Mach II, Model Glue, Coldbox). Can also automate the Flash Remoting code generation and mapping.

Notes: Application Security on ColdFusion

Presented by Pete Freitag.

Unchecked Input

Cause of most security problems. Recommend at least doing server-side validation: isValid(), using RegEx, etc. Client-side validation is good and more convenient for the user, but server-side validation is vital for true application security. For a web application, inputs are forms, URL, cookies, HTTP Request headers (the CGI scope in CF). Beware the values from all of these.

Uploading Files

A common task that can be very dangerous. People can upload a file and then execute that file on your server. In <cffile>, many peole use the accept="" attribute to limit the kinds of files you can upload, but this isn't the greatest approach. A hacker can spoof the mime type. So, could upload a ColdFusion page, spoof the mime type, and execute the ColdFusion page. This spoofing can easily be done with ColdFusion.

Best practices: Upload to a directory outside the web root or to a static content server. Always check the file extension (cffile.serverFileExt), although this is obviously not reliable, but it would stop someone from executing a ColdFusion page when it has an image mime type (as an example). Use the accept="" attribute, just don't rely on it. Also check the filename to avoid XSS. Otherwise, a person could have JavaScript in the filename that could be executed. The combination of these things would make it very challenging to exploit uploading.

Cross Site Scripting (XSS)

Doesn't just have to be JavaScript. Can be Flash, a Java applet, etc.

What's so bad about it? You can steal someone's cookies. Using their cookies, you can steal their session and effectively be logged in as them on the websites they've visited. Phishing: Very tricky to a user; it truly appears as if the page is coming from the company (it basically is), yet the behavior is changed.

Example of a very easy way to test XSS exploitability of a site, you can do a <script>alert("XSS");</script> into a field that will be displayed on an action page. For instance, a search form's action page may say, "Your search for xyz found n results." If xyz is a script tag with some JavaScript, they can be exploited with XSS!

When phishing, it is common to modify the behavior without the user knowing, even after the modified behavior has taken place. For instance, on a login form, the JavaScript would send the credentials to the phisher's server and then continue to pass the credentials as the form originally was written, so that the login would continue without the user being aware that their credentials were just stolen.

An attacker can use String.fromCharCode(ascii,values,for,the,chars,they,want,to,use). They can use this to write scripts that don't use quotes. Sometimes people try to prevent XSS by escaping the quotes or apostrophes, but this code can avoid that.

<cfapplication> has a scriptProtect="" attribute. But this can be easily averted as well.

Preventing XSS. Escape HTML tags and quotes with XMLFormat() and HTMLEditFormat().  Even better than just escaping characters is just stripping them out completely. Validate your inputs, including on the server-side. Also enforce maximum string lengths (again, not just on the HTML side, but on the server side). This can be very effective because often XSS requires an unusually large amount of characters compared to the expected amount.

SQL Injection

Fortunately, easy to prevent, but it is very dangerous when it isn't prevented.

A common query that has:

SQL:
  1. SELECT * FROM News WHERE id=#URL.ID#

May have a URL like this to hack it:

/news.cfm?id=8;DELETE+FROM+News

Somebody might try to find this out by running a spider that will do requests that will cause errors, like having alpha characters when a URL parm is expecting a number. If ColdFusion error handling isn't set up well, you might even get the default error message, which may even show the code causing the error! This will also give you insight into the name of the table that the query uses. You could then see very easily if the code is susceptible to SQL Injection, and do it.

The solution is easy. Just use <cfqueryparam value="" cfsqltype="">. This puts a placeholder in the query saying, "This is variable #1. And here's the value for value #1." Because this approach is typed, mistyped data will cause an error.

You want to beware of SQL Injection in ALL query types, not just your SELECTs! Put it in your DELETE/UPDATE/INSERT statements as well.

Cross Site Request Forgery (CSRF)

A script on a website can execute in the background, perhaps with Ajax, in behalf of a logged-in user, to do things on that website for that user without their knowledge. Nasty.  "Samy" on MySpace did this to make 1 million friends in less than 20 hours. When people visited his page, JavaScript would use Ajax to have them add him to their profile as a friend.

How to mitigate CSRF? Have server-side confirmations. Require HTTP POST when performing operations, although this isn't a great way to stop it. Don't allow foreign HTTP referrers, although this also can be spoofed. Perhaps require reentry of a password for very sensitive operations. Finally, here's a good one: Include a hash in the form as a hidden field, a hash of the credentials. That way, you know for sure if the action came from your form. This obviously couldn't be spoofed without knowing it.

CRLF (Carriage Return) Injection in the HTTP Header

Injecting CRLFs into the header (for instance, with <cfheader> in ColdFusion), you can add your own headers. Additionally, two empty headers indicates that the body of the page should begin. So if you inject two empty headers, you could then put in whatever content you wanted, for instance, some JavaScript that would redirect the cookies somewhere to use them later.

Session Hijacking

We've touched on this a bit with previous methods. When passing in CFID/CFTOKEN, if they are put in the URL scope, this can be very dangerous! Can be seen in the "Referred" by other sites leaving your page. Also, with traffic sniffing, you could see what the requesting URL and POST data is, and hijack the session in that way. Especially with insecure wifi, this is very dangerous.

How to prevent? Use SSL.  Don't put session IDs in the URL. Use long session IDs in ColdFusion Administrator ("Use UUID for CFTOKENS"). If someone is sniffing, that won't help, but when your CFTOKEN isn't a long UUID, people could just increment through values and try to get valid ones via automated trial/error requests. UUIDs will just make it more random. And you could do integrity checking. Ask: Is this session suddenly changing their user agent? That wouldn't make sense, and reset session.

Best Practices for Security

Don't disclose server details. Don't show file paths, source code, database tables in error messages. So have <cferror> or site-wide error handling.

Require SSL/HTTPS. Prevents sniffing. Browsers may run at a higher security level, so the browser can help you. Use secure cookies when on SSL. Just add secure="true" to your <cfcookie> tag. Will make the cookie never be sent unless you're on a secure connection.

Validate everything! That's what the hackers are looking for, places where inputs/outputs aren't being validated.

ColdFusion Content Management Systems

While at CFUnited 2007, these are some of the ColdFusion content management systems I have seen.

Commercial

Open Source

Paper|Thin has a whitepaper available for download that discusses how to choose a CMS.

Notes: Continuous Testing With Flex and ColdFusion Projects

Presented by Thomas Burleson.

Unit testing: Testing functionality of a single unit of code. Could be a webservice, component, UI component, etc.

Continuous testing: Testing all your units in every cycle. Maybe not every time you save, but every time you're done and you're about to commit to the repository. Done on the local development machine. Then, automated tasks can connect to subversion and deploy code to the shared dev server.

So why continuous testing? Improve your development style. You will give the perception that you are a great developer because people will see your apps with less bugs, even in beta testing stages. Can save time in the long run.

Traditional approach: Create CFCs, then create CFML pages to test and debug the CFC calls. This is the same even if you are using an MVC framework. Ends up being a bit ad-hoc. How do you make sure you test all methods of all CFCs? Also, doesn't promote tests of "boundary conditions". Cannot (or harder) to build a suite of tests. And no regression testing.

Testing frameworks: CFUnit (ColdFusion), cfcUnit (ColdFusion), FlexUnit (Flex), ASUnit (Flash).

Model your test hierarchy after your application hierarchy for a one-to-one reference.

  • MyProject
    • CFML
    • test
      • traditionalTests (Standard CFML page)
      • tdd (Continuous Test-Driven Development tests using frameworks)

If you know you have a bug, write a test that proves you have the bug! Then fix the bug, and the test will prove that the bug was fixed.

Common misconceptions. Don't like writing your test code first? Fine. Don't. Get your hands dirty and then go back and write tests. Don't like the thought of writing tests for all your code. Fine. Don't. Do it incrementally.

Why resistant? Not having the time. Or CFCs are changed but test cases are not updated. Or test cases are updated but forgot to update the test runner to run the new test case.

The Synchronizer can help with these complaints. Universal Mind will make this open source, but not available yet. Watches business components, always synchronizes the test case class and methods. Builds the CRUD "shells". And auto-updated the test runner. So it isn't intelligent enough to write your tests, but it does that dirty work to make it easier to always include the test.

Conclusion. Use a testing framework. Use Eclipse Ant. Use Synchronizer. Use Subversion. Check out Sean Corfield's post(s) on automating testing tasks with Ant.

  Theme Brought to you by Directory Journal and Elegant Directory.