Questions about this topic? Sign up to ask in the talk tab.
Difference between revisions of "Unsafe command processing"
From NetSec
| Line 2: | Line 2: | ||
Using user input as arguments for a system call should never be done. The system() and exec() functions are mostly universal between languages along with the backtick (`) characters for command substitution. In some languages, the $() operator for command substitution is also valid. | Using user input as arguments for a system call should never be done. The system() and exec() functions are mostly universal between languages along with the backtick (`) characters for command substitution. In some languages, the $() operator for command substitution is also valid. | ||
Proof of concept: | Proof of concept: | ||
| + | |||
>>> os.system("echo %s" % input("# ")) | >>> os.system("echo %s" % input("# ")) | ||
# unsafe; ping -c1 google.com | # unsafe; ping -c1 google.com | ||
| Line 12: | Line 13: | ||
Ctypes Examples: | Ctypes Examples: | ||
* Python: | * Python: | ||
| − | >>> from ctypes import *; cdll.LoadLibrary("libc.so.6").printf(c_char_p("abcdefgh\n")); # import printf() from libc.so.6 | + | {{code|text=<source lang="python">>>> from ctypes import *; cdll.LoadLibrary("libc.so.6").printf(c_char_p("abcdefgh\n")); # import printf() from libc.so.6 |
| − | 'abcdefgh' | + | 'abcdefgh'</source>}} |
* Perl: | * Perl: | ||
Revision as of 00:54, 12 May 2013
Unsafe command processing
Using user input as arguments for a system call should never be done. The system() and exec() functions are mostly universal between 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.
Ctypes Examples:
* Python:
>>> 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\(" '{}' \; &> command_processing.txt |