Will "the Mighty" Strohl

DotNetNuke Module Security: Filtering User-Entered Text

I recently read from someone that they suggest to always perform a Server.HtmlEncode on user-entered text.   While this is good advice, it reminded me that the DotNetNuke core gives us some additional security options in the DotNetNuke.Security.PortalSecurity class.  I figured that I would blog about this, as the DNN core gives us a great deal of pre-written methods to help make development easier and faster.  Even though a ton of functionality is written and provided to us, most people don’t know that much of this functionality exists.

The DotNetNuke.Security.PortalSecurity Class

The PortalSecurity class contains several methods to help you provide encryption, decryption, portal permissions, and user entry security to your modules and providers.  Here is a listing the publically available methods in DNN version 5.00.01:

  • ClearRoles() – This method deletes the “portalroles” cookie.  As a result, the current user will not match any roles used for security purposes.
  • CreateKey(Integer numBytes) As String – This method generates a SHA1 key based on the number of bytes you choose.  This is great to generate random key values.
  • Decrypt(String strKey, String strData) As String – This method decrypts a string value using DES encryption. The strKey object is a value that you provided to salt the data upon encrypting it.  strData is your previously encrypted string value.  The method returns the original decrypted string value.  If anything goes wrong, an empty string will be returned.
  • Encrypt(String strKey, String strData) As String – Using your strKey object to salt the encryption, this method returns a DES encrypted string value.  strData is the string value that you wish to encrypt.
  • ForceSecureConnection() – Calling this method takes the current URL and redirects to the secured version of it. For example, it changes HTTP connections to HTTPS, by redirecting to the altered version of the URL.  You will know when this occurs, as DNN appends ssl=1 to the URL.
  • HasNecessaryPermission(SecurityAccessLevel AccessLevel, PortalSettings PortalSettings, ModuleInfo ModuleConfiguration, UserInfo User) As Boolean +2 overloads – This method quickly tells you if a visitor has the appropriate permissions to access a resource that has the given AccessLevel.  This method can save you tons of time, and is a common chunk of logic that is unknowingly rewritten by developers all over.
  • InputFilter(String UserInput, FilterFlag FilterType) As String – A very useful method indeed, it parses a string value in UserInput, and returns a safe version of the string.  FilterType tells the method how you wish to parse the string, as your needs may vary.
  • IsInRole(String Role) As Boolean – When you call this method, it automatically pulls the UserInfo for the user that is currently logged in.  It then iterates through that users’ roles, and returns a Boolean value to let you know if any of those roles match the name of the role you gave it.  It is not a thread safe method, but you probably shouldn’t be calling it from a child thread anyhow.
  • IsInRoles(String Roles) As Boolean – This method expects a semi-colon (;) delimited string value in the Roles object, containing a list of role names.  For this method to return True, the user that is currently logged in must match every role name you passed into the method.
  • IsPageAdmin() As Boolean – Like the previous two methods, this one also grabs the information for the user that is currently logged in.  It then grabs a list of the roles that have Edit permissions to the current Tab or Page.  Finally, it uses the previously mentioned IsInRoles() method to see if the user is an administrator of the current page.  There is a problem with this method though.  If the current tab has multiple roles checked to edit the page, the current user will need to be in each of them for this method to return true.
  • SignOut() – Quite simply, this method does exactly what is says.  First, it calls the standard System.Web.Security.FormsAuthentication.SignOut() method to log you out.  Then, it clears all of the cookies that DNN uses to manage the permissions for the user.

Filtering User-Entered Text

Now we are going to get into the meat of why I originally began writing this blog entry.  We need to protect ourselves from malicious string values that may be submitted to our modules or providers.  I used the word malicious, but it is possible that the person who does this might not be doing it intentionally.  The most common way to protect against harmful user string values is shown below:

MyDataObject.PropertyName = Server.HtmlEncode(TextBox1.Text)

This will catch most of the security sensitive data that you don’t want to be saved and/or rendered to your DNN website.  But sometimes you need something a little more specialized.  The InputFilter() method in the PortalSecurity class will help you.  To simulate the previous example, here is how it might change:

Imports DotNetNuke.Security
Dim pSecurity As New PortalSecurity
MyDataObject.PropertyName = pSecurity.InputFilter(TextBox1.Text, NoMarkup)

With just a tiny bit of extra coding, the previous example does pretty much the same exact thing as Server.HtmlEncode().  But you get out of it core functionality that can be reused over and over, and called from child threads or the DNN scheduler.  It also performs a check to see if the encoding even needs to be done, potentially having higher performance than just calling HtmlEncode() alone.  You may have already noticed, but the second argument in the InputFilter() method is an Enumeration, allowing for more ways to filter the users’ input.

Here are the values for the FilterFlag enumeration:

  • MultiLine – This option simply replaces all line breaks with HTML break tags. Unfortunately, the break tags are not XHTML compliant.
  • NoMarkup – After checking to see if there is any HTML markup in the string, this then calls the HttpUtility.HtmlEncode() method.
  • NoScripting – This is one of the most handy options, as it prevents all of the known ways that can be used for cross-site scripting (XSS) attacks, by removing the potentially malicious strings.  Also, if the string is already HTML encoded, this option first decodes the string before running the security filter.
  • NoSQL – With the DAL and DAL+ that is offered by DNN, this option should be the least useful, as we should all be using Stored Procedures. However, if you find it necessary, you can use this option to remove the known attack methods used to perform SQL Injection attacks.  When you look at the source, it looks very much like the “Clean SQL” methods we used to write in the Classic ASP days.
  • NoAngleBrackets – This is an interesting option.  If it worked like the others it would just do it’s thing, which is to find and remove angle brackets, namely the < and > characters.  However, if you call this option, it is possible for the Web.Config to override you and cause the angle brackets to not be removed.  I will explain below.

In the web.config, you have the following AppSetting:

<add key=”RemoveAngleBracketsvalue=”false/>

If that AppSetting is either missing, or the value is False, then the angle brackets will not be removed even though you called it.

There you go!  DotNetNuke does an outstanding job of doing a lot of work for us, and providing common functionality that we don’t need to write.  This blog entry is a prime example of how much you can rely on DNN to save you time, effort, and add more value to your programming effort and project.

blog comments powered by Disqus