Hi everyone,
We’ve run into a problem with our ASP.NET 2.0 application while being audited by a third party for security. It seems that adopting the AJAX Control Toolkit has exposed us to an XSS vulnerability:
1) We’re using the AJAX Control Toolkit Script Manager control (from v. 2.0.20229, the last .NET 2.0 compatible build).
2) The exploit requires that the user authenticates successfully.
3) After login, the user pastes the following url into the browser:
https://oursitenamehere/Default.aspx?_TSM_HiddenField_=ajaxScriptManager_HiddenField37c5d%27)%3b}}alert(%27javascripthijacking%20and%20xss%27)//c9c4b0b8d4b&_TSM_CombinedScripts_=%3b%3bAjaxControlToolkit%2c+Version%3d1.0.20229.20821%2c+Culture%3dneutral%2c+PublicKeyToken%3d28f01b0e84b6d53e%3afi-FI%3ac5c982cc-4942-4683-9b48-c2c58277700f%3ae2e86ef9%3a1df13a87%3ac4c00916%3a9ea3f0e2%3a9e8e87e9%3a4c9865be%3aba594826%3ac76f1358%3a69ce9abf
4) The browser returns an aspx-file generated by the toolkit, e.g. CAWT4TOB.aspx. This file contains a huge amount of toolkit javascript, preceded by the following comment: //START AjaxControlToolkit.Common.Common.js
5) At the very bottom of this file, the following appears:
AjaxControlToolkit.ListSearchQueryPattern.registerEnum('AjaxControlToolkit.ListSearchQueryPattern');
//END AjaxControlToolkit.ListSearch.ListSearchBehavior.js
if(typeof(Sys)!=='undefined')Sys.Application.notifyScriptLoaded();
(function() {var fn = function() {$get('ajaxScriptManager_HiddenField37c5d');}}alert('javascripthijacking and xss')//c9c4b0b8d4b').value += ';;AjaxControlToolkit, Version=1.0.20229.20821, Culture=neutral, PublicKeyToken=28f01b0e84b6d53e:fi-FI:c5c982cc-4942-4683-9b48-c2c58277700f:e2e86ef9:1df13a87:c4c00916:9ea3f0e2:9e8e87e9:4c9865be:ba594826:c76f1358:69ce9abf';Sys.Application.remove_load(fn);};Sys.Application.add_load(fn);})();
So basically the script manager itself is sanitizing user input properly, and thus allows for javascript injection. I wasn’t able to get the script to execute and display the pop-up, but the auditor says they can’t guarantee it’s not possible. Here's the relevant
code from the ToolkitScriptManager.cs:
protected override void OnLoad(EventArgs e)
{
// Initialize
_disabledScriptReferences = new List<ScriptReference>();
_uncombinableScriptReferences = new List<scriptreference>();
// Create a hidden field to track loaded scripts - load its contents if already present
string hiddenFieldName = HiddenFieldName;
string value = "";
if (!IsInAsyncPostBack || (null == Page.Request.Form[hiddenFieldName]))
{
RegisterHiddenField(Page, hiddenFieldName, value);
}
else
{
//!!! This input isn't sanitized!
value = Page.Request.Form[hiddenFieldName];
}
// Get the list of already-loaded scripts from the page
_scriptEntries = DeserializeScriptEntries(value, true);
base.OnLoad(e);
}</scriptreference> So what are my options here? The auditor recommends using the Microsoft Anti-Cross Site Scripting Library [1] to encode the input. However, this means we would have to make changes to the toolkit source and recompile the dll. This might be tricky given
our current schedule. We also can’t remove the toolkit features from use without significant effort.
Has anyone seen this kind of behavior before? Is there some simple solution I’m overlooking? Google didn’t give me any real help, so I’m hoping someone can either provide me with a solution or give me evidence to prove that the injected script can never be
executed.
Thanks,
Tommi Lind
Avanade Finland
1) http://msdn.microsoft.com/en-us/library/aa973813.aspx