-
23 Nov 2009 11:50 AM #101
Putting my money where my mouth is, here is what I think would be an ideal solution:
- Create a property similar to .NET's Literal.Mode property which defines the behavior of a Literal's rendering engine. If it's set to "PassThrough" it simply dumps the string as provided directly to the browser. If however it is set to "Encode" it HTMLEncode's the string before doing so.
- Add this property to every Ext component that is responsible for writing strings, such as Grid Columns, Message Boxes, Panels, etc.
- Allow the developer to specify this value on a component-by-component basis, but default it's value to a new global variable..
- Create the global variable EXT_TRUST_MODE which ships with the value related to "Encode".
What this does is allow us to say that by default as Ext ships, all data is considered untrusted and thus encoded, however if we need a specific control to pass raw data through (because we trust the source of the data) then we can simply {trustMode: 'passthrough'} or whatnot.
Additionally, to handle the situation of breaking backwards compatibility of old implementations of Ext, we can simply inform those people that they may change the default value of EXT_TRUST_MODE to 'passthrough' defaulting all controls to do so (albeit with the warning of the security problems this may cause.)
I sincerely hope that this discussion and the ideas I have proposed are helpful. I truly believe that this is a big problem, but one that Ext can fix, making Ext an even better platform for serious developers.
-
8 Dec 2009 2:42 AM #102
I've spent hours trying to figure out how to do this.
Would you care to tell me?
Edit
I made some custom Components that take care of the issue:
http://www.extjs.com/forum/showthread.php?p=418233
-
19 Jan 2010 2:06 PM #103
I am strongly on the "ExtJS should encode by default" side.
The biggest argument is that a system's behavior should default to the safer option.
And yes, the current default behavior is prone to XSS - I don't really understand how that can be the point of an argument. For example one user saves a record representing a company with name field "ACME Corp.<script>...send-me-your-session-cookie...</script>" and another users views a grid with a list of companies.
You _could_ scrub the input on the server side, but you could also treat all data as potentially "tainted" on the client.
My strategy is:
- Store everything literally in the DB.
- Exclusively use prepared statements to prevent SQL injection.
- Let the client escape special characters (unless configured otherwise for special cases)
At the very least it should be easy to set a single flag somewhere to have ExtJS encode special characters.
For the grid panel (in ExtJS 3.1) I found a simple solution:
A couple additional characters that make ExtJS a lot safer by default.PHP Code:Ext.grid.ColumnModel.prototype.defaults = {
renderer: function(value) {
if (typeof value == "string") {
return value.length < 1 ? " " : this.escape === false ? value : Ext.util.Format.htmlEncode(value);
}
return value;
}
};
You can disable the encoding by setting "escape: false" in a column's config.
-
5 May 2010 7:41 AM #104
That's obvious, we can't stop users from attacking themselves, naturally. But the configuration defaults on the Grid component result in many real world applications letting users attack other users.
If you mean, "1 user of the same web application" - that's true most frequently, but not always!
Jack, it seems to me that you don't fully understand the threat model here.
XSS can also be used in other scenarios - for example (note: that's only one example) by an attacker who does not have user access to the given web application, but has managed to gain UPDATE/INSERT access to its database (e.g. SQL injection in a different application that shares this database, direct OS-level access).
In the above scenario, the attacker can stage a XSRF attack (using scripts inserted directly into the database) on a targeted user of the application to unknowingly perform operations chosen by the attacker on a second, unrelated web application.
For example, if the victim has two applications open in the browser - ExtJS-based application A, and a CRM application B whose admin he/she is, the attacker could insert a malicious script (<span onclick="do_bad_stuff_on_application_B">Some field value</span>) to the A's database, and when executed in the victim's browser context, that script would create a new account in application B for the attacker to use.
This is not purely theoretical. Similar (although possibly less or more sophisticated) attacks were recently used by Chinese to stage industrial espionage attacks against Google and Adobe employees, or in the recent attack by unknown perpetratos on JBoss and Apache Software Foundation's JIRAs.
No it's not, for a number of reasons:
1) It would not defend against the threat that I've described above. The filtering is just performed too early and data travels through multiple layers before it finally arrives in a user's browser where it becomes dangerous because of being interpreted as HTML. After this form of filtering you still have a range of attacks left unaccounted for.
2) It would unneededly mutilate data which might be useful in other contexts, where "XSS-dangerous" characters are needed and safe - e.g. PDF reports, generated bitmap images, plain text extracts from the database. Suddenly getting all the "<" and ">" characters removed or substituted with "<" and ">" is silly and short sighted. In other words, the data may as well not go to a web browser, but to a PDF report and stripping supposedly dangerous characters would interfere with this.
3) It mixes unrelated things - relational database is not a proper place for data pre-filtered for a HTML document. There's no threat whatsoever to a relational database itself from text with HTML tags lying in some fields of some rows in that database. The text content resident in the database should be neutral from any presentation technology that it might be later destined for. The filtering should take place exclusively when it becomes known with certainty that the data goes to a HTML document's element in some user's browser.
4) The most respectable source of best practices in web application security - OWASP - advises otherwise:
This being considered, the most proper way is to filter data shortly before it is going to be displayed, but on the server side.While input validation is important and should always be performed, it is not a complete solution for injection attacks. It's better to think of input validation as defense in depth and use escaping as described below as the primary defense.
...
Escaping is the primary means to make sure that untrusted data can't be used to convey an injection attack. There is no harm in escaping data properly - it will still render in the browser properly. Escaping simply lets the interpreter know that the data is not intended to be executed, and therefore prevents attacks from working.
True, ExtJS is not responsible for this, but any solution that combines ExtJS and server side code is (e.g. Ext GWT framework).
Still, considering that many developers seem to assume that ExtJS will default to HTML-encoding text before displaying (I would assume that myself, too, and I've seen numerous other developers do that), it would be wiser to switch the defaults so that it does encode, e.g. using the Ext.util.Format.htmlEncode renderer.
An alternative solution would be to make wider use of strong typing in Ext.data.Record, adding a "html" data type, and by default always encoding values that have the "auto" or "string" type.
If a developer wants the old ExtJS behaviour, he would have to knowingly configure the given widget for that and then take the responsibility for any XSS vulnerabilities introduced if the server side doesn't filter data fed to Ext widgets. In other words, the defaults should side on the more secure configuration, with risky configuration available when needed. BTW, there's an OWASP recommendation covering that, too.
If ExtJS did that, even given negligence on the server side, the attacks described above would fail (masochistic usage of FireBug aside).
Nowadays it is reasonable to expect the encoding to occur, since almost all other frameworks do that (ASP.net, Java Server Faces etc).
watrboy00, don't mix different issues.
SQL injection is a completely different animal, and it's mostly a problem of the past if you use stored procedures with bound parameters or an object-relational mapping framework like Hibernate.
With those, you can put any amount of 's, "s, --s and other characters in text data persisted into database and not worry about any problems.
SQL injection is a problem only for people stuck in the SQL query concatenation paradigm.
Also, what you propose would damage the data for non-HTML usages, like I've described above.
-
5 May 2010 11:27 PM #105
I think the ExtJS developers collectively would save a lot of time if the toolkit encoded to html by default. If you add up the thousands of hours spent typing Ext.util.Format.htmlEncode, that's a lot of lost productivity. Yes, everyone can implement their own hacks on top of the framework to do the magic for them, but the basic question is: why should they?
-
18 Jun 2010 3:44 AM #106
I'd just like to weigh in on this (old) discussion. Ext JS really should escape all input.
The problem
Consider a web app using a JSON api. All serious JSON apis send raw data. They do not html encode the data over the wire! Examples are the twitter api, amazon api, google api. I'm not talking about CSS, I just mean they send "some tweet by <adam>" not "some tweet by <adam>".
So this means we must htmlescape() on the client side when we recieve the data before we write to the DOM. The only question is who is responsible for the escaping.
Who is responsible?
I believe Ext is responsible. Why?
- The framework should protect beginners from this problem
- Ext has a well defined set of widgets for which to escape. My point being once you've written a big insecure web application its probably more sensible to subclass all the Ext widgets you use and implement escaping anyway. So this should just happen in Ext.
- As mentioned earlier the naming of properties and methods is not consistient. Consider TreeNode::setText which does not escape input. This should be called TreeNode::setHTML
http://code.djangoproject.com/wiki/AutoEscaping
http://groups.google.com/group/djang...62232b73?pli=1
http://groups.google.com/group/djang...c34ce7cc96e283
The only real rationale I can think of for not doing this is lack of resources which is fair enough. But right now Ext makes it very hard to write a complex secure webapp.
-
18 Jun 2010 9:39 AM #107
Ext doesn't make it hard to write a complex secure web application. The simple truth is people often don't plan their web applications properly. With a few exceptions, if the data you're providing to your Ext application is from an untrusted data source (ie, one in which you do not have control over the content of the data) the most secure method to do so is to use proxy services within your backend to collect and escape that data. Adding an escaping layer to Ext pushes an inordinant amount of work to the browser. Since browsers are unpredictable and variable you could literally stifle the performance of the web application for users running on less powerful workstations. And believe me, there are plenty of those machines still around the Internet.
With some simple planning on the backend, this issue can be completely mitigated and remains fully scalable.
-
19 Jun 2010 2:57 AM #108
No it doesn't. I escape almost all my text client-side, and the overhead of doing that is negligible.
Anyway, I thought the whole idea with ExtJS was that you loaded raw data into data stores, and then tied renderers to that to make the data appear on the screen. Entity-encoding on the server just doesn't blend with that approach, no matter how you plan your app. Currently with Ext I have to type Ext.util.Format.htmlEncode a lot, or patch the library to do it for me. Neither of those are very appealing. Even if it was disabled by default, some sort of "global" entity-escaping logic would be VERY welcome.
-
5 Jul 2010 5:39 AM #109
I don't think your doing justice to developers making this mistake appealing to bad planning. I think this is something you would reasonably expect a framework to take care of for you.
What makes you say that using a proxy is more secure? It's less efficient and will lower the scalability of your application. It adds complexity to the system and lowers reliablity. I strongly suspect it is also _much_ quicker to not use a proxy and htmlescape on the client side since it avoids some network latency and certainly will not "stifle the performace" of your webapp.
And are browsers unpredictable? Well yes but thats the point of frameworks like Ext and jQuery. To present a consistent interface for the application developer. Are you suggesting Ext.util.Format.htmlEncode is not cross-browser compatible?
-
5 Aug 2010 7:32 AM #110
Solutions?
Solutions?
I absolutely agree that escaping data for HTML is a fundamental concern of an HTML presentation layer. Your data is not HTML, and when it is added to an HTML document it must be escaped. There is a barrier there, and if you want break through the barrier (in the rare case that your internal data is actual HTML text) then you should have to explicitly declare that.
Is there any hope at all that EXT will correct this fundamental mistake or at least provide a mechanism for getting EXT to default to more sane behavior? In the mean time, is there any consensus on what the best way to get EXT to consistently escape all HTML unless told not to? I see lots of different suggestions, but it's not clear to me what the best approach is.


Reply With Quote
etText which does not escape input. This should be called TreeNode: