Sponsored Community Message Browse Free. Go deeper with Full Access. Free visitors can browse public knowledge. Full Access unlocks participation, member areas, and an ad-free experience.

XML Denial of Service Attacks and Defenses-gctid51532

Started by Ɔbenfo Ọbádélé, May 27, 2012, 07:07 AM

Previous topic - Next topic
XML Denial of Service Attacks and DefensesBryan SullivanDenial  of service (DoS) attacks are among the oldest types of attacks against  Web sites. Documented DoS attacks exist at least as far back as 1992,  which predates SQL injection (discovered in 1998), cross-site scripting  (JavaScript wasn’t invented until 1995), and cross-site request forgery  (CSRF attacks generally require session cookies, and cookies weren’t  introduced until 1994).
From the beginning, DoS attacks were  highly popular with the hacker community, and it’s easy to understand  why. A single “script kiddie” attacker with a minimal amount of skill  and resources could generate a flood of TCP SYN (for synchronize)  requests sufficient to knock a site out of service. For the fledgling  e-commerce world, this was devastating: if users couldn’t get to a site,  they couldn’t very well spend money there either. DoS attacks were the  virtual equivalent of erecting a razor-wire fence around a  brick-and-mortar store, except that any store could be attacked at any  time, day or night.
Over the years, SYN flood attacks have been  largely mitigated by improvements in Web server software and network  hardware. However, lately there has been a resurgence of interest in DoS  attacks within the security community—not for “old school”  network-level DoS, but instead for application-level DoS and  particularly for XML parser DoS.
XML DoS attacks are extremely  asymmetric: to deliver the attack payload, an attacker needs to spend  only a fraction of the processing power or bandwidth that the victim  needs to spend to handle the payload. Worse still, DoS vulnerabilities  in code that processes XML are also extremely widespread. Even if you’re  using thoroughly tested parsers like those found in the Microsoft .NET  Framework System.Xml classes, your code can still be vulnerable unless  you take explicit steps to protect it.
This article describes some  of the new XML DoS attacks. It also shows ways for you to detect  potential DoS vulnerabilities and how to mitigate them in your code.
XML BombsOne  type of especially nasty XML DoS attack is the XML bomb—a block of XML  that is both well-formed and valid according to the rules of an XML  schema but which crashes or hangs a program when that program attempts  to parse it. The best-known example of an XML bomb is probably the  Exponential Entity Expansion attack.
Inside an XML document type  definition (DTD), you can define your own entities, which essentially  act as string substitution macros. For example, you could add this line  to your DTD to replace all occurrences of the string &companyname;  with “Contoso Inc.”:

''.str_replace('
', '', '    
   
 
  ').'[/code]' You can also nest entities, like this:

''.str_replace('
', '', '    
 
   
 
  ').'[/code]' While most developers are familiar with using external DTD  files, it’s also possible to include inline DTDs along with the XML data  itself. You simply define the DTD directly in the   declaration instead of using  to refer to an external  DTD file:

''.str_replace('
', '', '    
        ]>    Glenn P, &divisionname;   Dave L, &divisionname;
   
 
  ').'[/code]' An attacker can now take advantage of these three properties  of XML (substitution entities, nested entities, and inline DTDs) to  craft a malicious XML bomb. The attacker writes an XML document with  nested entities just like the previous example, but instead of nesting  just one level deep, he nests his entities many levels deep, as shown  here:

''.str_replace('
', '', '    
                       ]> &lol9;
   
 
  ').'[/code]' It should be noted that this XML is both well-formed and  valid according to the rules of the DTD. When an XML parser loads this  document, it sees that it includes one root element, “lolz”, that  contains the text “&lol9;”. However, “&lol9;” is a defined  entity that expands to a string containing ten “&lol8;” strings.  Each “&lol8;” string is a defined entity that expands to ten  “&lol7;” strings, and so forth. 
After all the entity expansions  have been processed, this small (< 1 KB) block of XML will actually  contain a billion “lol”s, taking up almost 3GB of memory!  You can try  this attack (sometimes called the Billion Laughs attack) for yourself  using this very simple block of code—just be prepared to kill your test  app process from Task Manager:

''.str_replace('
', '', '    
void processXml(string xml) {     System.Xml.XmlDocument document = new XmlDocument();     document.LoadXml(xml); }
   
 
  ').'[/code]' Some of the more devious readers may be wondering at this  point whether it’s possible to create an infinitely recursing entity  expansion consisting of two entities that refer to each other:

''.str_replace('
', '', '    
  ]> &lol1;
   
 
  ').'[/code]' This would be a very effective attack, but fortunately it  isn’t legal XML and will not parse. However, another variation of the  Exponential Entity Expansion XML bomb that does work is the Quadratic  Blowup attack, discovered by Amit Klein of Trusteer. Instead of defining  multiple small, deeply nested entities, the attacker defines one very  large entity and refers to it many times:

''.str_replace('
', '', '    
  &a;&a;&a;&a;&a;&a;&a;&a;&a;...
   
 
  ').'[/code]'If an attacker defines the entity “&a;” as 50,000  characters long, and refers to that entity 50,000 times inside the root  “kaboom” element, he ends up with an XML bomb attack payload slightly  over 200 KB in size that expands to 2.5 GB when parsed. This expansion  ratio is not quite as impressive as with the Exponential Entity  Expansion attack, but it is still enough to take down the parsing  process.
Another of Klein’s XML bomb discoveries is the Attribute  Blowup attack. Many older XML parsers, including those in the .NET  Framework versions 1.0 and 1.1, parse XML attributes in an extremely  inefficient quadratic O(n2) runtime. By creating an XML  document with a large number of attributes (say 100,000 or more) for a  single element, the XML parser will monopolize the processor for a long  period of time and therefore cause a denial of service condition.  However, this vulnerability has been fixed in .NET Framework versions  2.0 and later.
External Entity AttacksInstead of defining  entity replacement strings as constants, it is also possible to define  them so that their values are pulled from external URIs:

''.str_replace('
', '', '    
   
 
  ').'[/code]' While the exact behavior depends on the particular XML parser  implementation, the intent here is that every time the XML parser  encounters the entity “&stockprice;” the parser will make a request  to www.contoso.com/currentstockprice.ashx and then substitute the  response received from that request for the stockprice entity. This is  undoubtedly a cool and useful feature of XML, but it also enables some  devious DoS attacks.
 The simplest way to abuse the external  entity functionality is to send the XML parser to a resource that will  never return; that is, to send it into an infinite wait loop. For  example, if an attacker had control of the server adatum.com, he could  set up a generic HTTP handler file at http://adatum.com/dos.ashx as  follows:

''.str_replace('
', '', '    
using System; using System.Web; using System.Threading;  public class DoS : IHttpHandler {     public void ProcessRequest(HttpContext context)     {         Thread.Sleep(Timeout.Infinite);     }      public bool IsReunited snakesble { get { return false; } } }
   
 
  ').'[/code]' He could then craft a malicious entity that pointed to  http://adatum.com/dos.ashx, and when the XML parser reads the XML file,  the parser would hang. However, this is not an especially effective  attack. The point of a DoS attack is to consume resources so that they  are unavailable to legitimate users of the application. Our earlier  examples of Exponential Entity Expansion and Quadratic Blowup XML bombs  caused the server to use large amounts of memory and CPU time, but this  example does not. All this attack really consumes is a single thread of  execution. Let’s improve this attack (from the attacker’s perspective)  by forcing the server to consume some resources:

''.str_replace('
', '', '    
public void ProcessRequest(HttpContext context) {     context.Response.ContentType = "text/plain";     byte[] data = new byte[1000000];     for (int i = 0; i < data.Length; i++) { data[i] = (byte)’A’; }     while (true)     {         context.Response.OutputStream.Write(data, 0, data.Length);         context.Response.Flush();     } }
   
 
  ').'[/code]'This code will write an infinite number of ‘A’ characters (one  million at a time) to the response stream and chew up a huge amount of  memory in a very short amount of time. If the attacker is unable or  unwilling to set up a page of his own for this purpose—perhaps he  doesn’t want to leave a trail of evidence that points back to him—he can  instead point the external entity to a very large resource on a  third-party Web site. Movie or file downloads can be especially  effective for this purpose; for example, the Visual Studio 2010  Professional beta download is more than 2GB.
Yet another clever  variation of this attack is to point an external entity at a target  server’s own intranet resources. Discovery of this attack technique is  credited to Steve Orrin of Intel. This technique does require the  attacker to have internal knowledge of intranet sites accessible by the  server, but if an intranet resource attack can be executed, it can be  especially effective because the server is spending its own resources  (processor time, bandwidth, and memory) to attack itself or its sibling  servers on the same network.
Defending Against XML BombsThe  easiest way to defend against all types of XML entity attacks is to  simply disable altogether the use of inline DTD schemas in your XML  parsing objects. This is a straightforward application of the principle  of attack surface reduction: if you’re not using a feature, turn it off  so that attackers won’t be able to abuse it.
In .NET Framework  versions 3.5 and earlier, DTD parsing behavior is controlled by the  Boolean ProhibitDtd property found in the System.Xml.XmlTextReader and  System.Xml.XmlReaderSettings classes. Set this value to true to disable  inline DTDs completely:

''.str_replace('
', '', '    
XmlTextReader reader = new XmlTextReader(stream); reader.ProhibitDtd = true;
   
 
  ').'[/code]'or

''.str_replace('
', '', '    
XmlReaderSettings settings = new XmlReaderSettings(); settings.ProhibitDtd = true; XmlReader reader = XmlReader.Create(stream, settings);
   
 
  ').'[/code]' The default value of ProhibitDtd in XmlReaderSettings is  true, but the default value of ProhibitDtd in XmlTextReader is false,  which means that you have to explicitly set it to true to disable inline  DTDs.
 In .NET Framework version 4.0 (in beta at the time of this  writing), DTD parsing behavior has been changed. The ProhibitDtd  property has been deprecated in favor of the new DtdProcessing property.  You can set this property to Prohibit (the default value) to cause the  runtime to throw an exception if a  element is present  in the XML:

''.str_replace('
', '', '    
XmlReaderSettings settings = new XmlReaderSettings(); settings.DtdProcessing = DtdProcessing.Prohibit; XmlReader reader = XmlReader.Create(stream, settings);
   
 
  ').'[/code]' Alternatively, you can set the DtdProcessing property to  Ignore, which will not throw an exception on encountering a   element but will simply skip over it and not process  it. Finally, you can set DtdProcessing to Parse if you do want to allow  and process inline DTDs.
 If you really do want to parse DTDs, you  should take some additional steps to protect your code. The first step  is to limit the size of expanded entities. Remember that the attacks  I’ve discussed work by creating entities that expand to huge strings and  force the parser to consume large amounts of memory. By setting the  MaxCharactersFromEntities property of the XmlReaderSettings object, you  can cap the number of characters that can be created through entity  expansions. Determine a reasonable maximum and set the property  accordingly. Here’s an example:

''.str_replace('
', '', '    
XmlReaderSettings settings = new XmlReaderSettings(); settings.ProhibitDtd = false; settings.MaxCharactersFromEntities = 1024; XmlReader reader = XmlReader.Create(stream, settings);
   
 
  ').'[/code]'Defending Against External Entity AttacksAt this  point, we have hardened this code so that it is much less vulnerable to  XML bombs, but we haven’t yet addressed the dangers posed by malicious  external entities. You can improve your resilience against these attacks  if you customize the behavior of XmlReader by changing its XmlResolver.  XmlResolver objects are used to resolve external references, including  external entities. XmlTextReader instances, as well as XmlReader  instances returned from calls to XmlReader.Create, are prepopulated with  default XmlResolvers (actually XmlUrlResolvers). You can prevent  XmlReader from resolving external entities while still allowing it to  resolve inline entities by setting the XmlResolver property of  XmlReaderSettings to null. This is attack surface reduction at work  again; if you don’t need the capability, turn it off:

''.str_replace('
', '', '    
XmlReaderSettings settings = new XmlReaderSettings(); settings.ProhibitDtd = false; settings.MaxCharactersFromEntities = 1024; settings.XmlResolver = null; XmlReader reader = XmlReader.Create(stream, settings);
   
 
  ').'[/code]' If this situation doesn’t apply to you—if you really, truly  need to resolve external entities—all hope is not lost, but you do have a  little more work to do. To make XmlResolver more resilient to denial of  service attacks, you need to change its behavior in three ways. First,  you need to set a request timeout to prevent infinite delay attacks.  Second, you need to limit the amount of data that it will retrieve.  Finally, as a defense-in-depth measure, you need to restrict the  XmlResolver from retrieving resources on the local host. You can do all  of this by creating a custom XmlResolver class.
The behavior that  you want to modify is governed by the XmlResolver method GetEntity.  Create a new class XmlSafeResolver derived from XmlUrlResolver and  override the GetEntity method as follows:

''.str_replace('
', '', '    
class XmlSafeResolver : XmlUrlResolver {     public override object GetEntity(Uri absoluteUri, string role,          Type ofObjectToReturn)     {      } }
   
 
  ').'[/code]' The default behavior of the XmlUrlResolver.GetEntity method  looks something like the following code, which you can use as a starting  point for your implementation:

''.str_replace('
', '', '    
public override object GetEntity(Uri absoluteUri, string role,      Type ofObjectToReturn) {     System.Net.WebRequest request = WebRequest.Create(absoluteUri);     System.Net.WebResponse response = request.GetResponse();     return response.GetResponseStream(); }
   
 
  ').'[/code]'The first change is to apply timeout values when making the  request and when reading the response. Both the System.Net.WebRequest  and the System.IO.Stream classes provide inherent support for timeouts.  In the sample code shown in Figure 1, I simply hardcode  the timeout value, but you could easily expose a public Timeout  property on the XmlSafeResolver class if you want greater  configurability.
Figure 1 Configuring Timeout Values

''.str_replace('
', '', '    
private const int TIMEOUT = 10000;  // 10 seconds  public override object GetEntity(Uri absoluteUri, string role,     Type ofObjectToReturn) {     System.Net.WebRequest request = WebRequest.Create(absoluteUri);     request.Timeout = TIMEOUT;      System.Net.WebResponse response = request.GetResponse();     if (response == null)         throw new XmlException("Could not resolve external entity");      Stream responseStream = response.GetResponseStream();     if (responseStream == null)         throw new XmlException("Could not resolve external entity");     responseStream.ReadTimeout = TIMEOUT;     return responseStream; }
   
 
  ').'[/code]'The next step is to cap the maximum amount of data that is  retrieved in the response. There’s no “MaxSize” property or the  equivalent for the Stream class, so you have to implement this  functionality yourself. To do this, you can read data from the response  stream one chunk at a time and copy it into a local stream cache. If the  total number of bytes read from the response stream exceeds a  predefined limit (again hardcoded for simplicity only), you stop reading  from the stream and throw an exception (see Figure 2).
Figure 2 Capping the Maximum Amount of Data Retrieved

''.str_replace('
', '', '    
private const int TIMEOUT = 10000;                   // 10 seconds private const int BUFFER_SIZE = 1024;                // 1 KB  private const int MAX_RESPONSE_SIZE = 1024 * 1024;   // 1 MB  public override object GetEntity(Uri absoluteUri, string role,     Type ofObjectToReturn) {     System.Net.WebRequest request = WebRequest.Create(absoluteUri);     request.Timeout = TIMEOUT;      System.Net.WebResponse response = request.GetResponse();     if (response == null)         throw new XmlException("Could not resolve external entity");      Stream responseStream = response.GetResponseStream();     if (responseStream == null)         throw new XmlException("Could not resolve external entity");     responseStream.ReadTimeout = TIMEOUT;      MemoryStream copyStream = new MemoryStream();     byte[] buffer = new byte[b];     int bytesRead = 0;     int totalBytesRead = 0;     do     {         bytesRead = responseStream.Read(buffer, 0, buffer.Length);         totalBytesRead += bytesRead;         if (totalBytesRead > MAX_RESPONSE_SIZE)             throw new XmlException("Could not resolve external entity");         copyStream.Write(buffer, 0, bytesRead);     } while (bytesRead > 0);      copyStream.Seek(0, SeekOrigin.Begin);     return copyStream; }
   
 
  ').'[/code]'As an alternative, you can wrap the Stream class and implement the limit checking directly in the overridden Read method (see Figure 3).  This is a more efficient implementation since you save the extra memory  allocated for the cached MemoryStream in the earlier example.
Figure 3 Defining a Size-Limited Stream Wrapper Class

''.str_replace('
', '', '    
class LimitedStream : Stream { private Stream stream = null; private int limit = 0; private int totalBytesRead = 0;   public LimitedStream(Stream stream, int limit) { this.stream = stream; this.limit = limit; }   public override int Read(byte[] buffer, int offset, int count) { int bytesRead = this.stream.Read(buffer, offset, count); checked { this.totalBytesRead += bytesRead; } if (this.totalBytesRead > this.limit) throw new IOException("Limit exceeded"); return bytesRead; }   ... }
   
 
  ').'[/code]'Now, simply wrap the stream returned from  WebResponse.GetResponseStream in a LimitedStream and return the  LimitedStream from the GetEntity method (see Figure 4).
Figure 4 Using LimitedStream in GetEntity

''.str_replace('
', '', '    
private const int TIMEOUT = 10000; // 10 seconds private const int MAX_RESPONSE_SIZE = 1024 * 1024; // 1 MB  public override object GetEntity(Uri absoluteUri, string role, Type ofObjectToReturn) {     System.Net.WebRequest request = WebRequest.Create(absoluteUri);     request.Timeout = TIMEOUT;      System.Net.WebResponse response = request.GetResponse();     if (response == null)         throw new XmlException("Could not resolve external entity");      Stream responseStream = response.GetResponseStream();     if (responseStream == null)         throw new XmlException("Could not resolve external entity");     responseStream.ReadTimeout = TIMEOUT;      return new LimitedStream(responseStream, MAX_RESPONSE_SIZE); }
   
 
  ').'[/code]'Finally, add one more defense-in-depth measure by blocking entity resolution of URIs that resolve to the local host (see Figure 5).This  includes URIs starting with http://localhost, http://127.0.0.1, and  file:// URIs. Note that this also prevents a very nasty information  disclosure vulnerability in which attackers can craft entities pointing  to file://resources, the contents of which are then duly retrieved and  written into the XML document by the parser.
 Figure 5 Blocking Local Host Entity Resolution

''.str_replace('
', '', '    
public override object GetEntity(Uri absoluteUri, string role,     Type ofObjectToReturn) {     if (absoluteUri.IsLoopback)         return null;     ... }
   
 
  ').'[/code]'Now that you’ve defined a more secure XmlResolver, you need to  apply it to XmlReader. Explicitly instantiate an XmlReaderSettings  object, set the XmlResolver property to an instance of XmlSafeResolver,  and then use the XmlReaderSettings when creating XmlReader, as shown  here:

''.str_replace('
', '', '    
XmlReaderSettings settings = new XmlReaderSettings(); settings.XmlResolver = new XmlSafeResolver(); settings.ProhibitDtd = false; // comment out if .NET 4.0 or later settings.DtdProcessing = DtdProcessing.Parse;  // comment out if                                                 // .NET 3.5 or earlier settings.MaxCharactersFromEntities = 1024; XmlReader reader = XmlReader.Create(stream, settings);
   
 
  ').'[/code]'Additional ConsiderationsIt’s important to note that  in many of the System.Xml classes, if an XmlReader is not explicitly  provided to an object or a method, then one is implicitly created for it  in the framework code. This implicitly created XmlReader will not have  any of the additional defenses specified in this article, and it will be  vulnerable to attack. The very first code snippet in this article is a  great example of this behavior:
''.str_replace('
', '', '

void processXml(string xml) {     System.Xml.XmlDocument document = new XmlDocument();     document.LoadXml(xml); }
   
 
  ').'[/code]'
This code is completely vulnerable to all the attacks  described in this article. To improve this code, explicitly create an  XmlReader with appropriate settings (either disable inline DTD parsing  or specify a safer resolver class) and use the  XmlDocument.Load(XmlReader) overload instead of XmlDocument.LoadXml or  any of the other XmlDocument.Load overloads, as shown in Figure 6.

 Figure 6 Applying Safer Entity Parsing Settings to XmlDocument

''.str_replace('
', '', '    
void processXml(string xml) {     MemoryStream stream =         new MemoryStream(Encoding.Default.GetBytes(xml));     XmlReaderSettings settings = new XmlReaderSettings();      // allow entity parsing but do so more safely     settings.ProhibitDtd = false;     settings.MaxCharactersFromEntities = 1024;     settings.XmlResolver = new XmlSafeResolver();      XmlReader reader = XmlReader.Create(stream, settings);     XmlDocument doc = new XmlDocument();     doc.Load(reader); }
   
 
  ').'[/code]'XLinq is somewhat safer in its default settings; the XmlReader  created by default for System.Xml.Linq.XDocument does allow DTD  parsing, but it automatically sets MaxCharactersFromEntities to  10,000,000 and prohibits external entity resolution. If you are  explicitly providing an XmlReader to XDocument, be sure to apply the  defensive settings described earlier.
Wrapping UpXML  entity expansion is a powerful feature, but it can easily be abused by  an attacker to deny service to your application. Be sure to follow the  principle of attack surface reduction and disable entity expansion if  you don’t require its use. Otherwise, apply appropriate defenses to  limit the maximum amount of time and memory your application can spend  on it.  
Bryan Sullivan is a security program  manager for the Microsoft Security Development Lifecycle team,  specializing in Web application and .NET security issues. He is the  author of “AJAXSecurity” (Addison-Wesley, 2007).
__________

Ọbádélé Kambon, PhD
Nana Kwame Pɛbi Date I, Ban mu Kyidɔmhene, Akuapem Mampɔn
Senior Research Fellow & Research Coordinator - Language, Literature and Drama Section
Institute of Kmtyw Studies - College of Humanities
Editor-in-Chief - Ghana Journal of Linguistics
Secretary (2015-2020) - Kmtyw Studies Association of Kmt
+233249195150 / +19192836824 | me@obadelekambon.com
www.obadelekambon.com | www.abibitumi.com
Room 115 IAS Kwame Nkrumah Complex
University of Ghana - Legon
Alternate Email: obkambon@staff.ug.edu.gh



Ọbádélé Kambon App



Abibitumi.com App