UNIX / Linux keyboard.

Software Security Tools

Testing shows the presence, not the absense of bugs.
— Edsger W. Dijkstra,
Software Engineering Techniques, 1969

Developing software that is more secure

It is extremely difficult to create trustworthy software. The difficulty and slow production leads to much higher price. That means that most software produced will be fairly insecure, because security is a fairly low priority for most producers and consumers of technology. As an example of the difficulty, the NSA asked Praxis High Integrity Systems to develop part of Tokeneer, a secure system.

The Tokeneer
Project

9939 lines of code were produced, in
260 days of work, for a production rate of
38 lines of code per day, and with
2 defects discovered since delivery.

They demonstrated that while it's possible to develop "highly secure systems to the level of rigor required by the higher assurance levels of the Common Criteria", it certainly isn't easy.

A lot of the difficulty goes back to the fundamental differences in secure design. Ross Anderson's book Security Engineering: A Guide to Building Dependable Distributed Systems is an excellent explanation of the issues of designing trustworthy systems.

I think a lot of the problem is philosophical. A typical system design is based on what features you want to include. The most important question for most designers is of the form, "Does this do what I want it to?" Unfortunately, they overlook the important question "Does this refuse to do what I want it to not do?" Could there be some way to get the system to do something helpful to the attacker and overlooked by the designer?

Put another way: A design should specify that the system should have only a narrowly defined set of functions: precisely that and no more. That means that the design analysis and implementation testing need to address failure modes and the handling of unexpected input.

What Really Runs Secure Software?

It is difficult enough to develop source code that is, at least in theory, secure. And much more difficult yet to make it proveably secure.

But, it's even worse.

Unless you are writing software directly in the processor's machine language — and hardly anyone does that — you have to rely on someone else's complex and opaque computer programs to make them run. That is, to turn them into the hardware-specific machine instructions that a processor uses, so the program can be executed by the machine.

A compiler converts source code written in a high-level relatively human-friendly language like C, C++, C#, Rust, Go, FORTRAN, etc., into machine instructions.

An assembler converts source code written in a low-level not-so-friendly language based on short and cryptic mnemonics such as:
addl (%ebx),%eax
into machine instructions.

An interpreter runs a scripting language like Python, Perl, Bash, PowerShell, JavaScript, etc., "on the fly", analyzing and converting the input syntax and semantics into machine instructions that the interpreter executes on the machine.

But why should we trust that a compiler, assembler, or interpreter will behave as we assume it will?

Ros Anderson of Cambridge University has written some excellent papers on the topic. Compilers can optimize code, changing the details of the resulting machine instruction sequence to implement the same logic in a way that runs faster. Or at least that's the intent. Most compiler optimizations can change the resulting logic, maybe in very subtle ways that don't significantly change the resulting behavior, but possibly creating many security holes.

Anderson's paper "What you get is what you C" describes how a programmer can't really control the degree to which a compiler attempts to optimize code. Worse yet, you can't even control whether it optimizes at all. Even when you run the compiler with what its documentation promises are options that direct it not to apply any optimizations.

More recently, more in the area of how unexpected and even unseen logical changes can be inserted, his "Trojan Source" paper shows how security problems and other logical flaws can be rendered invisible to the most careful would-be software auditor.

Researchers have been working in this problem area at least since the 1960s with no ultimate solution in sight.

Complexity Decreases Security

More complexity means more opportunities for bugs and greater difficulty finding them. Frederick Chang was Directory of Research at NSA. In his November 2013 testimony to the Committee on Science, Space and Technology of the U.S. House of Representatives he said:

When it comes to security, complexity is not your friend. Indeed it has been said that complexity is the enemy of security. This is a point that has been made often about cybersecurity in a variety of contexts including technology, coding, and policy. The basic idea is simple: as software systems grow more complex, they will contain more flaws and these flaws will be exploited by cyber adversaries.

I downloaded the source code for the Apollo Guidance Computer, which provided computation and electronic interfaces for guidance, navigation, and control of the Apollo program spacecraft. There are 363,397 lines of "code", some of which are comment headers inserted by the project that scanned this. Download yaAGC-dev-20100220.tar.bz2, extract the archive, and do this:

$ find . -name '*.agc' -exec cat {} \; | wc -l
  363397 

The Linux kernel as of kernel release 5.15 had 7,211,644 lines of code:

$ cd /usr/src
$ find linux-5.15 -name '*.c' -o -name '*.cc' -o -name '*.h' -exec cat {} \; | wc
23077772
7211644 23427246 401168844

The entire OpenBSD operating system, kernel plus user-space tools, had 4,662,411 lines of code at version 13.0.

$ find freebsd-src-main/ -name '*.c' -o -name '*.cc' -o -name '*.h' -exec cat {} \; | wc
4662411 20113124 199407604

Windows XP had 45 million lines of code.

Automobiles by 2014 had about 100 million lines of code.

All of Google's software services are estimated to have about 2 billion lines of code.

Writing More Secure Code

David Wheeler's Secure Programming HOWTO is a great reference for security software development. Much of it applies to programming in general. It's nicely written, both broad and detailed, and a free download. Many other things at his web site are very helpful.

Cross-Site Scripting (XSS) and similar attacks have become the largest category of threat, surpassing buffer overflow attacks. Wikipedia and others have good descriptions of these programming errors and pointers to further resources:

Cross-Site Scripting (XSS) Whitehat Security's XSS paper Cross-Site Request Forgery ([CX]SRF) SQL Injection Code Injection Format String Attacks Buffer Overflow Attacks in general Stack Overflow Heap Overflow Aleph One's "Smashing the Stack for Fun and Profit" Detailed description of Buffer Overflow and many more

A group of industry experts has defined a list of the 25 most dangerous programming errors, see the lists at the SANS Institute and MITRE.

Really Understand Code

There is some amazing content in PoC||GTFO.
PoC||GTFO

SAFECode, the Software Assurance Forum for Excellence in Code

SAFECode, the Software Assurance Forum for Excellence in Code, has this mission statement: "SAFECode is dedicated to increasing trust in information and communications technology products and services through the advancement of proven software assurance methods."

Safecode has released a very good document, Fundamental Practices for Secure Software Development: A Guide to the Most Effective Secure Development Practices in Use Today. To summarize it:

Secure Development for Cloud Platforms

SAFECode and the Cloud Security Alliance have written a paper, "Practices for Security Development of Cloud Applications".

C/C++ Security

Robert Seacord's Secure Coding in C and C++ and Vladimir Kushnir's Safe C++ address a vital topic, as most applications and pretty much all operating systems are written in those languages. C and C++ are used to create pretty much everything, but at the same time they are rather insecure languages. This goes back to the original design philosophy — Kernighan and Ritchie made it the programmer's job to very carefully use arrays. "Nevertheless, C retains the basic philosophy that programmers know what they are doing; it only requires that they state their intentions explicitly."

Bjarne Stroustrup has said, "C makes it easy to shoot yourself in the foot." C permits undesirable operations, and many simple and common programming errors are not detected by the compiler and may remain subtle at runtime.

The Software Engineering Institute at Carnegie Mellon University released the 2016 edition of the SEI CERT C++ Coding Standard: Rules for Developing Safe, Reliable, and Secure Systems in C++. It has rules for secure coding to help create systems free from undefined behaviors and exploitable vulnerabilities. They have also published a C Coding Standard.

Microsoft posted an article about Security Features in Microsoft Visual C++.

Compilers silently drop code when optimizing and this can lead to security and stability problems. "Towards Optimization-Safe Systems: Analyzing the Impact of Undefined Behavior" is a paper from the 24th ACM Symposium on Operating Systems Principles in 2014. (and also see Xi Wang's other papers) The paper examines optimization-unstable code which is unexpectedly discarded by compiler optimization due to undefined behavior within the program. They present the following common example of a pointer overflow check found in several code bases. Optimizing drops the second if statement, leaving the code vulnerable to overflow.

char *buf = ...;
char *buf_end = ...;
unsigned int len = ...;
if (buf + len >= buf_end)
	return; /* len too large */
if (buf + len < buf)
	return ; /* overflow, buf+len wrapped around */
/* write to buf[0..len-1] */

They present a list of undefined behaviors in C, both within the language itself and in library calls, and a table of varieties of unstable code optimized away by various commonly used compilers. Their Stack bug-finding tool discovers these vulnerabilities in the Linux kernel; the Python interpreter; the Chrome browser; the QEMU and Xen hypervisors; the Kerberos, OpenSSH, and OpenSSL security tools and libraries, and many other critical systems.

Also see MSC06-C Beware of compiler optimizations at CERT's secure coding site.

The following are from David Wheeler's paper, and they are all free software except as noted.

PHP Security

PHP is a powerful server-side scripting language, but with the power and the execution on the server comes risk.

Python Security

A Bite of Python is a good look at important Python security issues.

PyChecker checks for common Python bugs.

RATS (Rough Auditing Tool for Security) scans C/C++, Perl, PHP, and Python code for common problems.

Java Security

Node.js Security

Node.js is server-side JavaScript for creating web sites. It includes its own HTTP server. Security concerns here include:

Don't run the web server as root. Duh. But if creating a web server is suddenly so easy, many will be created by people who haven't heard the basics.

Set the secure and httpOnly flags on session cookies. Confusingly, this limits them to being sent over HTTPS and preventing script access to the cookie client side.

Add security focused server HTTP headers. As this page explains, the following server settings improve security. The following would be good on any web server, not just one based on Node.js, but the helmet middleware in Node.js makes its easy to add them.

Protect against CSRF/XSRF with the express.csrf() middleware.

The X-axis of weevil

A different measure of buggyness

Windows Source Code

The Kuro5hin site had some interesting comments about the leaked Windows source code.

Writing Your Own Exploit Code

The Metasploit Project is an open-source code library for developing and running exploits.


Back to the main Security Page