Ruby on Rails | Screencasts | Download | Documentation | Weblog | Community | Source

Changeset 6556

Show
Ignore:
Timestamp:
04/24/07 03:31:14 (1 year ago)
Author:
sam
Message:

prototype: Automatically strip security delimiter comments from JSON strings before evaling them. The default delimiter is '/*-secure- ... */' or you can specify your own with the Prototype.JSONFilter regular expression. If you wrap your JSON response bodies in this delimiter on the server side, rogue external sites can't hijack potentially sensitive data via <script> tags. Closes #7910.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • spinoffs/prototype/trunk/CHANGELOG

    r6555 r6556  
    11*SVN* 
     2 
     3* Automatically strip security delimiter comments from JSON strings before evaling them.  The default delimiter is '/*-secure- ... */' or you can specify your own with the Prototype.JSONFilter regular expression.  If you wrap your JSON response bodies in this delimiter on the server side, rogue external sites can't hijack potentially sensitive data via <script> tags.  Closes #7910.  [Tobie Langel] 
     4  For more details on potential security problems, see: http://www.fortifysoftware.com/servlet/downloads/public/JavaScript_Hijacking.pdf 
    25 
    36* Add extra spacing so Array#toJSON and Hash#toJSON generate YAML-loadable JSON.  Closes #7883.  [Andrew Dupont] 
  • spinoffs/prototype/trunk/src/ajax.js

    r6059 r6556  
    213213    try { 
    214214      var json = this.getHeader('X-JSON'); 
    215       return json ? eval('(' + json + ')') : null; 
     215      return json ? json.evalJSON() : null; 
    216216    } catch (e) { return null } 
    217217  }, 
     
    219219  evalResponse: function() { 
    220220    try { 
    221       return eval(this.transport.responseText); 
     221      return eval((this.transport.responseText || '').unfilterJSON()); 
    222222    } catch (e) { 
    223223      this.dispatchException(e); 
  • spinoffs/prototype/trunk/src/prototype.js

    r6501 r6556  
    1010    Gecko:  navigator.userAgent.indexOf('Gecko') > -1 && navigator.userAgent.indexOf('KHTML') == -1 
    1111  }, 
     12 
    1213  BrowserFeatures: { 
    1314    XPath: !!document.evaluate, 
     
    1718       document.createElement('form').__proto__) 
    1819  }, 
     20 
     21  ScriptFragment: '<script[^>]*>([\u0001-\uFFFF]*?)</script>', 
     22  JSONFilter: /^\/\*-secure-\s*(.*)\s*\*\/\s*$/,   
    1923   
    20   ScriptFragment: '<script[^>]*>([\u0001-\uFFFF]*?)</script>', 
    21   emptyFunction: function() {}, 
     24  emptyFunction: function() { }, 
    2225  K: function(x) { return x } 
    2326} 
  • spinoffs/prototype/trunk/src/string.js

    r6489 r6556  
    164164  }, 
    165165 
     166  unfilterJSON: function(filter) { 
     167    return this.sub(filter || Prototype.JSONFilter, '#{1}'); 
     168  }, 
     169 
    166170  evalJSON: function(sanitize) { 
     171    var json = this.unfilterJSON(); 
    167172    try { 
    168       if (!sanitize || (/^("(\\.|[^"\\\n\r])*?"|[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t])+?$/.test(this))) 
    169         return eval('(' + this + ')'); 
    170     } catch (e) {
    171     throw new SyntaxError('Badly formated JSON string: ' + this.inspect()); 
     173      if (!sanitize || (/^("(\\.|[^"\\\n\r])*?"|[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t])+?$/.test(json))) 
     174        return eval('(' + json + ')'); 
     175    } catch (e) {
     176    throw new SyntaxError('Badly formed JSON string: ' + this.inspect()); 
    172177  }, 
    173178   
  • spinoffs/prototype/trunk/test/unit/string.html

    r6489 r6556  
    431431      assertRaise('SyntaxError', function(){dangerous.evalJSON(true)}); 
    432432      assertEqual("Not scared!", attackTarget); 
    433      }} 
     433 
     434      assertEqual('hello world!', ('/*-secure-\n' + valid + '\n*/').evalJSON().test); 
     435      var temp = Prototype.JSONFilter; 
     436      Prototype.JSONFilter = /^\/\*(.*)\*\/$/; // test custom delimiters. 
     437      assertEqual('hello world!', ('/*' + valid + '*/').evalJSON().test); 
     438      Prototype.JSONFilter = temp; 
     439    }} 
    434440  }, 'testlog'); 
    435441// ]]>