Software Development without Security Holes
Table of Contents
- 1. Educational Objectives
- 2. Software without Security Holes: Big Picture
- 3. Past Exploits and Their Causes
- 4. Software Security Principles
- 5. Secure Coding Guidelines
- 6. Static Analysis of Source Code
- 7. Rough Auditing Tool for Security (RATS)
- 8. UNO
- 9. Valgrind
- 10. Correct By Design and Mathematical Proof
- 11. Lab Experiments
- 12. Acknowledgements
- 13. References
- 14. End
1 Educational Objectives
- Understand the contribution to insecurity made by programming errors.
- Be able to deploy no-security-holes programming techniques.
Abstract: This article is about programming techniques that prevent security-exploitable errors in security software. Buffer overflow issues are addressed in a separate article. In this article, we describe a few source code analysis tools, and the background needed to understand their use.
2 Software without Security Holes: Big Picture
- Lecture #1: Overview; Sections 2 – 4
- Lecture #2: First Lab: Software without Security Holes
- Lecture #3: Coding Principles and Static Analysis of Source Code; Sections 5, and 6
- Lecture #4: Correct By Design and Mathematical Proof; Section 7
- Lecture #5: Second Lab: Software without Security Holes
- No SecHoles Software pptx
2.1 What are Bugs v Vulnerabilities v Exploits v Attacks?
- A bug is a behavioral deviation from the functional spec. Two generalizations are permitted: (i) Anything that crashes. (ii) Anything that hangs. [Crashes and hangs can be rigorously defined.]
- A vulnerability is a bug that has "security implications".
- Not every bug is a vulnerability.
- Can we detect/ deduce a vulnerability?
- (We seem to) Know it after the fact.
- Can we define "security implications"?
- An exploit takes a vulnerabilty and builds software with an unexpected behavior.
- An attack is a deployment of an exploit. Often in large numbers.
- Fact about the State of the Art 2019: No contests to the following claim: No single example exists that is 1000+ SLOC and is bug-free.
2.2 Can We Expect All Software to be Secure?
The following programs must be "security-wise robust": (i) The OS
kernel, boot loaders. (ii) All setuid
and setgid
programs.
(iii) All system daemons [services] [that accept network
connections]. But … are they?
All large programs are buggy; the above [(i), (ii) and (iii)] are buggy. And, we should understand the distinctions of being robust, correct and/or secure.
Is it possible to develop secure programs? Yes, but the cost of developing such software is so high that neither customers not companies are willing to spend.
2.3 Improving Cyber Security
- CPU Architecture
- Secure Boot
- Executable Address Space disjoint from global-data/ stack/ heap
- Network Protocols
- Redesign of nearly all protocols
- Client/Server should Dis-Trust each other, by default
- Encrypted Packets
- OS Design
- Privileges, Permissions, and Policies
- Process Lineage/ Provenance
- Address Space Layout Randomization
- Control-Flow Integrity (ROC related)
- Detection of Races
- Cryptography
- System Administration
- Software Development Practices
- Only SE considered here, all others not.
2.4 Security Architecture Design Flaws
- Cryptography misuse
- Lack of compartmentalization
- More privilege used than necessary
- Relying on secret algorithms
- Sharing resources
- Usability problems
2.5 Solvable Security Problems
"All problems fall into one of two categories: Those that can and those that cannot be easily solved. For instance, some of the denial of service attacks … are a result of the IP protocol's design. Short of implementing a new protocol …, not much can be done beyond stopgap measures that make particular attacks less effective.
Other difficult problems include network sniffing and spoofing. These result from security-related information being sent in the clear over networks. Then there is the general authentication problem. The difficulty with authentication is that the lowest common denominator is user names and passwords, and that method is generally not sufficient.
Unfortunately, solving these problems requires new hardware, new software, and user training, … Over the longer term, protocols like IPV6 and IPsec will resolve many of these issues. Of course they may create new ones. …
The solvable problems are the result of poor planning, programming, and implementation. These can be solved by software vendors … to improve their coding methodologies. … "
"… Is code getting better? You could assume that the
security holes in operating systems are the result of poor coding
way back when, and that new code and coding methods do not have
the same problem. You would be wrong. Consider Windows NT and its
sorry security state. Or look in our own back yard at Solaris.
Bugs in admintool
, NIS+, the volume manager,
procfs
, PPP, PAM, and the PCI bus drivers … prove
the point." [Peter Galvin, Pete's Wicked World column, Sun World
Magazine, 1998]
3 Past Exploits and Their Causes
3.1 Top Ten Security Holes 2017
For 2017, the OWASP Top 10 Most Critical Web Application Security Risks are:
- [Code] Injection
- Broken Authentication and Session Management
- Cross-Site Scripting (XSS) Cross-site scripting on wikipedia. Recommended Reading.
- Broken Access Control (As it was in 2004)
- Security Misconfiguration
- Sensitive Data Exposure
- Insufficient Attack Protection
- Cross-Site Request Forgery (CSRF)
- Using Components with Known Vulnerabilities
- Underprotected APIs
3.2 Top Ten Security Holes 2000
GSA Federal Chief Information Officers Council listed, in 2000, the "The Ten Most Critical Internet Security Threats":
- BIND weaknesses: nxt, qinv and in.named allow immediate root compromise.
- Vulnerable CGI programs and application extensions (e.g., ColdFusion) installed on web servers.
- Remote Procedure Call (RPC) weaknesses in rpc.ttdbserverd (ToolTalk), rpc.cmsd (Calendar Manager), and rpc.statd that allow immediate root compromise
- Remote Data Services (RDS) security hole in the Microsoft's web server named IIS.
- Sendmail buffer overflow weaknesses, pipe attacks and MIMEbo, that allow immediate root compromise.
- Buffer overflows in sadmind (remote administration access to Solaris systems) and mountd (controls and arbitrates access to NFS mounts on UNIX hosts) permit root compromise.
- Global file sharing and inappropriate information sharing via NFS and Windows NT ports 135->139 (445 in Windows2000) or UNIX NFS exports on port 2049. Also Appletalk over IP with Macintosh file sharing enabled.
- User IDs, especially root/administrator with no passwords or weak passwords.
- IMAP and POP buffer overflow vulnerabilities or incorrect configuration.
- Default SNMP community strings set to ‘public’ and ‘private.’
Observe how many of these are due to programming errors. Items 1-6, and 9 are programming errors. Items 7, 8, and 10 are configuration errors. Note that none of the top ten are due to design errors in TCP/IP.
3.3 Past Exploits and Their Causes
- Unauthorized Access
- Denial of Service
- Confidential Information leakage
- Hijacking the Flow of Control
- Smashing the stack / Arbitrary Code injection
- SQL Injection on wikipedia. Recommended Reading.
3.4 Living with Bugs
All large programs are buggy. It is unfortunate, but this axiom captures the state of the technology. Security-relevant programs have security bugs. Large programs are buggier than their size would indicate. Good coding practices can make large programs less buggy.
Buffer Overflow. Be sure all buffers (arrays of
items, usually characters) are bounded. Do bounds
checking on every variable before the contents are copied to a
local buffer. Avoid routines that fail to check buffer
boundaries when manipulating strings, particularly:
=sprintf(), fscanf(), scanf(), vsprintf(), realpath(),
getopt(), getpass(), streadd(), strecpy(), strtrns(),
gets()=, strcpy()
, and
strcat()
Files and Directories. Always use full pathnames for any
file arguments. The current directory assumed by your
program may not be where it is at. Explicitly change
directories (chdir()
) to an appropriate directory
at program start. If creating a new file, use O-EXCL
and O-CREAT flags to assure that the file does not
already exist. Do not create files in world-writable
directories. Use lstat()
to make sure a file is
not a link, if appropriate. Set limit values to disable
creation of a core file if the program fails. If using
temporary files, consider using tmpfile()
or
mktemp()
system calls to create them (although
most mktemp()
library calls have problematic race
conditions).
Be aware of race conditions, deadlock conditions and sequencing conditions.
Never use system()
and popen()
(Huh? Why not??)
system calls
Do not make assumptions about port numbers, use
getservbyname()
instead. Do not assume
connections from low-numbered ports are legitimate or
trustworthy. Do not assume the source IP address is legitimate.
Place timeouts and load level limits on incoming
network-oriented read request. Place timeouts on outgoing
network-oriented write requests.
Daemons allow users to access the system without first getting authenticated. A network daemon may answer a network request and process it under the daemon's privileges, not a user's. Therefore, this is another way for users to increase access, or even gain initial access, to the target system.
Robust Compilation and Libraries. Make good use of tools such
as lint
and splint
. Have internal
consistency-checking code. Use your compiler wisely. With gcc,
use -Wall -ansi -pedantic
flags. Use safe libraries.
Have code reviewed by other people. E.g., commercial products such as 3Com's CoreBuilder and SuperStack II hubs were revealed to have "secret" backdoor passwords.
Test thoroughly. Test the software using the same methods that crackers do: Try to overflow every buffer in the package, Try to abuse command line options, Try to create every race condition conceivable. Have others besides the designers and implementers test the code. Be aware of test coverage; gcc -pg -a causes the program to produce a bb.out file that is helpful in determining how effective your tests are at covering all branches of the code.
3.5 Economy of Mechanism
Keep your implementation as simple as possible. Note that simple is different from small: just because you can write a CGI program in 300 bytes of line-noise Perl, doesn't mean you should. All the usual structured-programming tips help here: clean interfaces between modules, avoid global state, etc.
Keep Interactions Minimal. You often need to check how each pair of subsystems interacts, and possibly even each subset of subsystems. For example, interactions between the password checker and the page-fault mechanism.
Least Common Mechanisms. The assumptions originally made in shared code may no longer be valid.
Make the program's critical portion as short and simple as possible.
3.6 Fail-Open or Fail-Closed?
Security can fail in two different ways: Allow access when it shouldn't; this is called fail-open. Refuse access when it shouldn't; this is called fail-closed. As an example, consider electronic door lock. When the power goes out, locking the door by holding it closed with a massive electromagnet will fail-open, whereas locking the door with a spring-loaded deadbolt that is pulled out of the way with a solenoid will fail-closed.
Many programs do not check if enough resources will be available. What happens if there is not enough memory and some allocations fail? What happens if the program runs out of fille descriptors? What happens if the program cannot fork()?
4 Software Security Principles
4.1 Papers and Slides
- http://www.cs.ucsb.edu/~kemm/courses/cs177/principles.pdf 2012, 20+ slides, (Overview of) Security Principles, 2012. Required Reading.
- IEEE https://www.computer.org/cms/CYBSI/docs/Top-10-Flaws.pdf Avoiding the Top 10 Software Security Design Flaws, local PDF. 2014
- NASA Addressing SW Security, 20+ slides, 2015.
4.2 Trusting Untrustworthy Channels
If you send passwords in clear text over a LAN, if you create a world-writeable file and later try to read back data from that file, if you create a file in /tmp with O-TRUNC but not O-EXCL, etc., you are trusting an untrustworthy intermediary.
Do not assume that inputs are valid. E.g., if an argument should be a positive integer in the range of 2 to 7, verify that. If an argument should be a non-empty string of letters not exceeding 13 characters in length, verify that. Check interactive input to be sure it contains only "good" characters. Consider how such input will be parsed when substituted. Check arguments passed in environment variables.
Do not require clear-text authentication information.
Use session encryption to avoid session hijacking and hide authentication information.
4.3 Proper Defaults
If there are non-obvious, but insecure, defaults, it is likely that system administrators will leave them alone. For example, if you unpack an RPM or a ZIP archive and it creates some configuration files world-writeable, you are unlikely to notice.
4.4 Error Handling and Reporting
Error handling and reporting is an essential part of any programming paradigm. Delicate handling of and recovery from error conditions is an absolute necessity, especially in a third party library.
Check all system call parameters and system call return code. System calls should verify their arguments, but unfortunately most OS calls do not for fear of becoming inefficient, so you must. Fortunately, all system calls return a success or failure code. Unfortunately, only a few programs verify these result codes.
Logging Events. Do log relevant information, including date, time, uid and effective uid, gid and effective gid, terminal information, pid, command-line arguments, errors, and originating host. Make sure that the log files themselves remain bounded in size.
4.5 Change-of-Role Hole
What was originally a minor annoyance, or sometimes even a convenience, can become a security hole when a program is run in a different context. For example, suppose you have a PostScript interpreter that was originally intended to let you preview your documents before printing them. This is not a security-sensitive role; the PostScript interpreter doesn't have any capabilities that you do not. But suppose you start using it to view documents from other people. Suddenly, the presence of PostScript's file access operators becomes a threat! Someone can send you a document which will delete all your files – or possibly stash copies of your files someplace they can get at them.
4.6 Security Compartments
A system should be divided into security compartments. For example, a Linux system has numerous compartments known as "users", "kernel", and "network". The network subsystem is divided into sub compartments known as "network connections". There are well-defined trust relationships between these different compartments, which are based on system setup and authentication. The trust relationships must be enforced at every interface between security compartments.
5 Secure Coding Guidelines
5.1 Holzmann's Ten Rules
- Holzmann's paper (see the References) presents "Ten Rules for
Writing Safety Critical Code":
- Restrict to simple control flow constructs.
- Give all loops a fixed upper-bound.
- Do not use dynamic memory allocation after initialization.
- Limit functions to no more than 60 lines of text.
- Use minimally two assertions per function on average.
- Declare data objects at the smallest possible level of scope.
- Check the return value of non-void functions, and check the validity of function parameters.
- Limit the use of the preprocessor to file inclusion and simple macros.
- Limit the use of pointers. Use no more than two levels of dereferencing per expression.
- Compile with all warnings enabled, and use one or more source code analyzers.
5.2 CERT
- http://cs.stanford.edu/people/eroberts/cs181/projects/viruses/cert.html The Role of CERT
- https://www.securecoding.cert.org/confluence/display/seccode/SEI+CERT+Coding+Standards CMU SEI CERT Coding Standards. Required Reading – Top Level.
- https://www.securecoding.cert.org/confluence/display/java/SEI+CERT+Oracle+Coding+Standard+for+Java SEI CERT Oracle Coding Standard for Java
5.3 Android Source Code
- Prabhaker Mateti, Audit of Android Src Code, work-in-progress (not ready for public), {pm-aosp-audit-min.pdf} located on thumb drive. Discuss a couple of CERT rules for Android.
5.4 Secure Java and Secure C++
- Secure Java Programming basics by PM. About 2pp. Required Reading.
- Secure Programming in C/ C++ basics by PM. About 1 page. Required Reading.
6 Static Analysis of Source Code
- Concepts
- Data Flow Analysis
- Control Flow Graph
- Taint Analysis
- Lexical Analysis
- False Positives
- False Negatives
- AutoRefactor Examples of Code Transformation
- Static Source Code Analysis Tools
- splint
- Coverity
- Well-known "simple" Tools
- CheckStyle
- FindBugs
- PMD
- Ubuntu/ Debian:
apt install ...
- Commercial Tools
- Advanced Tools
- AutoRefactor Examples
- Security Improvement;
- Misc Open Source Projects;
- Formal Verification Tools
- Spoon
- JTransformer
- Frama-C
- All the above in Static Analysis of Source Code
7 Rough Auditing Tool for Security (RATS)
RATS is a security auditing utility for C, C++, PHP, Perl, and Python
source code. RATS scans source code, finding potentially dangerous
function calls. The goal of rats is to provide a starting point for
performing manual security audits. See the book "Building Secure
Software" by Viega and McGraw, 2001.} RATS is a standard package in
Debian: apt-get install rats
. Read man rats
and
https://security.web.cern.ch/security/recommendations/en/codetools/rats.shtml
2017
8 UNO
It is invoked as in uno file.c
. It intercepts (i) Use of
uninitialized variables, (ii) Null-pointer references, and (iii)
Out-of-bounds array indexing. Uno is not a standard Debian package;
build it from the source code downloadable from
http://spinroot.com/uno/. [Current Tool Version: 2.14 – 19 December
2016]
9 Valgrind
A fairly simple use of valgrind (http://valgrind.org/) is to monitor a
process to detect coding errors such as uninitialized variables, index
overflow of an array, or memory leaks. apt-get install valgrind
kcachegrind
as these are standard packages in Debian; read man
valgrind kcachegrind
Current release: valgrind-3.13.0 2017.
10 Correct By Design and Mathematical Proof
10.1 Robust, Correct and Secure Programs
For the purpose of this article, let us define robustness as being crash proof, and hang-proof no matter what the inputs are. Crash is unexpected termination. A hang is unexpected non-termination. Two classes of being hung are: infinite looping, and waiting for an event that will not occur. Infinite looping consumes heavily the CPU time. Waiting for a non-occurring event consumes almost no resources. Note that infinite recursion will lead to a crash via resource exhaustion.
When you're writing a normal piece of software, your purpose is to make certain things possible, if the user does things correctly. When you're writing a security-sensitive piece of software, you also must make certain things impossible, no matter what any trusted or untrusted user does. Cryptologists and real-time programmers are familiar with doing things this way. Most other programmers are not.
If the kernel has security holes, no amount of checking of system
programs is going to make the system secure from attack. However,
relatively few kernel bugs are being found and exploited these days.
In terms of security, kernels are relatively bug-free because of the
limited interfaces available to attack. For instance, Solaris has
210+ system calls (check /usr/include/sys/syscall.h
), and
Linux kernel of a few years ago about 190 and in 2012 about 320+.
Compare that to the thousands of points a hacker has available to
attack: sockets, files, devices, and programs.
It is expensive to develop secure programs by a factor of 10 or so. It is also the case, that placing high importance on security will lead to these programs being inefficient. In the next few paragraphs, we ignore both these issues (cost and efficiency) and speculate on the possibility of developing secure software.
10.2 Assertions, Pre- and Post-Conditions, Invariants
- ./Assertions/assertions-101.html Process state, invariants, Pre- Post-Conditions.
- The 3n+1 Termination Problem
- Assertions in Java
- Assertions in C/C++
- Practical-Advice on Writing Assertions
10.3 Methods of Correct by Design
There is a large body of technical literature that advocates designing software by first writing formal specifications capturing the all requirements of the software yet to be constructed. Subsequent steps are systematic refinements of such specifications yielding several levels of designs ultimately producing the source code in a programming language. The writings of Turing-award winners Dijkstra and Hoare are heavily influential in this regard. (For an elementary introduction, read "Practical Advice on Writing Pre- Post-Conditions for Real Programs," listed in the References.) Unfortunately, the open literature has documented only small programs that are so developed. Most of the academic computer science community as well as the industry believes that such development is astronomically expensive and even then not necessarily qualitatively "better."
In recent years, more practical uses of the above methodology have emerged. E.g., a tool, called SPLINT (see References), can analyze large amounts of C source code at a speed comparable to that of a typical compiler and flag a variety of notorious errors that made secure software succumb to such attacks as buffer overflow.
Use formal specifications. At a minimum, develop pre- and post-conditions in carefully written English.
assert(3) is a macro that accepts a single argument which it treats as a Boolean expression. If the expression evaluates to false, the assert macro prints an error message and terminates the program. Assertions are useful in the developmental stages of programs when verbose error handling is not in place or when a grievous error condition that normally should not happen occurs. One must use assertions, but exiting abruptly even after reporting an error is not acceptable. If a grievous error condition is detected, the code should return error codes to the caller, and let it decide what to do. Code should be able to handle grievous errors well enough to be able to exit gracefully from the top level (if possible). Also, never use structured exception handling as a substitute for writing solid code in the first place.
10.4 Writing Safe setuid
Programs
-rwsr-xr-x 1 root root 94792 Mar 30 2012 /bin/mount -rwsr-xr-x 1 root root 34888 Aug 14 2017 /bin/mount -rwsr-xr-x 1 root root 42824 Sep 12 2012 /usr/bin/passwd -rwsr-xr-x 1 root root 54224 Aug 20 2017 /usr/bin/passwd
The setuid
feature allows executables launched by a user to run with
the privileges of the owner of the executable. A typical example is
the passwd program. The "buffer overflow" attack exploits setuid root
programs in order to gain root level access.
A system administrator should hunt down all the setuid programs on a
system, and remove the setuid bit, or thorughly evaluate why it must
remain set. Equally important is to avoid creating setuid
or
setgid
shell scripts. Check for the s
permission in the rwx
permissions field to see if an executable is setuid root. Run find /
-perm +4000 -print
to locate all setuid files. Add -user root
to
find those files that elevate to root.
Like most man pages, the descriptions of suid the most famous syscall vary from Unix to Unix. Unfortunately, the man pages are quite unclear, and many programmers do not study other carefully written setuid programs.
10.5 frama-c
Frama-C is a suite of free tools that statically analyse the C source code. Their tools let us "observe sets of possible values for the variables of the program at each point of the execution; slice the original program into simplified ones; navigate the dataflow of the program, from definition to use or from use to definition." (http://frama-c.com)
10.6 JTransformer
"JTransformer is powerful and easy to use development environment for your own custom analyses and transformations of Java source code" https://sewiki.iai.uni-bonn.de/research/jtransformer/
10.7 Spoon
- http://spoon.gforge.inria.fr/ Spoon - Source Code Analysis and Transformation for Java
- Spoon is an open-source library that enables you to transform and analyze Java source code. Any program element (classes, methods, fields, statements, expressions…) can be accessed both for reading and modification. Spoon takes as input source code and produces transformed source code ready to be compiled. Spoon can be integrated in Maven and Gradle.
11 Lab Experiments
11.2 Lab Experiment-1
- Objective: Introduce you to formal methods based tools. Get you to think about secure programming some more.
- Study Matt Bishop's Robust Programming article. Provide answers to Exercises 10 and 19 in the lab report.
- List (as in
ls -l
) all the setuid programs in Knoppix. - Run
splint
onexploit4.c
of Aleph One. Revise the code ofexploit4.c
, and adjust the flags ofsplint
so that all errors and warnings shown bysplint
are gone. Include in the lab report the content ofexploit4Revised.c
. (Splint is already installed on the OSIS Lab PCs under Ubuntu.) - Download the source code of the latest stable release of
sudo
from http://www.sudo.ws/sudo/. Build as usual. Readman sudo
. Check that it "works." Submit details of how you checked. - Run
splint
, with no flags (except for include-related), collectively on all the source code files ofsudo
. Insert all its messages into the lab report as an appendix. - Select three interesting messages regarding source code errors generated by splint, and explain the messages and the causes for their generation.
Bonus Points: Study the different versions of the man pages of sudo that are in these tar balls. Focus on the "seven sins of the specifier", namely, 1. Noise, 2. Silence: 3. Overspecification,
- Contradiction, 5. Ambiguity, 6. Forward Reference, 7. Wishful
Thinking (from Bertrand Meyer 1985). Do you find that the man pages became better or worse over the years. Write up your findings.
- [[./SecSoftwareLabGS.html][Lab-1 Grading Sheet]
11.3 Lab Experiment-2
- Objective: Learn a few more static and dynamic analysis tools that help discover security bugs. Three such tools are briefly described below.
- Continue to work with the source code files of the latest sudo from http://www.sudo.ws/sudo/. Build it as usual. Check that it "works."
- Use the above tools (of Section Source Code Analysis) RATS, valgrind, and UNO on the source code files and/or the sudo program built from the above.
- Select and discuss five discoveries made by each of the tools. Total 15 items.
- Write a comparative review of the tools.
- Holzmann's paper (see the References) presents "Ten Rules for
Writing Safety Critical Code":
- Restrict to simple control flow constructs.
- Give all loops a fixed upper-bound.
- Do not use dynamic memory allocation after initialization.
- Limit functions to no more than 60 lines of text.
- Use minimally two assertions per function on average.
- Declare data objects at the smallest possible level of scope.
- Check the return value of non-void functions, and check the validity of function parameters.
- Limit the use of the preprocessor to file inclusion and simple macros.
- Limit the use of pointers. Use no more than two levels of dereferencing per expression.
- Compile with all warnings enabled, and use one or more source code analyzers.
- Comment on whether
sudo
follows these rules. - [[./SecSoftwareLab2GS.html][Lab-2 Grading Sheet]
12 Acknowledgements
These lecture materials are gleaned from many sources. All are presented after careful reading. In some cases, I may have unintentionally neglected proper attribution. I assure the reader it is not because I claim authorship. Indeed, in the lectures there is hardly any thing new that I have contributed. Suggestions for improvement are always welcome.
13 References
- Several references embedded in the above.
- Will reorganize these. Real-Soon-Now.
- Matt Bishop, Robust Programming, http://nob.cs.ucdavis.edu/~bishop/secprog/robust.pdf, 17pp, 2003. Required Reading.
- Matt Bishop, Secure setuid programs. 1996. setuidBishop1996-sans-tut.pdf. Required Reading.
- David Evans and David Larochelle, Improving Security Using Extensible Lightweight Static Analysis, http://www.cs.virginia.edu/~evans/pubs/ieeesoftware-abstract.html In IEEE Software, 2002. Required Reading.
13.1 References #2
- Simson Garfinkel, Gene Spafford Practical Unix and Internet Security, O'Reilly & Associates; Chapter 23: Writing Secure SUID and Network Programs. Required Reading.
- Gerard J. Holzmann, The Power of Ten – Rules for Developing Safety Critical Code,'' IEEE Computer, June 2006, pp. 93-95 http://spinroot.com/gerard/pdf/P10.pdf Required Reading.
- Prabhaker Mateti, "Practical Advice on Writing Pre- Post-Conditions for Real Programs," Lecture Notes, May 1998. ./PrePost/prepostNotesPM.html Required Reading.
- Prabhaker Mateti, "Buffer Overflow", Lectures on Internet Security, ../../Top/lectures.html There is a section on robust programming techniques that avoid the buffer overflow exploits. Required Reading.
13.2 References #3
- Adam Shostack, "Security Code Review Guidelines," http://www.homeport.org/~adam/review.html 1996/July 2006. Highly Recommended Reading.
- David A. Wheeler, "Secure Programming for Linux and Unix HOWTO", a book, http://www.linuxdoc.org/HOWTO/Secure-Programs-HOWTO.html 2015. Free book. Highly Recommended Reading.
- [Book] Chess, Brian, and Jacob West. Secure Programming with Static Analysis. Pearson Education, 2007. Reference
- [Book] Introduction to Computer Security, Michael Goodrich, University of California, Irvine Roberto Tamassia, Brown University, Addison Wesley, 2011. Reference
13.3 References #4
- McGraw, Gary, and Ming Chow. "Guest Editors' Introduction: Safeguarding the Future of Software Security." IEEE Security & Privacy, vol 7, no. 3 (2009): 11-12. PDF accessible via WSU Library proxy. Required Reading.
- Prabhaker Mateti, "Software without Security Holes", 2018. Required Reading.
- 2011 CWE/SANS Top 25 Most Dangerous Software Errors Recommended Reading.
- Dawson Engeler, et al., A Few Billion Lines of Code Later: Using Static Analysis to Find Bugs in the Real World, CACM, 10pp, 2010. http://courses.cs.washington.edu/courses/cse484/14au/reading/coverity.pdf. Required Reading.
13.4 References #5
- Cryptography misuse 95+ slides, Guevara Noubir, Northeastern University. Recommended Reading
- An Empirical Study of Cryptographic Misuse in Android Applications 2013 Recommended Reading.