Given some of the feedback I've received during the first couple of weeks after releasing DOM Snitch, I'd like to shed more light into some of the inner workings of DOM Snitch and the rationales behind some of the decisions that were made while building the tool.
Topic 1: Why is DOM Snitch not catching security issues executing at load time through inline JavaScript?
In its current implementation, DOM Snitch is set to start running on a page as soon as the DOMWindow object is created, but before the DOM tree is built. This allows the extension to act either as soon as it's instantiated or when any of the DOM modification events get dispatched. Relying on the events, however, comes with a cost and that is the inability to know what caused the event to be dispatched in the first place; therefore resulting in the tool's inability to gather proper debug information. (I should add the disclaimer that currently DOM Snitch does not use any of the V8 debugging functionality.)
Topic 2: Is DOM Snitch using any of the experimental APIs in Chrome?
The short answer is "no". One of the early goals I set while building the tool was to stay away from experimental APIs or touching the Chromium code base as doing either one of the two will get in the way of deploying easily without changing the security posture of the user. Additionally, using unsupported functionality might result in some maintenance issues further down the line. That being said, I'm quite keen on using the chrome.experimental.debugger API should it become supported by the Chromium team.
Topic 3: On innerHTML, outerHTML, and stale pointers inside JavaScript
Stale JavaScript pointers is one side effects that really worries me when intercepting innerHTML. Although, the tool has gone through lots of iterations to getting this right, I must admit that people still find creative ways to introduce a stale pointer somewhere in their code. By giving a bit more detail on how innerHTML is intercepted, I hope that developers will pay some attention as to what may go wrong in their code from a testability perspective.
In its current version, WebKit does not reveal the internal innerHTML pointers through the getter and setter methods. As a result, by overwriting the innerHTML setter, DOM Snitch loses the value of the original pointer. To counter this, DOM Snitch re-creates the action of setting an element's innerHTML by appending a new child element and setting the child's outerHTML to the intended innerHTML value ( and as it turns out, this will force WebKit to throw away the newly created child element and replace it with whatever children that get introduced through the HTML content). You can see this implementation here.
Showing posts with label testing. Show all posts
Showing posts with label testing. Show all posts
Jul 23, 2011
Feb 25, 2011
The evil magic of eval
Eval is a special, very powerful function in many scripting languages. JavaScript is not an exception. Although quite useful for dynamic manipulation of the existing code, any misuse of eval can cause a lot of problems and headaches. StackOverflow covers this topic well, with the exception of one very important bit: eval can get in the way of testability.
Static analysis
With JavaScript being what it is, it is easy to assume that one can painlessly audit the scripting code that runs inside the browser and understand how the client-side part of a web application functions. Well, that's not entirely true. With web applications becoming more complex, we often run into cases where we have a 60k line obfuscated code that looks a lot like this:
How should this be tested or audited? Simple answer: you can't really or at least not easily.
Dynamic analysis
This leads me to the next bit: what about dynamic analysis? What if we "hook" into eval and listen to the code as it goes by? As it turns out, this isn't a fool proof solution either. Eval is not exactly a function. In fact, if you ask any experienced developer, he/she may flat out tell you that eval is magic and should not be touched. To re-use the example from StackOverflow, what value should the alert box show?
As it turns out, eval is aware of the current scope from which it was called; therefore the alert box will show 2 and not 11. This is important because as you overload eval, you change the scope in which it operates (off by 1 stack frame). As a result eval will attempt to manipulate a global object and not the local one. This in turn may lead to a half baked page.
Conclusion
Although eval is very powerful, it is also overly misused for parsing and/or processing data (example: using eval to parse JSON). In a nutshell, eval provides one of the easiest ways to mix code and data... a dangerous thing to do nowadays.
P.S. - Although some browsers (namely Firefox) may allow you to overload eval at a lower level through an extension, it is not necessarily the same case with all mainstream browsers; therefore, some edge cases may be missed.
Static analysis
With JavaScript being what it is, it is easy to assume that one can painlessly audit the scripting code that runs inside the browser and understand how the client-side part of a web application functions. Well, that's not entirely true. With web applications becoming more complex, we often run into cases where we have a 60k line obfuscated code that looks a lot like this:
function a() {
this.c = eval;
}
...
var b = a();
var d = b.c(e);How should this be tested or audited? Simple answer: you can't really or at least not easily.
Dynamic analysis
This leads me to the next bit: what about dynamic analysis? What if we "hook" into eval and listen to the code as it goes by? As it turns out, this isn't a fool proof solution either. Eval is not exactly a function. In fact, if you ask any experienced developer, he/she may flat out tell you that eval is magic and should not be touched. To re-use the example from StackOverflow, what value should the alert box show?
var a = 10;
function foo() {
var a = 1;
eval("a+=1");
alert(a);
}
foo();
As it turns out, eval is aware of the current scope from which it was called; therefore the alert box will show 2 and not 11. This is important because as you overload eval, you change the scope in which it operates (off by 1 stack frame). As a result eval will attempt to manipulate a global object and not the local one. This in turn may lead to a half baked page.
Conclusion
Although eval is very powerful, it is also overly misused for parsing and/or processing data (example: using eval to parse JSON). In a nutshell, eval provides one of the easiest ways to mix code and data... a dangerous thing to do nowadays.
P.S. - Although some browsers (namely Firefox) may allow you to overload eval at a lower level through an extension, it is not necessarily the same case with all mainstream browsers; therefore, some edge cases may be missed.
Jan 28, 2011
The importance of the end-user experience: internationalization
A friend of mine always says: "I don't want more features. I want working features." This friend is also a big fan of Apple and the simple, clean, pleasant, intuitive user interfaces. In principle I agree with him (although I'm not an Apple fan boy), but I'd also like to add that software should work not only in its own little environment, but also in the user's environment.
I've ranted time and time again about the importance of localization and internationalization privately that I think it's time I express my opinion in the public. I'd like to pick on the Apple iTunes Store as an example and point out some of the reasons for my rants.
Here it goes...
Different country means different store.
Be it due to legal issues or some business strategy, Apple has decided separate entities to operate each store at the country level. So for instance, an Inc. operates the U.S. store, a B.V. operates the Dutch store, and so on. One thing worth of noting is that the content in each store differs. While the U.S. store offers games, music, movies, and so on, the Bulgarian store, for example, offers only a limited subset of the iOS apps that are available to U.S. customers.
Transferring from one store to another you ask? Not so easy. Buying a product in the Dutch store does not guarantee that you will receive your updates if you change to the Bulgarian or U.S. stores. Sure, you will get notified that your apps are out of date and a determined attacker may use them to compromise your email and private messaging... but in reality, the app you've installed has been purchased from a separate entity and is not available at the store which you are using. This brings me to the next point...
Your billing address determines your locale.
This is the fun bit in Apple's model. Everything is tied to the customer's payment card. Here is a trivial question: you're an expat living in the U.K., having just moved from Germany (thus having a credit card from a German bank), and are receiving your monthly statements in the Netherlands. Which locale of the Apple Store would you say you are using? The Dutch of course, your billing address is in the Netherlands.
Your locale determines your language.
Here's even the better question: what are the supported languages for your locale? English? German? Actually... Dutch is the only supported language in the Dutch locale. It's sad to see big companies like Apple deciding for their users that if a user receives his/her bank statements in a given country, then he/she surely speaks the local language.
So why am I sharing all this? Well... I for once experienced it as a user. It is not pleasant and it turns users away. Users deserve the right to use software at their own comfort level without being victims of engineering mistakes. Let's learn from this.
I've ranted time and time again about the importance of localization and internationalization privately that I think it's time I express my opinion in the public. I'd like to pick on the Apple iTunes Store as an example and point out some of the reasons for my rants.
Here it goes...
Different country means different store.
Be it due to legal issues or some business strategy, Apple has decided separate entities to operate each store at the country level. So for instance, an Inc. operates the U.S. store, a B.V. operates the Dutch store, and so on. One thing worth of noting is that the content in each store differs. While the U.S. store offers games, music, movies, and so on, the Bulgarian store, for example, offers only a limited subset of the iOS apps that are available to U.S. customers.
Transferring from one store to another you ask? Not so easy. Buying a product in the Dutch store does not guarantee that you will receive your updates if you change to the Bulgarian or U.S. stores. Sure, you will get notified that your apps are out of date and a determined attacker may use them to compromise your email and private messaging... but in reality, the app you've installed has been purchased from a separate entity and is not available at the store which you are using. This brings me to the next point...
Your billing address determines your locale.
This is the fun bit in Apple's model. Everything is tied to the customer's payment card. Here is a trivial question: you're an expat living in the U.K., having just moved from Germany (thus having a credit card from a German bank), and are receiving your monthly statements in the Netherlands. Which locale of the Apple Store would you say you are using? The Dutch of course, your billing address is in the Netherlands.
Your locale determines your language.
Here's even the better question: what are the supported languages for your locale? English? German? Actually... Dutch is the only supported language in the Dutch locale. It's sad to see big companies like Apple deciding for their users that if a user receives his/her bank statements in a given country, then he/she surely speaks the local language.
So why am I sharing all this? Well... I for once experienced it as a user. It is not pleasant and it turns users away. Users deserve the right to use software at their own comfort level without being victims of engineering mistakes. Let's learn from this.
Labels:
daily life,
testing
Sep 7, 2009
The 7 plagues of testing
James Whittaker was running the series of the 7 plagues of software testing on the Google Testing Blog. Since the series are at their last stretch, here is the list of plagues:
1. The Plague of Aimlessness
2. The Plague of Repetitiveness
3. The Plague of Amnesia
4. The Plague of Boredom
5. The Plague of Homelessness
6. The Plague of Blindness
7. The Plague of Entropy
There are also some additional plagues that were suggested by various readers (myself included):
- The Plague of Metrics
- The Plague of Semantics/Assumptions
- The Plague of Infinity/Endlessness/Exhaustion
- The Plague of Miscommunication/Language
- The Plague of Rigidness/Complacency
Out of the suggested bunch, I really like Roussi's notion that complacency can be the result of a product's success.
1. The Plague of Aimlessness
2. The Plague of Repetitiveness
3. The Plague of Amnesia
4. The Plague of Boredom
5. The Plague of Homelessness
6. The Plague of Blindness
7. The Plague of Entropy
There are also some additional plagues that were suggested by various readers (myself included):
- The Plague of Metrics
- The Plague of Semantics/Assumptions
- The Plague of Infinity/Endlessness/Exhaustion
- The Plague of Miscommunication/Language
- The Plague of Rigidness/Complacency
Out of the suggested bunch, I really like Roussi's notion that complacency can be the result of a product's success.
Labels:
productivity,
security,
testing
Aug 3, 2009
Recycling security test cases
Test cases are precious. In my day to day work, a lot of what we do is built around the notion that a test case either passes or fails. Think about the time when you withdraw money out of your favorite ATM or when your favorite application may have compromised your privacy... it's always the case of a passed or failed test case. Is there a flaw in the system? Can the system under test be put to its knees because of it?
A while ago James Whittaker talked about building repositories with reusable test cases. The whole discussion is available at the MSDN blogs. I definitely recommend reading it. As applications often have common flaws, it is beneficial to have such a repository. Tweaking the test cases to the application under test is definitely a "must-do". However, once those tweaks are done for the particular software under test, the job gets much easier.
Reflecting at the security industry, it's hard to not notice the need for James's idea to be adopted. In fact, a typical problem report from a security vendor will include the following bits:
A while ago James Whittaker talked about building repositories with reusable test cases. The whole discussion is available at the MSDN blogs. I definitely recommend reading it. As applications often have common flaws, it is beneficial to have such a repository. Tweaking the test cases to the application under test is definitely a "must-do". However, once those tweaks are done for the particular software under test, the job gets much easier.
Reflecting at the security industry, it's hard to not notice the need for James's idea to be adopted. In fact, a typical problem report from a security vendor will include the following bits:
- What is the problem?
- How can the problem be reproduced?
- How can the problem be fixed?
Labels:
productivity,
security,
testing,
web
Subscribe to:
Posts (Atom)