General Guidelines for Secure Coding

Follow these coding practices to enhance security at the source code level:
  • Check that input data is what the program expects by performing type, length, and bound checking. Inputs include command line arguments and environment variables in addition to data that a user enters.

  • Check input data for the inclusion of constructs such as shell commands, SQL statements, and any XML or HTML code that might be used in an injection attack.

  • Check the type, length, and bounds of arguments to system calls and library routines. If possible, use library routines that guard against buffer overflows.

  • Use full pathnames for file-name arguments, don't use files in world-writable directories, verify that a file being written to isn't a symbolic link, and protect against the unintended overwriting of existing files.

  • Check the type, length, and bounds of values returned by system calls and library routines. Make the code respond appropriately to any error codes that system calls and library functions set or return.

  • Don't assume the state of the shell environment. Check any settings that a program inherits from the shell, such as the user file-creation mask, signal handling, file descriptors, current working directory, and environment variables, especially PATH and IFS . Reset the settings if needed.

  • Perform assert checking on variables that can take a finite set of values.

  • Log any information about privileged actions and error conditions. Don't let the program dump a core file on an end-user system.

  • Don't echo passwords to the screen or send or store them as clear text. Before sending or storing a password, combine it with a salt value and use a secure one-way algorithm such as SHA-512 to create a hash.

  • If the program uses a pseudo random number generating routine, verify that the numbers that it generates are sufficiently random to match security requirements. Also use a good random seed that a potential attacker can't be expected to predict. See RFC 4086, Randomness Requirements for Security, for more information.

  • Enable Address Space Layout Randomization (ASLR) on the host system as this feature can help defeat certain types of buffer overflow attacks. See Address Space Layout Randomization.

  • When compiling and linking a program, use the Position Independent Executables (PIE) feature to generate a position-independent binary. See Position Independent Executables.

  • Consider using chroot() to confine the operating boundary of a program to a specified location within a file system.

  • Don't run a shell command by calling popen() or syscall() from within a program, especially from a setuid or setgid program.

The following guidelines apply if a program has its setuid or setgid bit set so that it can perform privileged actions on behalf of a user who haven't been granted those privileges:
  • Don't set the setuid or setgid bit on shell scripts. However, if you use Perl scripts that are setuid or setgid, you can run perl in "taint mode," which can be more secure than using similar C code. See the perlsec(1) manual page for details.

  • Restrict the use of the privilege that setuid or setgid grants to the functionality that requires it, and then return the effective UID or GID to that of the user. If possible, perform the privileged functionality in its own monitored thread or process.

  • Don't run a setuid or setgid program inside a child processes using execlp() or execvp(), which use the PATH environment variable.