Categories:
/ (30)
discoveries/ (1)
events/ (5)
humor/ (6)
paradigms/ (3)
rants/ (3)
In computer security, the vendor of a software product is commonly seen as the entity responsible for fixing identified security issues with the product and proactively working towards better security in general. While some notable software vendors accept this challenge posed by their customers, many don't really care and handle vulnerability reports much the same way as they handle complains about a false button color in the user interface.
While we are waiting for those vendors to take a bite from the Apple from the tree of knowledge and getting banned from their imagined paradise of unbreakable software, we have some time to think about this perception of the vendor's sole responsibility for security. This commonly accepted point of view is partially based on the fact that the vendor who receives the money for the software product must care about the product's quality, security included. While I fully embrace this concept and still hope that one day, you can return software that just doesn't work as advertised [1], it is an insufficient argument when it comes to security. What about free open source software?
Intuitively, GPL software users also hold the maker of the software responsible for its security, and there is nothing wrong with that. The user extended a certain level of trust to the maker(s) by using their software and this trust gets hurt when the user gets owned. But the argument of responsibility based on a monetary transaction clearly doesn't hold in this case. There have been cases where free software makers simply refused to fix their code or committed that they don't care. Others just mention that the user is an unthankful beast and should run something else. After all, the software was free and there is no warranty.
We could try and change the definition of the responsible party to "owner of the source code". After all, you can only secure something if you have access to its building blocks, right? This case would mean the same thing for commercial software vendors, since they do own the code to their products and are the only ones who can access it. If we extend the definition to mean "write access to the main source tree", it would also neatly describe the maintainers of free software. Case closed, or may be not?
The problem with this approach is that nobody has complete control over the entire source code, and even the few who apparently have it don't. Software is made out of modules and every piece of software uses a wide range of modules: from kernel and system calls to statically and dynamically linked libraries, other software handling the events sent by the software and of course firmware and microcode on hardware devices. It is highly unrealistic to expect anyone or any organization to have complete control over all the components their software depends on. Big software companies are much like a collection of small companies that happen to work together on a single large project.
Today, the lack of central understanding and control leads to responsibility being resolved by the social or business equivalent of a call graph. If, for example, a vendor of a complex server software faces a security vulnerability in the image parsing and handling code of said server, he identifies the maker of the library in question. The library maker gets contacted and asked to fix the bug. The library maker in turn realizes that the issue is in a piece of lower level library and contacts its respective maker and so forth, until hopefully one of the elements in this chain feels responsible and fixes the issue. Or this is how it should work.
In reality, it is often not so easy to identify whose code is actually responsible for the security issue. In the post buffer overflow era of software vulnerabilities, many application specific issues arise from the inter-workings of components. Let's assume, to stay with the image library example above, the image in question has a width and height information of -3. The low level library computes that there will be -3 * -3 = 9 bytes space required and provides this much. The upper level library copies image data until a counter reaches 4294967293, the unsigned interpretation of -3 on a 32 Bit machine. Both parts of the behavior are not correct, but who is responsible for fixing the issue? What if they do not agree? That becomes an important point when the issue is larger than just a signed vs. unsigned integer.
It is by now a commonly accepted fact that a good design and architecture can prevent a lot of issues before they actually happen. After all, the term architecture comes from a profession that must plan on things to be not perfect. If an essential part of a building does hold the weight anymore and crashes, you can sue the vendor and demand a fix but your building is already in rumble and dust. Or, you can just design the whole thing to not depend completely on a single element. Some software vendors have understood that and start to build their products accordingly.
Design becomes even more important than it already is when it comes to computer systems, simply since this is the only way to handle all the complexity we are facing. Accordingly, it needs to be more precisely executed and validated by additional people with a different viewing angle on the subject. Also, changes dictated by reality, Murphy, management or customers need to get back-ported into the design documents. Companies who already work by those principles produce amazingly good, secure and easy to manage products, not only in the software world.
We already identified that there is no such thing as the software maker but rather a more or less designed and planned way of putting together components. In that respect, writing software is some times just linking already existing components by specifying their inter-working in arcane grammars called programming languages. Therefore, the primary work is in selecting the right components for the task, design their relations and how data is handed over from one to the other and make the whole thing work.
But if we take this description, we can see that selecting an operating system and installing software on top of it is actually the same process. In fact, on a high abstraction level, there is no difference between writing code and designing and implementing an infrastructure solution like a company's email system. You have to know your components. You have to rely on third parties to tell you exactly what their components can and cannot fulfill and how they work. You have to take explicit and implicit requirements into account and finally design a solution. And you have to work on imperfect data, since almost all facts you take into the calculation may turn out to be false, just like the assumption about the security of this image parser.
A good design is based on the definition of your goals, so I gave this insight a try. The defined goal was an actively used Windows XP system that rots as little as possible over time. Most people are forced to freshly install their Windows from time to time, just because they installed and deinstalled a lot of software and everything left a bit of waste lying around or installed additional components that are not removed when the software is already gone. And, much like with security issues, most people believe that, if you actively use a Windows system and install new stuff from time to time, a performance degrading mess is inevitable, since you don't have the source code and you don't know what happens under the hood.
In my design, I therefore decided to not just install software all the time but rather to perform a minimal verification. This is done by installing it into a VMware Windows installation. What I'm looking at is:
It's a very quick check. The result are two Windows XP systems that I run for over a year now, heavily used and permanently modified but still almost as well performing as when I installed them for the first time and not a single fatal failure that caused data loss.
I'm totally aware that this example is slightly off-topic and that it is common practice in every good IT operation, but it is useful to illustrate how important design and architecture are and how little difference there is between composing an application by code plus libraries and composing a set of software to work together by setup.exe and configuration menus. After all, seasoned UNIX programmers tend to be very good system administrators on the same platform. For both large system architectures as well as for my question whether I install a piece of software on my production system or not, one thing holds true: you have to decide on inperfect information but once you decided, it's pretty hard to get rid of the consequences.
Coming back to the responsibility question, I tried to show that really good security, namely defense in depth, can only be achieved by a good design and architecture. While having a number of other merits, a well reviewed design can be held accountable for security, despite all the imperfections of the components involved. The only entity that can finally be held responsible for the security of something is whoever designed it. Having an all-embracing system design, reviewed by experienced subject matter experts from different fields, yields a very good result and provides as much security was we can achieve today.
[1] I could also imagine getting reimbursed a percentage of the software's price for every crash dump I send to the vendor via the "please inform CorpX about this problem that just wasted half a day worth of your work" message box.
posted at: 18:08 by FX | path: /paradigms | permanent link to this entry
While auditing commercial software for security issues, you often come across the pattern of proprietary authentication, authorization and object access control. The software designers, or, in case it wasn't really designed, the developers, implement their own user credential and access permission mechanisms. Doing so always significantly degrades the security of the entire solution and the custom mechanisms almost always go down in flames the first time someone looks at them too hard.
I vividly remember the fascination of coming up with your own authentication mechanisms. 14 years ago, I was doing the same. This was at the times of MS-DOS, where there wasn't any such facility provided by the operating system. While it still didn't make too much sense to implement something that was called in autoexec.bat to check for credentials (remember the F5 key?), it wasn't mission critical or even commercial software either, so I hope it's forgivable. Interestingly enough, one year later, I was presented with an access control software that was used by the German postal service to secure access to their MS-DOS machines. The person showing it to me said: "You can't break into this, it is commercial grade software." while I rebooted the machine and pressed F5. Well, yes, I could.
When designing identity checks and object access control, the guiding principle should be: PAL. It is a German slang acronym and stands for "Problem anderer Leute", which can roughly be translated to "someone else's problem". In most cases, your underlying operating system or database does require authentication anyway and does offer a fine granularity of access control mechanisms based on the credentials used in the authentication process. Use them!
When moving into a new house or flat, nobody in his right mind would go into a hardware store (as in "Home Depot", not as in "Radio Shack") and buy metal, rasp and small drill bits to make himself a lock for the front door. The person would instinctively know that the expense in time and money exceeds buying a commercial door lock. Additionally, the person would normally realise that a homemade lock will not provide the same level of security.
In many applications, the homemade approach is favoured. By implementing it's own authentication and authorization schemes and using a single almighty user account on the operating system and/or database, the vendor makes his own door lock out of cardboard or wood and embeds the original key to the commercial door lock in the mechanism, so the original door lock still functions. Sounds silly? It is.
Imagine a kiosk type application, such as a cash register or device control system, running on a modern version of Microsoft Windows and compare the following two design approaches. First, we look at what's usually done, namely the kiosk application implements it's own authentication and authorization scheme:
It should be fairly obvious by now that, by implementing it's own authentication, the application actually disabled all build-in security provided. And, regardless of your opinion on Microsoft, it's fair to say that they probably spent significantly more time on making sure their authentication and authorization is correct than the developer(s) of the kiosk application.
If, on the other hand, the application would be designed to use the Windows user accounts as means of authentication, the picture is a lot different:
The same approach works on almost every modern operating system, although the almighty root account on UNIX type systems makes it a little more complicated to securely store user related credentials. The approach also works with most web servers and databases. Side effects include less code to develop, higher security due to the use of well-audited code and kissing goodbye authentication bypass vulnerabilities.
Interestingly enough, some commercial web application developers have already learned this lesson and are using frameworks that handle authentication and session tracking for them. Next time you evaluate the design of a to-be-build solution or a to-be-purchased product, ask how authentication and authorization are implemented. If you hear stories about strong encryption and their own user management, at least ask why.
posted at: 15:06 by FX | path: /paradigms | permanent link to this entry
Recently I met a friend of mine, who is responsible for a fairly large production network with well-founded high security requirements. One of the interesting aspects of his work was the plan to actually remove some of the security devices and appliances deployed. Removing, you ask? Yes!
The driving force for looking at the effectiveness of their network security was of course money, namely the money needed to operate and maintain it. When this network was built, a great deal was spent on the security of it, much like many people in the industry and all security appliance vendors recommend. But when looking at the cost years later, they decided to grab available data and see what type and how many actual attacks happened since the deployment of all the firewalls, IDS sensors and whatnot. The result: very little. So they get rid of some.
On the other hand, think about the security devices as targets and not protections for a minute.
Take a fairly simple protocol, such as HTTP. A web server only needs to implement the functionality of this one clear text protocol correctly and will be fine. Now, how many major web servers do you know that didn't have a HTTP parsing vulnerability in the past? But the parsing of a HTTP request is implemented in a fairly small share of the web server's code base, because it also has to deal with things like MIME types, virtualization of path information, finding and opening files and other stuff.
Compare this to an network intrusion detection system (NIDS) sensor. It needs to do the same thing, namely implement protocol parsing correctly, but for 100 some times complex protocols (the number is from ISS's Proventia). Also, the protocol inspection is it's job, so the lion share of binary code executed is actually attackable surface. In the past, people used TAPs (RX-only network connection) and stated that this prevents attackers from breaking into the NIDS sensors, because they would be unable to communicate with it. Did anybody ever evaluate a fully deployed NIDS under the assumption of one sensor running non-interactive attacker code? I think a not too complex multi-stage shellcode (the term is a bit misleading here) should be able to exploit the central NIDS management server from the implicitly trusted NIDS sensor and phone home from there. Stuff like this has been done before.
Today, everyone deploys inline network IPS. eEye showed nicely [1, 2] what it means to deploy something with such a large attack surface in the middle of your communication stream: namely, your IPS gets owned first and used as a very convenient jump point into the management network. I also vividly remember when K2 presented at DefCon 9 on polymorphic shellcode [3] and the ISS sensor, which was supposed to just not notice the exploit, crashed in front of the audience while parsing the modified exploit. And please don't think this is about ISS's products, this is a general issue.
On the organizational side of larger IT operations, the same or related teams usually manage the firewall and NIDS rules. In practice, this means the firewall will have a rule saying "block port 99" and the NIDS will have a rule saying, "alert on internal port 99 traffic". So you have two types of NIDS sensors deployed, the ones on the outside producing several thousand alarms per minute and the ones on the inside reporting traffic violations and P2P leech. Is this worth thousands of bucks per month operational cost?
But the only actual reason many organizations have these devices is for forensics, since nobody is watching them in real time anyway. If I were to be called into a case where systems are owned using 0day, I would much prefer a full packet dump covering the last 30 days instead of a selection of may-be-accurate information the IDS has for the same time period. Running a full packet log with a rotation of 30 days is going to cost you very little. A common 100 GB hard drive will be easily able to handle a day worth of traffic and one can reproduce the entire day completely without a semi-intelligent piece of hot needle software pre-filtering the data.
Again, the very old recommendation to keep things simple and stupid holds ground. If your deployed software does not act on input such as network traffic, the same can be as malformed as it wishes to be. I wonder how many IDS sensors choke on HTTP chunked encoding reassembly when the "protected" web server behind it does not even support this transfer method.
Consider throwing away at least parts of your IDS and reinvesting the saved money and staff time into their education. Even a little talented network security person will be able to use additional knowledge more intelligently than any of your alert filtering software solutions. And, you don't have to script them: they are voice controllable.
posted at: 11:19 by FX | path: /paradigms | permanent link to this entry