
/*  First crack at a vulnerability database by John Viega (viega@list.org).
 *  A lot of the background work behind this stuff was done by Tom O'Connor
 *  (toc@list.org).
 *
 *
 *  WARNING:  Keep things in alphabetical order by category if you want
 *            output to alphabatize properly.
 */

// You probably don't want to change these assignments.
NO_RISK       = 0;
LOW_RISK      = 1;
MODERATE_RISK = 2;
RISKY         = 3;
VERY_RISKY    = 4;
MOST_RISKY    = 5;
FALSE         = 0;
TRUE          = 1;

// Handler enumeration.
H_DEFAULT  = 0; // This one can be omitted, but add it if you want.
H_STRCPY   = 1;
H_SPRINTF  = 2;
H_SNPRINTF = 3;
H_SCANF    = 4;
H_SSCANF   = 5;
H_TOCTOUA  = 6;
H_TOCTOUB  = 7;
H_TOCTOUC  = 8;
H_FPRINTF  = 9;
H_PRINTF   = 10;
H_SYSLOG   = 11;

// Commonly used error messages.
BO_LOW  =     "Low risk of buffer overflows.";
BO_MED  =     "At risk for buffer overflows.";
BO_HIGH =     "This function is high risk for buffer overflows";
BO_LOOP =     "Be careful not to introduce a buffer overflow when "
	      "using in a loop.";
BO_LIB  =     "Depending on the lib implementation, can be a buffer overflow "
	      "problem.";
TOCTOUA =     "Can lead to process/file interaction race conditions (TOCTOU "
	      "category A)";
TOCTOUB =     "Can lead to process/file interaction race conditions (TOCTOU "
	      "category B)";
TOCTOUC =     "Can lead to process/file interaction race conditions (TOCTOU "
	      "category C)";
TOCTOUG =     "Can lead to process/file interaction race conditions (TOCTOU "
	      "problems)";
RAND =        "Don't use rand() and friends for security-critical needs.";
EXEC =        "Many potential problems.";
INPUT_DESC =  "Check to make sure malicious input can have no ill effect.";
OPEN_DESC  =  "Can be involved in a race condition if you open things after "
	      "a poor check. "
              "For example, don't check to see if something is not a symbolic "
	      "link before opening it.  Open it, then check bt querying the "
	      "resulting object.  Don't run tests on symbolic file names...";
FORMAT_DESC = "Non-constant format strings can often be attacked.";

// Common solutions
TOCTOU_SOL     = "Manipulate file descriptors, not symbolic names, when "
	         "possible.";
BO_MAXLEN_SOL  = "Make sure that your buffer is really big enough to handle "
	         "a max len string.";
RAND_SOL       = "Use better sources of randomness, like /dev/random (linux) "
	         "or Yarrow (windows).";
EXEC_SOL       = "Close all fds, clean the environment, set the umask to "
	 	 "something good, and reset uids before calling.";
BO_LOOP_SOL    = "Make sure to check your buffer boundries.";
BO_LIB_SOL     = "Truncate all str inputs to a reasonable size before "
		 "calling this.";
SCANF_SOL      = "Use precision specifiers, or do your own parsing.";
INPUT_SOL      = "Carefully check all inputs.";
OPEN_SOL       = "Perform all checks AFTER the open, and based on the "
	         "returned object, not a symbolic name.";
FORMAT_SOL     = "Use a constant format string.";

// Begin function data declarations

FUNC access {
desc = TOCTOUA,
solution = TOCTOU_SOL,
risk = RISKY,
handler = H_TOCTOUA
}
FUNC acct {
desc = TOCTOUA,
solution = TOCTOU_SOL,
risk = RISKY,
handler = H_TOCTOUA
}
FUNC au_to_path {
desc = TOCTOUG,
solution = TOCTOU_SOL,
risk = RISKY
}
FUNC basename {
desc = TOCTOUG,
solution = TOCTOU_SOL,
risk = RISKY
}
FUNC bcopy {
desc = BO_MED,
solution = BO_MAXLEN_SOL,
risk = MODERATE_RISK
}
FUNC bind {
desc = "potential race condition with access, according to cert.  Also, bind(s, INADDR_ANY, ) followed by setsockopt(s, SOL_SOCKET, SO_REUSEADDR) leads to potential packet stealing vuln",
solution = "Be careful.",
risk = LOW_RISK
}
FUNC catopen {
desc = OPEN_DESC,
solution = OPEN_SOL,
risk = RISKY,
handler = H_TOCTOUB
}
FUNC chdir {
desc = TOCTOUG,
solution = TOCTOU_SOL,
risk = RISKY
}
FUNC chgrp {
desc = TOCTOUA,
solution = TOCTOU_SOL,
risk = RISKY,
handler = H_TOCTOUA
}
FUNC chmod {
desc = TOCTOUA,
solution = TOCTOU_SOL,
risk = RISKY,
handler = H_TOCTOUA
}
FUNC chown {
desc = TOCTOUA,
solution = TOCTOU_SOL,
risk = RISKY,
handler = H_TOCTOUA
}
FUNC chroot {
desc = "Don't forget to chdir() first!  Also, can lead to process/file interaction race conditions (TOCTOU category A)",
solution = TOCTOU_SOL,
risk = RISKY,
handler = H_TOCTOUA
}
FUNC copylist {
desc = TOCTOUG,
solution = TOCTOU_SOL,
risk = RISKY
}
FUNC creat {
desc = TOCTOUB,
solution = TOCTOU_SOL,
risk = RISKY,
handler = H_TOCTOUB
}
FUNC cuserid {
desc = "According to the man page, don't use it.",
solution = "Should use getpwuid(geteuid()) instead.",
risk = VERY_RISKY
}
FUNC db_initialize {
desc = TOCTOUG,
solution = TOCTOU_SOL,
risk = RISKY
}
FUNC dbm_open {
desc = OPEN_DESC,
solution = OPEN_SOL,
risk = RISKY
}
FUNC dbminit {
desc = TOCTOUG,
solution = TOCTOU_SOL,
risk = RISKY
}
FUNC dirname {
desc = TOCTOUG,
solution = TOCTOU_SOL,
risk = RISKY
}
FUNC dlopen {
desc = "Can lead to race conditions.  Attacker might be able to replace your DLL with his own.",
solution = "Do sufficient sanity checking, but watch out for TOCTOU stuff when you do so.",
risk = RISKY
}
FUNC drand48 {
desc = RAND,
solution = RAND_SOL,
risk = RISKY
}
FUNC erand48 {
desc = RAND,
solution = RAND_SOL,
risk = RISKY
}
FUNC execl {
desc = EXEC,
solution = EXEC_SOL,
risk = RISKY
}
FUNC execle {
desc = EXEC,
solution = EXEC_SOL,
risk = RISKY
}
FUNC execlp {
desc = EXEC,
solution = EXEC_SOL,
risk = RISKY
}
FUNC exect {
desc = EXEC,
solution = EXEC_SOL,
risk = RISKY
}
FUNC execv {
desc = EXEC,
solution = EXEC_SOL,
risk = RISKY
}
FUNC execve {
desc = EXEC,
solution = EXEC_SOL,
risk = RISKY
}
FUNC execvp {
desc = EXEC,
solution = EXEC_SOL,
risk = RISKY
}
FUNC fattach {
desc = TOCTOUG,
solution = TOCTOU_SOL,
risk = RISKY
}
FUNC fchmod {
desc = TOCTOUC,
solution = TOCTOU_SOL,
risk = RISKY,
handler = H_TOCTOUC
}
FUNC fchown {
desc = TOCTOUC,
solution = TOCTOU_SOL,
risk = RISKY,
handler = H_TOCTOUC
}
FUNC fdetatch {
desc = TOCTOUG,
solution = TOCTOU_SOL,
risk = RISKY
}
FUNC fdopen {
desc = OPEN_DESC,
solution = OPEN_SOL,
risk = RISKY
}
FUNC fgetc {
desc = BO_LOOP,
solution = BO_LOOP_SOL,
risk = MODERATE_RISK,
input = TRUE
}
FUNC fgets {
desc = BO_LOW,
solution = BO_MAXLEN_SOL,
risk = LOW_RISK,
input = TRUE
}
FUNC fopen {
desc = OPEN_DESC,
solution = OPEN_SOL,
risk = RISKY,
handler = H_TOCTOUB
}
FUNC fprintf {
desc = FORMAT_DESC,
solution = FORMAT_SOL,
risk = LOW_RISK,
handler = H_FPRINTF
}
FUNC fwprintf {
desc = FORMAT_DESC,
solution = FORMAT_SOL,
risk = LOW_RISK,
handler = H_FPRINTF
}
FUNC fread {
desc = INPUT_DESC,
solution = INPUT_SOL,
risk = LOW_RISK,
INPUT = TRUE
}

FUNC freopen {
desc = OPEN_DESC,
solution = OPEN_SOL,
risk = RISKY,
handler = H_TOCTOUB
}
FUNC fscanf {
desc = BO_HIGH,
solution = SCANF_SOL,
risk = VERY_RISKY,
handler = H_SSCANF
}
FUNC fstat {
desc = TOCTOUC,
solution = TOCTOU_SOL,
risk = RISKY,
handler = H_TOCTOUC
}
FUNC ftok {
desc = TOCTOUG,
solution = TOCTOU_SOL,
risk = RISKY
}
FUNC ftw {
desc = TOCTOUG,
solution = TOCTOU_SOL,
risk = RISKY
}
FUNC getattr {
desc = TOCTOUG,
solution = TOCTOU_SOL,
risk = RISKY
}
FUNC getc {
desc = BO_LOOP,
solution = BO_LOOP_SOL,
risk = MODERATE_RISK,
input = TRUE
}
FUNC getchar {
desc = BO_LOOP,
solution = BO_LOOP_SOL,
risk = MODERATE_RISK,
input = TRUE
}
FUNC getenv {
desc = "Often seen in conjunction with buffer overflows, etc.",
solution = "Remember that env vars can contain arbitrary malicious input.  Test accordingly before use.",
risk = VERY_RISKY, 
input = TRUE
}
FUNC getlogin {
desc = "It is very easy to fool.",
solution = "Don't trust its output.",
risk = VERY_RISKY
}
FUNC getopt {
desc = BO_LIB,
solution = BO_LIB_SOL,
risk = MODERATE_RISK
}
FUNC getopt_long {
desc = BO_LIB,
solution = BO_LIB_SOL,
risk = MODERATE_RISK
}
FUNC getopt_long_only {
desc = BO_LIB,
solution = BO_LIB_SOL,
risk = MODERATE_RISK
}
FUNC getpass {
desc = BO_LIB,
solution = BO_LIB_SOL,
risk = RISKY
}
FUNC gets {
desc = "The input buffer can almost always be overflowed.",
solution = "Use fgets(buf,size,stdin) instead.",
risk = MOST_RISKY,
input = TRUE
}
FUNC jrand48 {
desc = RAND,
solution = RAND_SOL,
risk = RISKY
}
FUNC krb_recvauth {
desc = TOCTOUG,
solution = TOCTOU_SOL,
risk = RISKY
}
FUNC krb_set_tkt_string {
desc = TOCTOUG,
solution = TOCTOU_SOL,
risk = RISKY
}
FUNC kvm_open {
desc = TOCTOUG,
solution = TOCTOU_SOL,
risk = RISKY
}
FUNC lchown {
desc = TOCTOUG,
solution = TOCTOU_SOL,
risk = RISKY
}
FUNC link {
desc = TOCTOUA,
solution = TOCTOU_SOL,
risk = RISKY,
handler = H_TOCTOUA
}
FUNC lrand48 {
desc = RAND,
solution = RAND_SOL,
risk = RISKY
}
FUNC lstat {
desc = TOCTOUA,
solution = TOCTOU_SOL,
risk = RISKY,
handler = H_TOCTOUA
}
FUNC mbstowcs {
desc = "Internal stack allocated buffer can be overflown on some versions.",
solution = "Don't use it.",
risk = RISKY
}
FUNC memcpy {
desc = BO_LOW,
solution = BO_MAXLEN_SOL,
risk = LOW_RISK
}
FUNC mkdir {
desc = TOCTOUA,
solution = TOCTOU_SOL,
risk = RISKY,
handler = H_TOCTOUA
}
FUNC mkdirp {
desc = TOCTOUG,
solution = TOCTOU_SOL,
risk = RISKY
}
FUNC mknod {
desc = TOCTOUA,
solution = TOCTOU_SOL,
risk = RISKY,
handler = H_TOCTOUA
}
FUNC mkstemp {
desc = TOCTOUB,
solution = TOCTOU_SOL,
risk = RISKY,
handler = H_TOCTOUB
}
FUNC mktemp {
desc = TOCTOUB,
solution = TOCTOU_SOL,
risk = RISKY,
handler = H_TOCTOUB
}
FUNC mount {
desc = TOCTOUG,
solution = TOCTOU_SOL,
risk = RISKY
}
FUNC mrand48 {
desc = RAND,
solution = RAND_SOL,
risk = RISKY
}
FUNC nftw {
desc = TOCTOUG,
solution = TOCTOU_SOL,
risk = RISKY
}
FUNC nis_getservlist {
desc = TOCTOUG,
solution = TOCTOU_SOL,
risk = RISKY
}
FUNC nis_mkdir {
desc = TOCTOUG,
solution = TOCTOU_SOL,
risk = RISKY
}
FUNC nis_ping {
desc = TOCTOUG,
solution = TOCTOU_SOL,
risk = RISKY
}
FUNC nis_rmdir {
desc = TOCTOUG,
solution = TOCTOU_SOL,
risk = RISKY
}
FUNC nlist {
desc = TOCTOUG,
solution = TOCTOU_SOL,
risk = RISKY
}
FUNC nrand48 {
desc = RAND,
solution = RAND_SOL,
risk = RISKY
}
FUNC open {
desc = OPEN_DESC,
solution = OPEN_SOL,
risk = RISKY,
handler = H_TOCTOUB
}
FUNC opendir {
desc = OPEN_DESC,
solution = OPEN_SOL,
risk = RISKY,
handler = H_TOCTOUB
}
FUNC openlog {
desc = TOCTOUB,
solution = TOCTOU_SOL,
risk = RISKY,
handler = H_TOCTOUB
}
FUNC pathconf {
desc = TOCTOUG,
solution = TOCTOU_SOL,
risk = RISKY
}
FUNC pathfind {
desc = TOCTOUG,
solution = TOCTOU_SOL,
risk = RISKY
}
FUNC popen {
desc = "Easy to run arbitrary commands through env vars.",
solution = "Use fork + execve + pipes instead.",
risk = MOST_RISKY
}
FUNC printf {
desc = FORMAT_DESC,
solution = FORMAT_SOL,
risk = LOW_RISK,
handler = H_PRINTF
}
FUNC rand {
desc = RAND,
solution = RAND_SOL,
risk = RISKY
}
FUNC random {
desc = RAND,
solution = RAND_SOL,
risk = RISKY
}
FUNC read {
desc = BO_LOOP,
solution = BO_LOOP_SOL,
risk = MODERATE_RISK,
input = TRUE
}
FUNC readlink {
desc = TOCTOUA,
solution = TOCTOU_SOL,
risk = RISKY,
handler = H_TOCTOUA
}
FUNC realpath {
desc = "Depending on impl, b.oflow problem.  Also, potential TOCTOU problem.",
solution = "Allocate your buf to be of size MAXPATHLEN and manually check arg lengths.  Also, manipulate file descriptors when possible.",
risk = MODERATE_RISK
}
FUNC recv {
desc = INPUT_DESC,
solution = INPUT_SOL,
risk = LOW_RISK,
input = TRUE
}
FUNC recvfrom {
desc = INPUT_DESC,
solution = INPUT_SOL,
risk = LOW_RISK,
input = TRUE
}
FUNC recvmsg {
desc = INPUT_DESC,
solution = INPUT_SOL,
risk = LOW_RISK,
input = TRUE
}

FUNC remove {
desc = TOCTOUA,
solution = TOCTOU_SOL,
risk = RISKY,
handler = H_TOCTOUA
}
FUNC rename {
desc = TOCTOUA,
solution = TOCTOU_SOL,
risk = RISKY,
handler = H_TOCTOUA
}
FUNC rmdir {
desc = TOCTOUA,
solution = TOCTOU_SOL,
risk = RISKY,
handler = H_TOCTOUA
}
FUNC rmdirp {
desc = TOCTOUG,
solution = TOCTOU_SOL,
risk = RISKY
}
FUNC scandir {
desc = TOCTOUG,
solution = TOCTOU_SOL,
risk = RISKY
}
FUNC scanf {
desc = BO_HIGH,
solution = SCANF_SOL,
risk = VERY_RISKY,
handler = H_SCANF,
input = TRUE
}
FUNC select {
desc = "Adding a +1 to MAX_FDS can cause a 1 bit heap overflow.",
solution = "The +1 is already in the macro.  Leave it out.",
risk = LOW_RISK
}
FUNC snprintf {
desc = BO_LOW,
solution = BO_MAXLEN_SOL,
risk = LOW_RISK,
handler = H_SNPRINTF
}
FUNC socket {
desc = "If a socket created by root is passed to children, children might be able to DoS using ioctl.",
solution = "Avoid doing it if possible, especially if you don't trust child processes.",
risk = LOW_RISK
}
FUNC sprintf {
desc = BO_HIGH,
solution = "Use snprintf if available, or precision specifiers, if available.",
risk = VERY_RISKY,
handler = H_SPRINTF
}
FUNC srand {
desc = RAND,
solution = RAND_SOL,
risk = RISKY
}
FUNC srand48 {
desc = RAND,
solution = RAND_SOL,
risk = RISKY
}
FUNC sscanf {
desc = BO_HIGH,
solution = SCANF_SOL,
risk = VERY_RISKY,
handler = H_SSCANF
}
FUNC stat {
desc = TOCTOUA,
solution = TOCTOU_SOL,
risk = RISKY,
handler = H_TOCTOUA
}
FUNC statvfs {
desc = TOCTOUA,
solution = TOCTOU_SOL,
risk = RISKY,
handler = H_TOCTOUA
}
FUNC strcadd {
desc = BO_LOW,
solution = BO_MAXLEN_SOL,
risk = LOW_RISK
}
FUNC strcat {
desc = BO_HIGH,
solution = "Use strncat instead.",
risk = VERY_RISKY,
handler = H_STRCPY
}
FUNC strccpy {
desc = BO_LOW,
solution = BO_MAXLEN_SOL,
risk = LOW_RISK
}
FUNC strcpy {
desc = BO_HIGH,
solution = "Use strncpy instead.",
risk = VERY_RISKY,
handler = H_STRCPY
}
FUNC streadd {
desc = BO_MED,
solution = "Make sure the dest param is 4x bigger than the src, minimum.",
risk = RISKY
}
FUNC strecpy {
desc = BO_MED,
solution = "Make sure the dest param can hold x4 more stuff than in the src, minimum.",
risk = RISKY
}
FUNC strncpy {
desc = BO_LOW,
solution = "Make sure that the destination buffer is as big as you think it is.",
risk = LOW_RISK,
handler = H_STRCPY
}
FUNC strtrns {
desc = BO_MED,
solution = "Manually check to see the dest is at least the same size as the src string.",
risk = RISKY
}
FUNC swprintf {
desc = BO_LOW,
solution = BO_MAXLEN_SOL,
risk = LOW_RISK,
handler = H_SNPRINTF
}
FUNC symlink {
desc = TOCTOUA,
solution = TOCTOU_SOL,
risk = RISKY,
handler = H_TOCTOUA
}
FUNC syslog {
desc = BO_LIB,
solution = BO_LIB_SOL,
risk = LOW_RISK,
handler = H_SYSLOG
}
FUNC system {
desc = "Easy to run arbitrary commands through env vars. Also, potential TOCTOU problems.",
solution = "Use fork + execve instead.",
risk = MOST_RISKY
}
FUNC t_open {
desc = TOCTOUG,
solution = TOCTOU_SOL,
risk = RISKY
}
FUNC tempnam {
desc = TOCTOUG,
solution = TOCTOU_SOL,
risk = RISKY
}
FUNC tmpfile {
desc = TOCTOUG,
solution = TOCTOU_SOL,
risk = RISKY
}
FUNC tmpnam {
desc = TOCTOUG,
solution = TOCTOU_SOL,
risk = RISKY
}
FUNC tmpnam_r {
desc = TOCTOUG,
solution = TOCTOU_SOL,
risk = RISKY
}
FUNC truncate {
desc = TOCTOUG,
solution = TOCTOU_SOL,
risk = RISKY
}
FUNC ttyname {
desc = "Value should not be trusted.",
solution = "Don't trust it.",
risk = RISKY
}
FUNC umask {
desc = "Setting a liberal umask can be bad when you exec an untrusted process.",
solution = "Reset the umask to something sane before execing.",
risk = RISKY
}
FUNC umount {
desc = TOCTOUA,
solution = TOCTOU_SOL,
risk = RISKY,
handler = H_TOCTOUA
}
FUNC unlink {
desc = TOCTOUA,
solution = TOCTOU_SOL,
risk = RISKY,
handler = H_TOCTOUA
}
FUNC utime {
desc = TOCTOUA,
solution = TOCTOU_SOL,
risk = RISKY,
handler = H_TOCTOUA
}
FUNC utimes {
desc = TOCTOUA,
solution = TOCTOU_SOL,
risk = RISKY,
handler = H_TOCTOUA
}
FUNC utmpname {
desc = TOCTOUG,
solution = TOCTOU_SOL,
risk = RISKY
}
FUNC utmpxname {
desc = TOCTOUG,
solution = TOCTOU_SOL,
risk = RISKY
}
FUNC vfscanf {
desc = BO_HIGH,
solution = SCANF_SOL,
risk = VERY_RISKY,
handler = H_SSCANF,
input = TRUE
}
FUNC vfwprintf {
desc = FORMAT_DESC,
solution = FORMAT_SOL,
risk = LOW_RISK,
handler = H_FPRINTF
}
FUNC vscanf {
desc = BO_HIGH,
solution = SCANF_SOL,
risk = VERY_RISKY,
handler = H_SCANF,
input = TRUE
}
FUNC vsnprintf {
desc = BO_LOW,
solution = BO_MAXLEN_SOL,
risk = LOW_RISK,
handler = H_SNPRINTF
}
FUNC vsprintf {
desc = BO_HIGH,
solution = "Use vsnprintf if available, or precision specifiers.",
risk = RISKY,
handler = H_SPRINTF
}
FUNC vsscanf {
desc = BO_HIGH,
solution = SCANF_SOL,
risk = VERY_RISKY,
handler = H_SSCANF
}
FUNC vswprintf {
desc = BO_LOW,
solution = BO_MAXLEN_SOL,
risk = LOW_RISK,
handler = H_SNPRINTF
}
FUNC vwprintf {
desc = FORMAT_DESC,
solution = FORMAT_SOL,
risk = LOW_RISK,
handler = H_PRINTF
}
FUNC wprintf {
desc = FORMAT_DESC,
solution = FORMAT_SOL,
risk = LOW_RISK,
handler = H_PRINTF
}

/*
 * Grammar for this file format, for those who care:
 *
 * program: var program
 *       | def program
 *       | EOF;
 *
 * var: id '=' (string|int) ';';
 * def: 'FUNC' id '{' (guts|) '}';
 * guts: id '=' (string|id|int) opt;
 * opt:  ',' guts
 *       |;
 */
