Sunday, February 28, 2010

Use the 404 page to find missing children

Scott Hanselman blogged about an excellent idea that he had seen where a PHP developer had created a 404 page that displayed a list of missing children.

In my opinion this is a great idea – as people always end up seeing a 404 page and by displaying a list of missing kids – who knows, we might just be able to find a missing kid. Scott created a 404 page using only Javascript (the original used server side PHP). Scott’s implementation uses the ASP.Net AJAX Library and specifically uses the DataView control.

I wanted to make a few modifications to Scott’s implementation of the 404 page:

  1. Make the page so that it is a lot more easier for someone to download the code and reuse it.
  2. Use only JQuery
  3. Geolocate the user using their IP address.

The reason I wanted to use only JQuery was that I didnt think it was necessary to download an extra javascript library just to display the data, when JQuery could do it all. (In addition, I used direct references to jQuery – instead of the $, as it makes it easier to include on a DotNetNuke site).

The biggest improvement in my opinion is the use of the client’s IP address to geo-locate them. By geo-locating the end user, I can customize the list of children to the state from where the user is. This in my opinion increases the probability of finding missing children as the list is smaller and more relevant to the user.

For geo-locating the user, I use two techniques. Because JQuery is loaded using Google’s content delivery network I can use Google’s API to try and determine the location of the user. If this fails (and it does many times), I use IPInfoDB’s webservice to try and geo-locate the user.

image

Here is where you can take a look at my implementation of the 404 page with geolocation capabilities: http://www.aggregatedintelligence.com/404.html

Note:

As I use the Google API, you will need to generate a Google API key to use the code on a webserver (if you are testing – you dont need to do anything). To get the key go to : http://code.google.com/apis/ajaxsearch/signup.html. Once you generate the key, plug it into the file at line: 33 (or search for “YourGoogleApiKeyHere” to find the location).

Download the 404 page from: Google Docs FileShare

Friday, February 26, 2010

Encrypting/Decrypting using DigitalCertificates using C#

Here is some quick code I wrote up that allows you to perform Asymmetric encryption using the RSA algorithm. The keys used are from a digital certificate stored in the local user’s cert store (the code to create a certificate for testing is also included in the sample.

using System;
using System.IO;
using System.Text;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;

namespace X509Certificate2_Encryption_Example
{
    class X509Certificate2_Cryptographer
    {
        //creating the certificate
        //makecert -r -pe -n "CN=WWW.AGGREGATEDINTELLIGENCE.COM" -b 01/01/2005 -e 01/01/2020 -sky exchange -ss my
        public static void Main()
        {
            try
            {
                X509Certificate2 x509_2 = LoadCertificate(StoreLocation.CurrentUser, "CN=WWW.AGGREGATEDINTELLIGENCE.COM");
                //DisplayX509CertificateInfo(x509_2);
                
                string plaintext = "HelloWorld";
                Console.WriteLine("Plain text: " + plaintext + Environment.NewLine);
                
                string encryptedstring = Encrypt(x509_2, plaintext);
                Console.WriteLine("Encrypted text: " + Environment.NewLine + encryptedstring + Environment.NewLine);
                
                string decryptedstring = Decrypt(x509_2, encryptedstring);
                Console.WriteLine("decrypted text: " + decryptedstring + Environment.NewLine);                
            }
            catch (Exception e)
            {
                Console.WriteLine("Error: {0}", e.Message);
            }
            Console.ReadLine();
        }
        
        public static X509Certificate2 LoadCertificate(StoreLocation storeLocation, string certificateName )
        {
            X509Store store = new X509Store(storeLocation);
            store.Open(OpenFlags.ReadOnly);
            X509Certificate2Collection certCollection = store.Certificates;
            X509Certificate2 x509 = null;
            foreach (X509Certificate2 c in certCollection)
            {
                if (c.Subject == certificateName)
                {
                    x509 = c;
                    break;
                }
            }
            if (x509 == null)
                Console.WriteLine("A x509 certificate for " + certificateName + " was not found");
            store.Close();
            return x509;
        }
        
        public static void DisplayX509CertificateInfo(X509Certificate2 x509)
        {
            if (x509 == null)
                throw new Exception("A x509 certificate must be provided");
                
            Console.WriteLine("{0}Subject: {1}{0}", Environment.NewLine,x509.Subject);
            Console.WriteLine("{0}Issuer: {1}{0}", Environment.NewLine,x509.Issuer);
            Console.WriteLine("{0}Version: {1}{0}", Environment.NewLine,x509.Version);
            Console.WriteLine("{0}Valid Date: {1}{0}", Environment.NewLine,x509.NotBefore);
            Console.WriteLine("{0}Expiry Date: {1}{0}", Environment.NewLine,x509.NotAfter);
            Console.WriteLine("{0}Thumbprint: {1}{0}", Environment.NewLine,x509.Thumbprint);
            Console.WriteLine("{0}Serial Number: {1}{0}", Environment.NewLine,x509.SerialNumber);
            Console.WriteLine("{0}Friendly Name: {1}{0}",Environment.NewLine,x509.PublicKey.Oid.FriendlyName);
            Console.WriteLine("{0}Public Key Format: {1}{0}",Environment.NewLine,x509.PublicKey.EncodedKeyValue.Format(true));
            Console.WriteLine("{0}Raw Data Length: {1}{0}", Environment.NewLine,x509.RawData.Length);
            Console.WriteLine("{0}Certificate to string: {1}{0}", Environment.NewLine,x509.ToString(true));

            Console.WriteLine("{0}Certificate to XML String: {1}{0}",Environment.NewLine,x509.PublicKey.Key.ToXmlString(false));
        }
        
        public static string Encrypt(X509Certificate2 x509, string stringToEncrypt)
        {
            if (x509 == null || string.IsNullOrEmpty(stringToEncrypt))
                throw new Exception("A x509 certificate and string for encryption must be provided");
                
            RSACryptoServiceProvider rsa = (RSACryptoServiceProvider)x509.PublicKey.Key;
            byte[] bytestoEncrypt = ASCIIEncoding.ASCII.GetBytes(stringToEncrypt);
            byte[] encryptedBytes = rsa.Encrypt(bytestoEncrypt, false);
            return Convert.ToBase64String(encryptedBytes);
        }
        
        public static string Decrypt(X509Certificate2 x509, string stringTodecrypt)
        {
            if (x509 == null || string.IsNullOrEmpty(stringTodecrypt))
                throw new Exception("A x509 certificate and string for decryption must be provided");
                
            if (!x509.HasPrivateKey)
                throw new Exception("x509 certicate does not contain a private key for decryption");
                
            RSACryptoServiceProvider rsa = (RSACryptoServiceProvider)x509.PrivateKey;
            byte[] bytestodecrypt = Convert.FromBase64String(stringTodecrypt);
            byte[] plainbytes = rsa.Decrypt(bytestodecrypt, false);
            System.Text.ASCIIEncoding enc = new System.Text.ASCIIEncoding();
            return enc.GetString(plainbytes);
        }
    }
}

Notes:

RSACryptoServiceProvider: http://msdn.microsoft.com/en-us/library/bfsktky3(VS.80).aspx

MakeCert: http://msdn.microsoft.com/en-us/library/bfsktky3(VS.80).aspx

X509Certificate2 Class: http://msdn.microsoft.com/en-us/library/system.security.cryptography.x509certificates.x509certificate2.aspx

Example of Rijndael based encryption/decryption in C#

from: http://www.obviex.com/samples/Code.aspx?Source=EncryptionCS&Title=Symmetric%20Key%20Encryption&Lang=C%23

Uses plain text for its initialization vector and password. Which means that you can store those values in your web.config (which you would obviously have to encrypt – see exportable encryptio)

///////////////////////////////////////////////////////////////////////////////
// SAMPLE: Symmetric key encryption and decryption using Rijndael algorithm.
// 
// To run this sample, create a new Visual C# project using the Console
// Application template and replace the contents of the Class1.cs file with
// the code below.
//
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, 
// EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED 
// WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
// 
// Copyright (C) 2002 Obviex(TM). All rights reserved.
// 
using System;
using System.IO;
using System.Text;
using System.Security.Cryptography;

/// <summary>
/// This class uses a symmetric key algorithm (Rijndael/AES) to encrypt and 
/// decrypt data. As long as encryption and decryption routines use the same
/// parameters to generate the keys, the keys are guaranteed to be the same.
/// The class uses static functions with duplicate code to make it easier to
/// demonstrate encryption and decryption logic. In a real-life application, 
/// this may not be the most efficient way of handling encryption, so - as
/// soon as you feel comfortable with it - you may want to redesign this class.
/// </summary>
public class RijndaelSimple
{
    /// <summary>
    /// Encrypts specified plaintext using Rijndael symmetric key algorithm
    /// and returns a base64-encoded result.
    /// </summary>
    /// <param name="plainText">
    /// Plaintext value to be encrypted.
    /// </param>
    /// <param name="passPhrase">
    /// Passphrase from which a pseudo-random password will be derived. The
    /// derived password will be used to generate the encryption key.
    /// Passphrase can be any string. In this example we assume that this
    /// passphrase is an ASCII string.
    /// </param>
    /// <param name="saltValue">
    /// Salt value used along with passphrase to generate password. Salt can
    /// be any string. In this example we assume that salt is an ASCII string.
    /// </param>
    /// <param name="hashAlgorithm">
    /// Hash algorithm used to generate password. Allowed values are: "MD5" and
    /// "SHA1". SHA1 hashes are a bit slower, but more secure than MD5 hashes.
    /// </param>
    /// <param name="passwordIterations">
    /// Number of iterations used to generate password. One or two iterations
    /// should be enough.
    /// </param>
    /// <param name="initVector">
    /// Initialization vector (or IV). This value is required to encrypt the
    /// first block of plaintext data. For RijndaelManaged class IV must be 
    /// exactly 16 ASCII characters long.
    /// </param>
    /// <param name="keySize">
    /// Size of encryption key in bits. Allowed values are: 128, 192, and 256. 
    /// Longer keys are more secure than shorter keys.
    /// </param>
    /// <returns>
    /// Encrypted value formatted as a base64-encoded string.
    /// </returns>
    public static string Encrypt(string   plainText,
                                 string   passPhrase,
                                 string   saltValue,
                                 string   hashAlgorithm,
                                 int      passwordIterations,
                                 string   initVector,
                                 int      keySize)
    {
        // Convert strings into byte arrays.
        // Let us assume that strings only contain ASCII codes.
        // If strings include Unicode characters, use Unicode, UTF7, or UTF8 
        // encoding.
        byte[] initVectorBytes = Encoding.ASCII.GetBytes(initVector);
        byte[] saltValueBytes  = Encoding.ASCII.GetBytes(saltValue);
        
        // Convert our plaintext into a byte array.
        // Let us assume that plaintext contains UTF8-encoded characters.
        byte[] plainTextBytes  = Encoding.UTF8.GetBytes(plainText);
        
        // First, we must create a password, from which the key will be derived.
        // This password will be generated from the specified passphrase and 
        // salt value. The password will be created using the specified hash 
        // algorithm. Password creation can be done in several iterations.
        PasswordDeriveBytes password = new PasswordDeriveBytes(
                                                        passPhrase, 
                                                        saltValueBytes, 
                                                        hashAlgorithm, 
                                                        passwordIterations);
        
        // Use the password to generate pseudo-random bytes for the encryption
        // key. Specify the size of the key in bytes (instead of bits).
        byte[] keyBytes = password.GetBytes(keySize / 8);
        
        // Create uninitialized Rijndael encryption object.
        RijndaelManaged symmetricKey = new RijndaelManaged();
        
        // It is reasonable to set encryption mode to Cipher Block Chaining
        // (CBC). Use default options for other symmetric key parameters.
        symmetricKey.Mode = CipherMode.CBC;        
        
        // Generate encryptor from the existing key bytes and initialization 
        // vector. Key size will be defined based on the number of the key 
        // bytes.
        ICryptoTransform encryptor = symmetricKey.CreateEncryptor(
                                                         keyBytes, 
                                                         initVectorBytes);
        
        // Define memory stream which will be used to hold encrypted data.
        MemoryStream memoryStream = new MemoryStream();        
                
        // Define cryptographic stream (always use Write mode for encryption).
        CryptoStream cryptoStream = new CryptoStream(memoryStream, 
                                                     encryptor,
                                                     CryptoStreamMode.Write);
        // Start encrypting.
        cryptoStream.Write(plainTextBytes, 0, plainTextBytes.Length);
                
        // Finish encrypting.
        cryptoStream.FlushFinalBlock();

        // Convert our encrypted data from a memory stream into a byte array.
        byte[] cipherTextBytes = memoryStream.ToArray();
                
        // Close both streams.
        memoryStream.Close();
        cryptoStream.Close();
        
        // Convert encrypted data into a base64-encoded string.
        string cipherText = Convert.ToBase64String(cipherTextBytes);
        
        // Return encrypted string.
        return cipherText;
    }
    
    /// <summary>
    /// Decrypts specified ciphertext using Rijndael symmetric key algorithm.
    /// </summary>
    /// <param name="cipherText">
    /// Base64-formatted ciphertext value.
    /// </param>
    /// <param name="passPhrase">
    /// Passphrase from which a pseudo-random password will be derived. The
    /// derived password will be used to generate the encryption key.
    /// Passphrase can be any string. In this example we assume that this
    /// passphrase is an ASCII string.
    /// </param>
    /// <param name="saltValue">
    /// Salt value used along with passphrase to generate password. Salt can
    /// be any string. In this example we assume that salt is an ASCII string.
    /// </param>
    /// <param name="hashAlgorithm">
    /// Hash algorithm used to generate password. Allowed values are: "MD5" and
    /// "SHA1". SHA1 hashes are a bit slower, but more secure than MD5 hashes.
    /// </param>
    /// <param name="passwordIterations">
    /// Number of iterations used to generate password. One or two iterations
    /// should be enough.
    /// </param>
    /// <param name="initVector">
    /// Initialization vector (or IV). This value is required to encrypt the
    /// first block of plaintext data. For RijndaelManaged class IV must be
    /// exactly 16 ASCII characters long.
    /// </param>
    /// <param name="keySize">
    /// Size of encryption key in bits. Allowed values are: 128, 192, and 256.
    /// Longer keys are more secure than shorter keys.
    /// </param>
    /// <returns>
    /// Decrypted string value.
    /// </returns>
    /// <remarks>
    /// Most of the logic in this function is similar to the Encrypt
    /// logic. In order for decryption to work, all parameters of this function
    /// - except cipherText value - must match the corresponding parameters of
    /// the Encrypt function which was called to generate the
    /// ciphertext.
    /// </remarks>
    public static string Decrypt(string   cipherText,
                                 string   passPhrase,
                                 string   saltValue,
                                 string   hashAlgorithm,
                                 int      passwordIterations,
                                 string   initVector,
                                 int      keySize)
    {
        // Convert strings defining encryption key characteristics into byte
        // arrays. Let us assume that strings only contain ASCII codes.
        // If strings include Unicode characters, use Unicode, UTF7, or UTF8
        // encoding.
        byte[] initVectorBytes = Encoding.ASCII.GetBytes(initVector);
        byte[] saltValueBytes  = Encoding.ASCII.GetBytes(saltValue);
        
        // Convert our ciphertext into a byte array.
        byte[] cipherTextBytes = Convert.FromBase64String(cipherText);
        
        // First, we must create a password, from which the key will be 
        // derived. This password will be generated from the specified 
        // passphrase and salt value. The password will be created using
        // the specified hash algorithm. Password creation can be done in
        // several iterations.
        PasswordDeriveBytes password = new PasswordDeriveBytes(
                                                        passPhrase, 
                                                        saltValueBytes, 
                                                        hashAlgorithm, 
                                                        passwordIterations);
        
        // Use the password to generate pseudo-random bytes for the encryption
        // key. Specify the size of the key in bytes (instead of bits).
        byte[] keyBytes = password.GetBytes(keySize / 8);
        
        // Create uninitialized Rijndael encryption object.
        RijndaelManaged    symmetricKey = new RijndaelManaged();
        
        // It is reasonable to set encryption mode to Cipher Block Chaining
        // (CBC). Use default options for other symmetric key parameters.
        symmetricKey.Mode = CipherMode.CBC;
        
        // Generate decryptor from the existing key bytes and initialization 
        // vector. Key size will be defined based on the number of the key 
        // bytes.
        ICryptoTransform decryptor = symmetricKey.CreateDecryptor(
                                                         keyBytes, 
                                                         initVectorBytes);
        
        // Define memory stream which will be used to hold encrypted data.
        MemoryStream  memoryStream = new MemoryStream(cipherTextBytes);
                
        // Define cryptographic stream (always use Read mode for encryption).
        CryptoStream  cryptoStream = new CryptoStream(memoryStream, 
                                                      decryptor,
                                                      CryptoStreamMode.Read);

        // Since at this point we don't know what the size of decrypted data
        // will be, allocate the buffer long enough to hold ciphertext;
        // plaintext is never longer than ciphertext.
        byte[] plainTextBytes = new byte[cipherTextBytes.Length];
        
        // Start decrypting.
        int decryptedByteCount = cryptoStream.Read(plainTextBytes, 
                                                   0, 
                                                   plainTextBytes.Length);
                
        // Close both streams.
        memoryStream.Close();
        cryptoStream.Close();
        
        // Convert decrypted data into a string. 
        // Let us assume that the original plaintext string was UTF8-encoded.
        string plainText = Encoding.UTF8.GetString(plainTextBytes, 
                                                   0, 
                                                   decryptedByteCount);
        
        // Return decrypted string.   
        return plainText;
    }
}

/// <summary>
/// Illustrates the use of RijndaelSimple class to encrypt and decrypt data.
/// </summary>
public class RijndaelSimpleTest
{
    /// <summary>
    /// The main entry point for the application.
    /// </summary>
    [STAThread]
    static void Main(string[] args)
    {
        string   plainText          = "Hello, World!";    // original plaintext
        
        string   passPhrase         = "Pas5pr@se";        // can be any string
        string   saltValue          = "s@1tValue";        // can be any string
        string   hashAlgorithm      = "SHA1";             // can be "MD5"
        int      passwordIterations = 2;                  // can be any number
        string   initVector         = "@1B2c3D4e5F6g7H8"; // must be 16 bytes
        int      keySize            = 256;                // can be 192 or 128
        
        Console.WriteLine(String.Format("Plaintext : {0}", plainText));

        string  cipherText = RijndaelSimple.Encrypt(plainText,
                                                    passPhrase,
                                                    saltValue,
                                                    hashAlgorithm,
                                                    passwordIterations,
                                                    initVector,
                                                    keySize);

        Console.WriteLine(String.Format("Encrypted : {0}", cipherText));
        
        plainText          = RijndaelSimple.Decrypt(cipherText,
                                                    passPhrase,
                                                    saltValue,
                                                    hashAlgorithm,
                                                    passwordIterations,
                                                    initVector,
                                                    keySize);

        Console.WriteLine(String.Format("Decrypted : {0}", plainText));
    }
}
//
// END OF FILE
///////////////////////////////////////////////////////////////////////////////

Wednesday, February 24, 2010

Google Tasks - Bookmarklet

Here is a bookmarklet that opens Google Tasks in its own little window:

javascript:newwindow=window.open('http://mail.google.com/tasks/ig','','resizable=1,toolbar=0,location=0,status=0,menubar=0,scrollbars=1,width=400,height=600');newwindow.focus();

Just create a bookmark, open its properties and paste the above code into the address field. Move the bookmark to your toolbar for easy access.

Tuesday, February 23, 2010

DotNetNuke Zero Day Vulnerability (semi-colon bug)

There is a major security loop hole in DotNetNuke versions 4.9.2 and below where DNN will allow an unauthorized user to upload almost any file onto the server. This loop hole combined with the IIS 5/6 zero day multiple extension exploit can allow a hacker complete access to your website.So if you are a DNN version that is not 4.9.4 and up – read on as this is huge hole in your website.
The DNN Issue:
If you browse to the following sub-folder on your DNN site “Providers/HtmlEditorProviders/Fck/fcklinkgallery.aspx”, you will see a page that looks like this:
 image
The above page on its own is not too bad. But if you now paste the following javascript code into the address bar and hit enter: “javascript:__doPostBack('ctlURL$cmdUpload','')” you will see the following browse dialog which will allow you to upload almost any file onto the website (restricted to the list of files allowed by FCKEditor – typically images, documents, etc).
image
The above hack will typically lead to hackers dropping small txt files that have some kind of a notice saying that your website has been hacked!
image
It is hard to do anything substantial with this hack alone.
But wait there is more…..
The IIS Issue:
On December 25th of 2009, an “Ethical” hacker found a vulnerability in IIS 5 and IIS 6 called the “semi-colon” bug or the “multiple extensions IIS/ASP bug”. Read More.
The semi-colon bug allows any file that has .asp in the file name to execute as an ASP file. This bug occurs in all versions of IIS 6 and prior. This means that a file named “innocusFile.asp;.jpg” will be executed like an ASP file.
The big scary picture:
The 2 bugs on their own were bad, but it still would be hard for anything bad to happen. But together – they open up a can of worms that is going to make everyone in your organization pulling every fire alarm in the building. Here is the big picture:
1. Hacker fabricates an ASP file that uses COM objects such as the FileSystemObject to get complete access to your computer.
2. Hacker names the asp file as “myHack.asp;.jpg”.
3. Hacker navigates to the “Providers/HtmlEditorProviders/Fck/fcklinkgallery.aspx” file in his browser and uses the DNN loop hole to upload his myHack.asp;.jpg file. DNN complies because it thinks it is a simple jpg file. This is because DNN looks only at the last extension it finds in a file name.
4. The file uploads to the DNN website to the folder (WITHHELD – to protect unprotected DNN sites).
5. The hacker browses to the file that he uploaded. The file is delivered to the ASP processing engine by IIS and a page that opens up the entire computer to the hacker is displayed. This is because IIS has been coded such that it recognizes a file type based on its extension even if the extension is not the last part of the file name!!
6. The hacker uses his ASP page to get full control of your website (and I mean full control – all disk drives, connection strings, databases, registy, etc.). Nothing is safe after this.
Here is a sample ASP file called the “Smart Shell”, that basically shows the capabilities that an hacker can get over your website: (This kind of an ASP file is also called the 3fexe ASP hack).
image
How to mitigate:
Because there is no known fix, there are only ways to mitigate this attack (and hence it is a zero-day hack).
1. Rename the fcklinkgallery.aspx file
As fcklinkgallery.aspx is the entry point for this hack attack, the first thing to do is to rename this file. I suggest using a random file name – like a guid. After you rename the file, you will need to update the “LinksGalleryPath” setting in your config file. This will be found in the <dotnetnuke><htmlEditor><providers><add name="FckHtmlEditorProvider"> section. Just look for “LinksGalleryPath” and update the value to the newly named file name.
If the hacker cannot browse to the fcklinkgallery.aspx file, he will not be able to upload a ASP file onto your DNN site.
(Update: 03-30-2010) please note: Gabe has included an extra step that needs to be taken to get the link editor to work after renaming it. Please see the comments below. Basically you need to also rename the  "\Providers\HtmlEditorProviders\Fck\App_LocalResources\fcklinkgallery.aspx.resx" to match the renamed fckLinkGallery file.)

2. Remove Execute permission on the Portals folder of your DNN site.
The sub-folder “Portals” in your DNN site typically does not need to be able to run ASP files or any other files. So remove “Execute” permissions on that folder.
Open up IIS.
Expand the website node for your DNN site.
Select the Portals node in the explorer view on the left.
Right click on the Portals node and open the Properties dialog.
Chose the Directory Node.
Set Execute Permissions to “None”.

3. Remove access to FileSystemObject.
This falls into the excessively precautious as it is not really required for you to do. An important note: Do not do this if you know that you have some ASP apps on your site and if those ASP apps use FileSystemObject – you might end up hosing those apps.
There are 2 ways to do this: Remove access to this COM object from the security principal used to run your IIS website (typically ASPNET) or to completely unregister the dll.
1. Registry access:
Open registry editor.
Browse to “HKEY_CLASSES_ROOT\Scripting.FileSystemObject”, right click and under permissions deny access to the ASPNET user.
2. Completely disable FileSystemObject
Run regsvr32 scrrun.dll .u in the C:\windows\System32 folder.
Remember – step 3 is really not required to be done.

The only Fix:

The only “true” fix is to upgrade to IIS 7 or higher and a DNN version of 4.9.4 or higher.
Notes:
Securing IIS 6.0:
http://technet.microsoft.com/en-us/library/cc875829.aspx
One way hacking (which is what the above type of hack is known as):
http://www.net-square.com/papers/one_way/one_way.html
Restricting information available to anonymous users:
http://support.microsoft.com/kb/143474
DNN LinkGallery Remote File Upload without Extension:
http://securityreason.com/exploitalert/6234
DNN Failure to revalidate file and folder permissions correctly for uploads:
http://www.dotnetnuke.com/News/SecurityPolicy/SecurityBulletinno17/tabid/1162/Default.aspx
IIS Security Vulnerability and DNN
http://www.dotnetnuke.com/Community/Forums/tabid/795/forumid/108/postid/347394/scope/posts/Default.aspx

SQL Server and External Connector Licenses

If you have a web-application that uses a SQL Server database then you might have to buy an external connector license (this I did not know before today – luckily we have a licensing guy in our org.)

From http://www.microsoft.com/licensing/about-licensing/client-access-license.aspx:

External Connector Licensing:

An external user is a person who is not an employee or similar personnel of the company or its affiliates, and is not someone to whom you provide hosted services. An EC license assigned to a server permits access by any number of external users, as long as that access is for the benefit of the licensee and not the external user.

Anyways, the only time you wont need an external connector license for your SQL Server database is when your installation is licensed by the processor.

Per Processor Licensing

Under the Per Processor model, you acquire a Processor License for each processor in the server on which the software is running. A Processor License includes access for an unlimited number of users to connect from either inside the local area network (LAN) or wide area network (WAN), or outside the firewall (via the Internet). You do not need to purchase additional server licenses, CALs, or Internet Connector Licenses.

Monday, February 22, 2010

Response.Redirect cannot be called in a Page callback

If you are getting the “Response.Redirect cannot be called in a Page callback” then you are most probably using AJAX and you are using a Response.Redirect (or Server.Transfer) in an event that was fired from within an AJAX panel.

The reason this does not work is that there is only a partial post-back that occurs with controls that are within an AJAX panel and you cannot perform a Redirect from within a partial post-back.

Fixes:

1. Dont do a redirect in an event that is fired due to a partial post-back!

2. In the event, instead of doing a redirect, register a javascript method that will perform the redirect from the client’s browser. eg:

string script = string.Format("document.location.href = '{0}');", "pageToRedirectTo.aspx");
ScriptManager.RegisterClientScriptBlock(Page, typeof(Page), "redirect", script, true);

Saturday, February 20, 2010

MousePath – create your own art

Came across this very cool app that tracks your mouse and draws out lines on a large canvas. The app is called MousePath and was created by Anatoliy Zenkov.

MousePath is a Java app and can be downloaded for the PC (dl.dropbox.com/u/684632/mousepath.exe.zip) and Mac(dl.dropbox.com/u/684632/mousepath.jar)

You run the app and leave it in its maximized state and then go about doing your daily work. And when you are happy with the art created just hit the S button and it will create a file in the same folder where the app is running.

Here is my mousepath art created after 30 minutes:

mousePath

Friday, February 19, 2010

BBC Redesign

Here is a post on how the BBC is redesigning their new website. I found it an interesting study in design and how through their project was (setting guidelines on underlying grids, color palettes, embedding of audio/video, etc).

Also as some one who is completely bereft of the ability to choose good colors that go well with each other, there are palettes on the page that I could use on my web-pages (as well as other design pointers).

http://www.bbc.co.uk/blogs/bbcinternet/2010/02/a_new_global_visual_language_f.html

3-GVL2-Grid

Keeping Employees Motivated

From a Harvard Business School article:

First step: stop demotivating employees

According to the author there are just three important factors that matter most when it comes to keeping employees motivated:

  • Equity: To be respected and to be treated fairly in areas such as pay, benefits, and job security.
  • Achievement: To be proud of one's job, accomplishments, and employer.
  • Camaraderie: To have good, productive relationships with fellow employees.

Interestingly, the author found that if one of the above factors is missing, then they cannot be substituted with another factor (for e.g: higher pay).

And here are the main things the author says managers can do in different areas:

  • Achievement related
    • Instill an inspiring purpose
    • Provide recognition
    • Be an expediter for your employees
    • Coach your employees for improvement
  • Equity related
    • Communicate fully
    • Face up to poor performance
  • Camaraderie related
    • Promote teamwork
  • All three areas (Achievement, Equity and Camaraderie)
    • Listen and involve

Read the entire article as it elaborates on the above listed points.

http://hbswk.hbs.edu/archive/5289.html