Apr23Written by:Will
4/23/2009

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 AsNew 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:
<addkey=”RemoveAngleBrackets” value=”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.
5 comment(s) so far...

Hi Will,
This is a great review of the options available in the class. Thought I'd add a couple points:
1. I strongly discourage that PortalSecurity.Decrypt and PortalSecurity.Encrypt be used for the protection of sensitive data (and, when there is a need for encryption, aren't we always dealing with sensitive data?). The cypher used is weak, and the code is maintained for legacy purposes. These calls obscure -- but do not significantly protect -- data.
2. Even with the additional protection offered by the InputFilter overloads, it is important that the resultant string be returned encoded. This means that, for virtually all applications, the NoMarkup flag must be set on the InputFilter call. Though the other flags may be set (or not) at a developer's discretion, the NoMarkup bit should be omitted only when there is a specific design need not to do so.
3. The exception to the above rule is the NoSQL flag. This flag trumps the NoMarkup flag; it should not be set when formatting data that is to be displayed to an end user.
Hope this helps!
Brandon
By Brandon Haynes on
4/24/2009 |
Nice write up Will. I'd just like to draw your attention to the "secure module development" guide @ www.dotnetnuke.com/News/SecurityPolicy/tabid/940/Default.aspx which details many of these filters, and how to use them (as well as some lesser known functions).
As for the RemoveAngleBrackets setting, it was added per a request of a major customer, so they could pass a security audit - ironically, it doesn't provider any extra security, but their audit team didn't understand this despite repeated explanations (they failed to recognise the false positive from their vulnerability scanner). We added it, as we didn't want to be dotnetnuke to be blocked from this customer (i'm not at liberty to give their name, but they're a major military customer)
By Cathal on
4/24/2009 |
Thank you both for your comments.
@Brandon - Thanks for the input (no pun intended). Those are some great tips!
@Cathal - I completely forgot to mention the Module Development Security Guide. Though, since I haven't read it in a while, I was uncertain to how accurate it still is.
By Will on
4/24/2009 |
RE: #2 above: "the NoMarkup flag must be set on the InputFilter call"
where is this set please?
By mark on
5/27/2009 |
"NoMarkup" is part of an enumeration. It is used in a code example in the blog post.
By Will on
5/27/2009 |