The App Compat Guy

Chris Jackson's Semantic Consonance

August, 2005

  • The App Compat Guy

    Cookieless Session State Scenarios

    • 0 Comments
    The other day, I was working through a problem that a customer was having while using cookieless session state in ASP.NET. This got me thinking about when this is an appropriate approach to take.
     
    Many web developers are concerned about their ability to support a browser that does not accept cookies. While it is quite uncommon for somebody to have a browser that doesn't support cookies these days, it is still possible that somebody has a browser that supports it, but they have explicitly turned off this functionality.
     
    There are a limited number of places to place data to emulate a session on the web. You can place data in the URL (the query string), you can place data in the headers (cookies are contained in headers that the browser manages for you), and you can place data in the body of the post (such as a hidden form field). Since it's difficult to control the headers on the client without explicit support like Cookies have, and since not every web request a client will make to your site will be a POST, the remaining option is to use the URL. ASP.NET mangles the URL in order to embed the session ID.
     
    Of course, this opens up social engineering security vulnerabilities. With a non-persistent cookie, all but the most absolutely technically proficient users will be unable to even find this session identifier, and convincing somebody to take these steps would be extraordinarily unlikely indeed. With a persistent cookie, it would still be difficult to convince somebody to dig in to their Cookies folder, locate and grab the one for that site, and then send it to the person who intends to spoof that identity. However, with the session identifier embedded in the URL, all it takes is a request to "send me a link to that page." The unknowing victim opens up the browser, navigates to that page, copies the URL (by this time, users are so accustomed to having long and complicated URLs that they don't think twice about the unusual sequence of characters in the middle), pastes it into an email, and now (assuming they get to the site before the session expires) the attacker has the ability to spoof the identity of that session.
     
    This, of course, is nothing new. As with any securable resources, it is a matter of making a trade-off. How valuable is the reach of the application, compared to the value of the information you are hoping to secure? What was interesting about this particular scenario is that they were implementing cookieless session state in a scenario where the probability of cookies being disabled is either extremely unlikely or outright impossible.
     
    One scenario was an intranet example. Since it was an intranet application, they were using Windows Authorization. Of course, this implies that the web site itself will be living in the Local Intranet security zone, since by default this is the only zone where a token will be passed. If you go in to Internet options, click on the Privacy tab, and crank up the privacy to Block All Cookies, you will notice that cookies will still work in the Local Intranet zone. This setting applies to the Internet zone! (Trusted Sites are also exempted from this, giving you the option of accepting cookies from sites that you explicitly trust, and not accepting them from anybody else.) Now, it is possible to disable cookies in the Local Intranet zone. One way is to create a Customized Privacy Import File. But exactly how likely will it be that somebody will go to this amount of trouble to disable cookies in the Local Intranet zone, and how often will the best answer be to invest resources and accept lowered security in order to support an employee going to these lengths to disable functionality from their own company? In my view, it is unlikely to the point of not being a meaningful consideration.
     
    The other scenario was an extranet scenario, where they did not want to have a dependency on cookies. There were two problems that I saw. One was important, but not decisive. They were holding some reasonably valuable information in session state, so the decision whether or not to increase the exposure of this information was one to be carefully contemplated. More importantly, they were using forms authentication. In both 1.0 and 1.1 of the framework, forms authentication is always based on cookies. If a client doesn't accept cookies, they cannot even get in to the application. Given this, is there any value in supporting cookieless session state, since no cookie-disabled user will ever be able to create a session anyway since they can never authenticate? Obviously not! Now, the 2.0 framework will support cookieless forms authentication, but until that time, it is additional security exposure to support a scenario that can never exist.
     
    So, in addition to understanding how cookieless session state affects the overall security of your application, consider as well whether this is a scenario that is likely, or even possible, for the client to be facing.
  • The App Compat Guy

    Defining Units of Selection

    • 0 Comments
    In my previous posts, I discussed the concepts of non-random selection and arms races. With this understanding in mind, we can start to see a very important concept arise.
     
    Accurately defining the unit of selection is absolutely critical to effectively evolving your software.
     
    It is all too easy to introduce pleiotropy into software. Pleiotropy in biology is the ability for a single gene to cause multiple phenotypes. For example, some cats have a particular allele which makes them white, and they also happen to be deaf. Other alleles may cause changes in the face, ears, and hair - all from a single gene. In software, this principle generally expresses itself as unintended consequences - generally these are bugs.
     
    Once we put these two concepts together, we gain some very important architectural learning, which will come as no surprise whatsoever to any software engineer: you want to design your software so that modification to one system do not adversely produce unintended side effects. While it seems quite obvious, it is not always that straightforward to execute on this.
     
    Furthermore, you would also like to architect your system to enable you to select into the next generation of your software those implementations which have given your software an evolutionary advantage, while mutating those elements of your system which have not given your software the competitive advantage you had hoped for.
     
    A highly visible illustration of this notion comes with the separation of user interface from business action. This is a pattern that has been around for quite some time, most commonly known as model-view-controller. As the user interface is something that is highly likely to change (this is the component that is most visible to the user, and tastes tend to change over time), you would like to be able to select those UI elements which make your software easy to use, while mutating those that are not comprehensible enough to surface a given functionality. Nonetheless, it is very common to see many logical dependencies sitting inside of UI code. How many web development projects on ASP.NET, for example, have you seen with business logic code sitting in the code-behind for a given page? How many button handlers in a Windows Forms application immediately take some action right inside of a form user interface object?
     
    Once you begin thinking of your software with the goal of explicitly defining your units of selection, you can begin to architect your solution to achieve this goal.
     
    As an example, consider the architectural changes being undertaken for Windows Vista. Larry Osterman provides a description of this layered architecture here. In essence, what the Windows team has created is a system of layers wherein components in a given layer should not have a dependency on components in a higher layer. The lower a component lives in this layered system, the higher the probability of pleiotropy. As a result, low level components have been set up to evolve slowly and deliberately, as changes will involve extensive testing of all higher-layer components. Components that sit in a high layer are now able to evolve far more quickly, because there is a much smaller chance of pleiotropy in these components. Not only can they do so, but there is an implicit statement that they both want and expect to do so.
     
    This is an appropriate starting point to architecting your software to evolve - explicitly defining those components which can be rapidly evolved. And, in any reasonably complex software project, this is an important statement to make, and it should be explicit.
  • The App Compat Guy

    Selection and Evolutionary Arms Races

    • 0 Comments

    Selection is the basis by which evolution can develop the enormously complicated systems that exist today. The underlying principal is non-random selection of random mutations. In any organism, there is some degree of genetic drift. Despite the built-in error correction of DNA replication, mutations still occur, and they occur randomly. I should be explicit here - they occur randomly with regards to the phenotype of that mutation. Some mutations will produce a phenotype that is non-selective. In other words, an individual who possesses that phenotype is neither more likely nor less likely to survive. Other mutations will be beneficial, increasing the likelihood of survival. Still others will be detrimental, decreasing the likelihood of survival. Because selection is non-random, it will usually select the phenotype that has superior survivability characteristics. So, a single mutation that increases, however slightly, the ability of an individual to survive, it is far more likely that the organism will, in fact, survive to reproductive age, and that this mutation will continue into the next generation.

    For example, assume that an organism randomly develops a mutation that makes a cell on its face more sensitive to light. That sensitivity allows it to see, however, vaguely, that there is a shadow moving overhead, and run away. Such an organism is likely to have sufficiently higher survivorship than its companions, be more likely to reproduce, and eventually this selection will drive the majority of the population to have this mutation. Each successive mutation that refines this detection will be selected for, and eventually you end up with an eye.

    This has a couple of assumptions, mind you. The most important one: that there are too many organisms for a given environment. A given group of organisms will produce too many offspring to ensure the survival of all of them. As a result the remaining organisms must compete to survive. Because only some of them survive, most often it will be those organisms who possess the superior phenotype - filtering out mutations that are less beneficial. The same is also true between species: if two species are competing for the same set of limited resources, then mutations that either make them more effective at competing, or else mutations that cause them to seek out a different (and less hotly contested) set of resources will be selected.

    The idea of selection is just as important for software. This process is what drives the continued evolution of software, just as it drives the continued evolution in the natural world. The only difference is that mutations are non-random (or, at least, most of them are, we hope!), but selection is the process that determines which characteristics will survive into the next generation of software, and which will not.

    The importance of selection can be seen in a couple of ways. The first is in determining the evolutionary rate. Consider, first, the amount of competition for a limited set of resources. In this case, these resources will likely be either money or time. If there is a great deal of competition, then your software is likely to evolve fairly quickly. If there is not much competition, then the evolutionary rate is likely to slow. Mutations may still take place, but without a set of selection criteria these mutations will not survive based on merit, but will simply be part of the genetic drift.

    You can find an excellent example with web browsers. Once people began to realize that they really needed to have a web browser, then resources opened up to consume them. However, this set of resources was limited: people generally were content to have a single web browser. So, the competitors were vying for this resource, to become the choice. This spurned rapid innovation in the web browser market, as competitors struggled for their very survival against other web browsers. Eventually, one browser came to be the victor, consuming the vast majority of the resources (installed desktops) available in the market. The competition died down, and so did the innovation. Even assuming that development continued at the same rapid pace on the product, without contention for resources, there would have been no way to select specifically for those features which are of the greatest tangible benefit to users, against those features that are pure genetic drift. The product simply cannot evolve as quickly.

    However, once competition emerged again, selection could come back into play. Features could be added to enhance the product, and those features that drove adoption would be selected for, driving evolution for more rapidly. Non-random selection is critical.

    It is important to keep in mind, however, that all mutations in a software organism that the environment is currently selecting for are not necessarily the unit of causation of that selection. If you come up with a new browser that supports tabbed browsing, a new security model, and the ability to render all pictures in shades of purple instead of full color, can you necessarily say that rendering all pictures in shades of purple were instrumental in the success of the product? In much the same way, can you say that tabbed browsing is a mutation that is selected for, or was it actually security that was selected for? It is important not to conflate the issues; the environment, given a degree of competition, will provide selection. However, you can not always interpret any one factor as being key to the success of an adaptation.

    An even more extreme scenario comes with evolutionary arms races. Competition for a limited set of resources drives rapid evolutionary change. Competition for immediate survival compels even more rapid evolutionary change. Consider the evolution of the cheetah and the antelope. The antelope will evolve to run away more quickly. An antelope with a mutation that will allow it to run a little bit faster will have a much greater chance of survival into the next generation. By the same token, a cheetah with a mutation that enables it to run a little bit faster will catch more food, thus increasing the chance of this mutation surviving to the next generation. Here, the success of one organism definitively means the failure of the other. This is an arms race: in this scenario, evolution takes place very quickly.

    The most direct analogy here is towards security. Software that evolves to be more secure is more likely to survive. So, the attackers become more sophisticated, creating new malicious software able to overcome these obstacles. Both sides evolve their software more rapidly than in any other evolutionary environment. But, in this case, there is some degree of hope for everyone who is trying to develop secure software while facing attacks from continually more sophisticated attackers. To quote Richard Dawkins, "if the predator loses the race, he simply loses a meal. If the prey loses the race, he loses his life." The pressure is on everyone developing software to make it more secure, or they will lose altogether. Thus, it seems likely that many will be able to maintain this accelerated evolutionary rate, because they simply have no choice.

    Understanding the environment your software is critical to guiding its evolution. What are the resources? Who is competing for them? And what features are actually being selected for? This is a powerful principal that has done amazing things with nature, and can do similarly amazing things for software when they are leveraged.

Page 1 of 1 (3 items)