The Sin Explained

As you may have gathered, there are two major components to this sin; think of each as a peccadillo . Peccadillo #1 is weak access control mechanisms, and peccadillo #2 is hard-coding secret data. Lets look at each in detail.

Weak Access Controls to Protect Secret Data

When it comes to the problem of setting access controls, there are significant cross-platform differences to consider. Current Windows operating systems support rich yet complex access control lists (ACLs). The complexity that is available cuts both ways. If you understand how to correctly use ACLs, you can solve complex problems that cannot be solved with simpler systems. If you dont understand what youre doing, the complexity of ACLs can be baffling and, worse yet, can lead you to make serious mistakes that may not adequately protect the underlying data.

While ACLs have traditionally been available on many UNIX systems through POSIX compliance, the access control system that has been uniformly supported is known as user - group -world. Unlike a Windows access control mask, which has a complex assortment of permissions, only 3 bits are used (not counting some nonstandard bits) to represent, read, write, and execute permission. The simplicity of the system means that some problems are difficult to solve, and forcing complex problems into simple solutions can lead to errors. The benefit is that the simpler the system, the easier it is to protect data. The Linux ext2 file system supports some additional permission attributes that go beyond the set of permissions that are commonly available.

Another difference between Windows systems and UNIX-based systems is that in UNIX-based systems, everything is a filesockets, devices, and so onand can be treated like a file. On a Windows system, theres a mind-boggling array of objects to consider, and each one of these has access control bits particular to that type of object. We wont get into the gory details of which bits apply to mutexes , events, threads, processes, process tokens, services, drivers, memory mapped sections, registry keys, files, event logs, and directories. As with many things, if you need to create an object with specialized permissions, you need to go Read The Fine Manual. The good news is that most of the time, the default permissions the operating system grants to most of these objects are the permissions you should be using.

ACLs and Permissions Redux

The user-group-world system grants permissions first based on the effective user ID (EUID) of the process that created the file. The group permissions depend on whether the operating system uses the effective process group ID, or the group ID of the directory that the file was created in. Finally, if the creator of the file or a high-level user allows access, everyone (world) may be granted access. When a process attempts to open the file, the access check first checks whether the user is the owner of the file, next whether the user is in the group designated for the file, and last the permissions that apply to anyone . An obvious consequence of this system is that it tends to depend on users being in the correct groups, and if the system admin doesnt manage groups correctly, many files end up with excess permissions granted to everyone.

Although there are actually a few different kinds of access control entries (ACEs) on a Windows system, they all have three things in common:

  • A user or group identifier

  • An access control mask to identify what actions the entry regulates (read, write, etc.)

  • A bit to determine whether the entry allows or denies access

The user-group-world approach can be thought of as an ACL with a maximum of three entries, and a limited set of control bits. The way that an ACL is checked is that if the user or group identifier matches the user or a group thats enabled in the processs token, then the entry applies, and the access thats requested is compared with the access controlled by the ACE. If there is a match, and the ACE allows access, then you check to see if all of the access-requested flags match granted-access flags, and if so, then youve passed the access check. If you dont have all of the bits you need, then you continue to process more ACEs until you either get all of the access you requested or run out of ACEs to process. In the event that you hit an access denied ACE that matches both the access youve requested and a user or group in your token (whether enabled or not), then access is denied and no more ACEs are processed . As you can see, ACE order is important, and its best to use APIs that will correctly order ACEs for you.

Another aspect of ACLs that creates more complexity is the possibility of inheritance. While files on UNIX will sometimes inherit the group from the parent container, any object on Windows that contains other objectsdirectories, registry keys, Active Directory objects, and a few otherswill likely inherit one or more ACEs from the parent object. It isnt always a safe assumption that the inherited access control entries are appropriate for your object.

 

Sinful Access Controls

Because poor access controls arent specific to any language, well focus on what problem patterns look like. But given a detailed look at the mechanisms used to create correct access controls across multiple operating systems could be a small book in its own right, were only going to cover the high-level view.

The worst, and one of the most common, problem is creating something that allows full control access to anyone (in Windows, this is the Everyone group; in UNIX, it is world); and a slightly less sinful variant is allowing full access to unprivileged users or groups. The worst of the worst is to create an executable that can be written by ordinary users, and if youre really going to make the biggest mess possible, create a writable executable thats set to run as root or localsystem. There have been many exploits enabled because someone set a script to suid root and forgot to remove write permissions for either group or world. The way to create this problem on Windows is to install a service running as a highly privileged account and have the following ACE on the service binary:

Everyone (Write)

This may seem like a ridiculous thing to do, but antivirus software has been known to commit this sin time and again, and Microsoft shipped a security bulletin because a version of Systems Management Server had this problem in 2000 (MS00-012). Refer to CVE-2000-0100 in the Example Sins section that follows for more information about this.

While writable executables are the most direct way to enable an attacker, writable configuration information can also lead to mayhem. In particular, being able to alter either a process path or a library path is effectively the same as being able to write the executable. An example of this problem on Windows would be a service that allows nonprivileged users to change the configuration information. This can amount to a double-whammy because the same access control bit would regulate both the binary path setting and the user account that the service runs under, so a service could get changed from an unprivileged user to localsystem, and execute arbitrary code. To make this attack even more fun, service configuration information can be changed across the network, which is a great thing if youre a system admin, but if theres a bad ACL, its a great thing for an attacker.

Even if the binary path cannot be changed, being able to alter configuration information can enable a number of attacks. The most obvious attack is that the process could be subverted into doing something it should not. A secondary attack is that many applications make the assumption that configuration information is normally only written by the process itself, and will be well formed . Parsers are hard to write, developers are lazy, and the attackers end up staying in business. Unless youre absolutely positive that configuration information can only be written by privileged users, always treat configuration information as untrusted user input, create a robust and strict parser, and best yet, fuzz test your inputs.

Another incarnation of this problem is when multiple applications have to share memory between them. Shared memory is a high-performance, unsafe, insecure way to do inter-process communications. Unless the application is robust enough to treat a shared memory section as untrusted user input, having writable shared memory sections typically leads to exploits.

The next greatest sin is to make inappropriate information readable by unprivileged users. One example of this was SNMP (Simple Network Management Protocol, also known as the Security Not My Problem service) on early Windows 2000, and earlier, systems. The protocol depends on a shared password known as a community string transmitted in what amounts to cleartext on the network, and it regulates whether various parameters can be read or written. Depending on what extensions are installed, lots of interesting information can be written. One amusing example is that you can disable network interfaces and turn smart power supply systems off. As if a correctly implemented SNMP service werent enough of a disaster, many vendors , including Microsoft, made the mistake of storing the community strings in a place in the registry that was locally world-readable. A local user could read a writable community string, and then proceed to administer not only that system, but also quite possibly a large portion of the rest of the network.

All of these mistakes can often be made with databases as well, each of which has its own implementation of access controls. Give careful thought to which users ought to be able to read and write information.

One problem worth noting on systems that do support ACLs is that it is generally a bad idea to use deny ACEs to secure objects. Lets say, for example, that you have an ACL consisting of:

Guests: Deny All
Administrators: Allow All
Users: Allow Read

Under most scenarios, this works relatively well until someone comes along and places an administrator into the guests group (which is a really stupid thing to do). Now the administrator will be unable to access the resource, because the deny ACE is honored before any allow ACE. On a Windows system, removing the deny ACE accomplishes exactly the same thing without the unintended side effect, because in Windows, if users are not specifically granted access, they will be denied access.

Another Windows-specific problem is that the access token will be built by first including groups from the users domain, next including groups for the domain that contains the system being logged onto, and finally including groups provided by the local system. Where you can get into trouble is when youre delegating access to a resource contained by another system. If you just take the ACL from the object (one example might be an Active Directory object) and perform an access check locally, you could end up granting extra access unless youre careful to process the ACL and strip out locally defined groups, such as Administrators. This may sound far- fetched , but its unfortunately a common problem because few networks have Kerberos delegation enabled. At one time, Microsoft Exchange had a problem with this root cause.

Embedding Secret Data in Code

The next goof up, hardcoding secret data, is really irksome. Lets look at an example. Your application needs to connect to a database server that requires a password, or access a protected network share using a password, or encrypt and decrypt data on the fly using a symmetric key. How are you going to do it? The simplest, and by far the worst (read: most insecure), way is to hardcode the secret data, such as the password or key, in the application code.

There is another reason for not committing this sin, and it has nothing to do with security. What about maintenance? Imagine your application is written in, say, C++, and is used by 1,200 customers. The application is sinful, and has an embedded encryption key used to communicate with your servers. Someone works out the key (its not difficult, as well explain shortly), so you have to update the application for 1,200 users. And all the users must update because the key is now public, which means your servers need updating, which means all customers must update NOW!

Related Sins

Race conditions are a related sin where poor access controls enable some race condition attacks. This sin is covered in detail in Sin 16. Several other related sins involve processing untrusted user input. Another related problem is not using proper cryptography. Sometimes you can mitigate information disclosure problems with encryption, or if you must leave input information in a writable area, sign the information to mitigate tampering attacks.

Another related sin is failure to use the principle of least privilege. If your process is running as root or localsystem, the best access controls wont protect the operating system from your mistakesthe application can do anything, and access controls cant stop it.



19 Deadly Sins of Software Security. Programming Flaws and How to Fix Them
Writing Secure Code
ISBN: 71626751
EAN: 2147483647
Year: 2003
Pages: 239

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net