Security: Difference between revisions

[unchecked revision][unchecked revision]
Content deleted Content added
No edit summary
m Bot: Replace deprecated source tag with syntaxhighlight
 
(18 intermediate revisions by 8 users not shown)
Line 1:
Security in an OS is a very important issue. It not only includes security from outside sourcesthreats, such as viruses and hacking, but internal security as well. For example, the OS is responsible for making sure that processes don't access memory outside of their own address space. If a program does so, it must be shutdown to protect other 'well behaved' programs. Operating system security can be divided into two basic categories, high-level and low-level security.
{{In Progress}}
 
Security in an OS is a very important issue. It not only includes security from outside sources, such as viruses and hacking, but internal security as well. For example, the OS is responsible for making sure that processes don't access memory outside of their own address space. If a program does so, it must be shutdown to protect other 'well behaved' programs. Operating system security can be divided into two basic categories, high-level and low-level security.
To see articles under this category, browse [[:Category:Security|this list]].
 
== Low-level Protection Mechanisms==
Line 6 ⟶ 7:
 
=== Rings ===
Rings offer a protection layer for programs. They allow certain levels of resource access to processes. This is good, because it keeps bad programs from messing things up. There are, however, several downsides: The more CPU rings you use, the more the OS is tied to the architecture. You can, however, have several architectures each with it's own ring switching code. Another issue with this is that you OS must have a [[TSS]] set up and several other features, making ring switching much more difficult than just running all programs in kernel mode. There are a total of 4 rings in most common architectures:. However, many architectures have only two rings (e.g. x86_64), corresponding to ring 0 and 3 in this description.
 
==== Ring 0 ====
Line 19 ⟶ 20:
Most OS's use only Ring 0 and 3. This is because rings 1 and 2 are unneeded, as device drivers can run in either ring.
 
Sometimes applications need access to resources that their ring wontwon't allow. If they try to access them, a General Protection Fault (int 13) will be triggered, and the application shutdown. The application must interface with the kernel somehow, and mostly this is done with [[System Calls]].
 
==== I/O Privilege Level ====
Another important aspect of the ring permission system on the x86 architecture is the I/O Privilege Level (IOPL). It determines which rings have unrestricted access to I/O ports. It is a two bit number set in the EFLAGS register. Rings with numbers less than or equal to it have full I/O permissions, while those greater than it have none. It can be used on a process-by-process basis to grant certain servers I/O port access.
 
===Paging===
Line 30 ⟶ 34:
High level security in an operating system can be accomplished in many different ways. One way would be through file permissions in a [[VFS]]. Files in *nix have a 'permission' value in their inode entry. This controls which users can read, write, execute or delete a file. These are mostly controlled by the [[File Systems]].
 
==Programming Language Specific Security (Assembly/C/C++)==
Many operating systems around the osdevOSDev community trust user based input completely. While it is understood that most users are fighting to get a driver working/stable, it should also be understood that production level code should not contain fundamental security problems. For example, many system call implementations take values off the stack from users and store them into registers and themthen freely dereference them or use them foras lengths/, offsets, etcand so on. Looking Usingdeeper into the abovefollowing linkssubtopics, readers should be able to decipher why thesethis areposes problemsa problem and how they can be used to gain elevated privledgesprivileges inside an otherwise 'secure system'.
 
TheAlso weakestnote areas seen are by the current author arethat ELF parsers and network stack implementations can pose a large threat. Many osdevOSDev projects trust integers and offsets takenloaded from elfELF files inside their loaders and freely execute and store data at these addresses. Similarly, network protocol parsers are riddled with security -related bugs (mostly integer overflow/over-and underflows) that are thenoften used to cause real security implications usuallyproblems due to heap-based ramficationsramifications. (Take a look at the following piece Forof examplecode:
 
<syntaxhighlight lang="c">
int size = int_from_user();
char *buf = malloc(size + 1);
memcpy(buf, data_from_user, size);
</syntaxhighlight>
 
intAs sizeyou =can int_from_user(); char *buf = malloc(size+1); memcpy(bufsee,data_from_user,size); ). As can be seen if the user sets size to ((unsigned int) -1 then), the allocation will allocate 0 bytes, which on most userlandusermode heap allocatorsheaps will allocate space for the headers and no data, and causecausing a full blown heap overflow controllable by the user.
 
===Stack-based Overflows===
Knowing the x86 [[Stack]], you should already be able to deduce why this can pose a security threat. It is (relatively) very easy to make a stack overflow, so special care has to be taken while implementing one in your OS.
 
===Heap-based Overflows===
Heap-based overflows are fundamentally different from stack-based ones and are specific to each allocator. You can help to detect them inside your OS by setting "poison values" for each member of the control structures on free and allocation and checking them before operations. Linux uses this approach (see LIST_POISON1 and LIST_POISON2 [http://lxr.linux.no/linux/include/linux/poison.h#L10]).
 
===Integer-based Overflows===
Integer Overflows do not cause a direct impact such as stack-based or heap-based overflows do. Instead they lead to these types of bugs (usually heap-based) later on in the code. For instance, let's say we have an application parsing data from a protocol or file format:
 
<syntaxhighlight lang="c">
int size = read_int_from_network();
char *buffer = malloc(size + 1); // leave room for NULL.
memcpy(buffer, data_from_network(), size); // copies 2^32-1 bytes into buffer.
</syntaxhighlight>
 
As you can see, there is no verification on the size read from the user and this can cause large problems later in the code. Examples in OSDev where this arises include ELF parsers (think segment/program/entry point offset into the file), network parsers, read/write/lseek implementations, and so on. If your code takes input from the user you *MUST* verify that it fits within the range of the data you are going to process it with. Also you should check for integer-based problems on each math operation done using user-supplied data.
 
===C/C++/ASMPrevention===
While obviously these cannot be directly applied to hobby OSes, the ideas can certainly be used and ported to them. The best set of documents for securing systems can be found at
Stack Based Overflows [[Stack-Based-Overflow]]
[http://pax.grsecurity.net/docs/ PaX Design and Implementation]
 
Pax provides almost all the operating system security you need. Reading the documents pertaining to its implementations should allow Hobby OS developers to use most of these ideas in their systems. Most current Windows/BSD (kernel) protections are based on these schemes. Userland Protections can be attributed to [http://en.wikipedia.org/wiki/Address_space_layout_randomization ASLR], Heap Cookies (along with general heap hardening), Stack Canaries, and NX.
Heap Based Overflows [[Heap-Based-Overflows]]
 
Using these mechanisms does not prevent corruption of in memory data, but instead makes using the corruption for elevated privledges/advantage very difficult.
Integer Overflows [[Integer-Overflows]]
 
== See Also ==
Books on application Security [[Application-Security-Books]]
=== Articles ===
* [[GCC Stack Smashing Protector]]
* [[Resources#Software_Specifications|The Art of Software Security Assessment]]
 
=== Threads ===
General Notes:
Many operating systems around the osdev community trust user based input completely. While it is understood that most users are fighting to get a driver working/stable, it should also be understood that production level code should not contain fundamental security problems. For example, many system call implementations take values off the stack from users and store them into registers and them freely dereference them or use them for lengths/offsets etc. Using the above links, readers should be able to decipher why these are problems and how they can be used to gain elevated privledges inside an otherwise 'secure system'.
 
=== External Links ===
The weakest areas seen are by the current author are ELF parsers and network stack implementations. Many osdev projects trust integers and offsets taken from elf files inside their loaders and freely execute and store data at these addresses. Similarly, network protocol parsers are riddled with security related bugs mostly integer overflow/underflows that are then used to cause real security implications usually due to heap-based ramfications. ( For example:
* [http://duartes.org/gustavo/blog/post/cpu-rings-privilege-and-protection Aug 2008: CPU Rings, Privilege, and Protection] by Gustavo Duarte
int size = int_from_user(); char *buf = malloc(size+1); memcpy(buf,data_from_user,size); ). As can be seen if the user sets size to (unsigned int)-1 then the allocation will allocate 0 bytes, which on most userland heap allocators will allocate space for the headers and no data, and cause a full blown heap overflow controllable by the user.
* [http://doc.bughunter.net/buffer-overflow/#heap Public Documents on heap-based overflows]
 
[[Category:Security]]
I will add more notes later if the above links do not help or if extra special attention is paid to this topic.