Unsafe command processing
It is never safe or secure to process user input into system commands. The system() and exec() functions are mostly universal between programming languages along with the backtick (`) characters for command substitution. In some languages, the $() operator for command substitution is also valid.
Proof of concept
>>> os.system("echo %s" % input("# ")) $ unsafe; ping -c1 google.com PING google.com (74.125.224.168) 56(84) bytes of data. 64 bytes from lax02s01-in-f8.1e100.net (74.125.224.168): icmp_req=1 ttl=51 time=13.1 ms |
Mitigation
Instead of using system, backticks, popen, exec or any other command executing function, use the language's native built in library. If it does not have one, then write one - but do not simply wrap system() and call this a library; this is bad form. All interpreted languages have a way to load shared libraries (*.so files) and interface with the functions provided by their export tables. These are what should be utilized when authoring libraries that seemingly need you to run a command. Instead, the C interface (CTypes) can be used.
Ctype or native examples:
>>> from ctypes import *; cdll.LoadLibrary("libc.so.6").printf(c_char_p("abcdefgh\n")); # import printf() from libc.so.6 'abcdefgh' |
- Perl:
- PHP:
- Ruby:
Auditing
Auditing command processing is simple: check for all uses of system(), exec(), backticks, popen, and any language specific function.
find -type f -regextype posix-awk -regex ".*\.(rb|php|py|pl|pm)" -exec grep -EHnC2 "system\(\|[pP]open\(\|\`\|exec.*\(\|passthru\(" '{}' \; |