mirror of
				https://github.com/ruby/ruby.git
				synced 2022-11-09 12:17:21 -05:00 
			
		
		
		
	Enhanced RDoc concerning command injection (#5537)
Clarifies security vulnerabilities for commands.
Treats:
    Kernel.system
    Kernel.` (backtick)
    IO.popen
    IO.read
    IO.write
    IO.binread
    IO.binwrite
    IO.readlines
    IO.foreach
			
			
This commit is contained in:
		
							parent
							
								
									542a38f619
								
							
						
					
					
						commit
						e9a2b30744
					
				
				
				Notes:
				
					git
				
				2022-02-18 21:46:25 +09:00 
				
			
			Merged-By: BurdetteLamar <BurdetteLamar@Yahoo.com>
					 4 changed files with 79 additions and 26 deletions
				
			
		
							
								
								
									
										29
									
								
								doc/command_injection.rdoc
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								doc/command_injection.rdoc
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,29 @@ | ||||||
|  | == Command Injection | ||||||
|  | 
 | ||||||
|  | Some Ruby core methods accept string data | ||||||
|  | that includes text to be executed as a system command. | ||||||
|  | 
 | ||||||
|  | They should not be called with unknown or unsanitized commands. | ||||||
|  | 
 | ||||||
|  | These methods include: | ||||||
|  | 
 | ||||||
|  | - Kernel.system | ||||||
|  | - {`command` (backtick method)}[rdoc-ref:Kernel#`] | ||||||
|  |   (also called by the expression <tt>%x[command]</tt>). | ||||||
|  | - IO.popen(command). | ||||||
|  | - IO.read(command). | ||||||
|  | - IO.write(command). | ||||||
|  | - IO.binread(command). | ||||||
|  | - IO.binwrite(command). | ||||||
|  | - IO.readlines(command). | ||||||
|  | - IO.foreach(command). | ||||||
|  | 
 | ||||||
|  | Note that some of these methods do not execute commands when called | ||||||
|  | from subclass \File: | ||||||
|  | 
 | ||||||
|  | - File.read(path). | ||||||
|  | - File.write(path). | ||||||
|  | - File.binread(path). | ||||||
|  | - File.binwrite(path). | ||||||
|  | - File.readlines(path). | ||||||
|  | - File.foreach(path). | ||||||
							
								
								
									
										71
									
								
								io.c
									
										
									
									
									
								
							
							
						
						
									
										71
									
								
								io.c
									
										
									
									
									
								
							|  | @ -7374,6 +7374,9 @@ static VALUE popen_finish(VALUE port, VALUE klass); | ||||||
|  *  Executes the given command +cmd+ as a subprocess |  *  Executes the given command +cmd+ as a subprocess | ||||||
|  *  whose $stdin and $stdout are connected to a new stream +io+. |  *  whose $stdin and $stdout are connected to a new stream +io+. | ||||||
|  * |  * | ||||||
|  |  *  This method has potential security vulnerabilities if called with untrusted input; | ||||||
|  |  *  see {Command Injection}[command_injection.rdoc]. | ||||||
|  |  * | ||||||
|  *  If no block is given, returns the new stream, |  *  If no block is given, returns the new stream, | ||||||
|  *  which depending on given +mode+ may be open for reading, writing, or both. |  *  which depending on given +mode+ may be open for reading, writing, or both. | ||||||
|  *  The stream should be explicitly closed (eventually) to avoid resource leaks. |  *  The stream should be explicitly closed (eventually) to avoid resource leaks. | ||||||
|  | @ -9813,10 +9816,15 @@ argf_readlines(int argc, VALUE *argv, VALUE argf) | ||||||
| 
 | 
 | ||||||
| /*
 | /*
 | ||||||
|  *  call-seq: |  *  call-seq: | ||||||
|  *    `cmd` -> string |  *    `command` -> string | ||||||
|  * |  * | ||||||
|  *  Returns the <tt>$stdout</tt> output fromm running +cmd+ in a subshell; |  *  Returns the <tt>$stdout</tt> output from running +command+ in a subshell; | ||||||
|  *  sets global variable <tt>$?</tt> to the process status: |  *  sets global variable <tt>$?</tt> to the process status. | ||||||
|  |  * | ||||||
|  |  *  This method has potential security vulnerabilities if called with untrusted input; | ||||||
|  |  *  see {Command Injection}[command_injection.rdoc]. | ||||||
|  |  * | ||||||
|  |  *  Examples: | ||||||
|  * |  * | ||||||
|  *    $ `date`                 # => "Wed Apr  9 08:56:30 CDT 2003\n" |  *    $ `date`                 # => "Wed Apr  9 08:56:30 CDT 2003\n" | ||||||
|  *    $ `echo oops && exit 99` # => "oops\n" |  *    $ `echo oops && exit 99` # => "oops\n" | ||||||
|  | @ -11196,36 +11204,29 @@ io_s_foreach(VALUE v) | ||||||
| 
 | 
 | ||||||
| /*
 | /*
 | ||||||
|  *  call-seq: |  *  call-seq: | ||||||
|  *    IO.foreach(command, sep = $/, **opts) {|line| block }    -> nil |  | ||||||
|  *    IO.foreach(command, limit, **opts) {|line| block }       -> nil |  | ||||||
|  *    IO.foreach(command, sep, limit, **opts) {|line| block }  -> nil |  | ||||||
|  *    IO.foreach(path, sep = $/, **opts) {|line| block }       -> nil |  *    IO.foreach(path, sep = $/, **opts) {|line| block }       -> nil | ||||||
|  *    IO.foreach(path, limit, **opts) {|line| block }          -> nil |  *    IO.foreach(path, limit, **opts) {|line| block }          -> nil | ||||||
|  *    IO.foreach(path, sep, limit, **opts) {|line| block }     -> nil |  *    IO.foreach(path, sep, limit, **opts) {|line| block }     -> nil | ||||||
|  |  *    IO.foreach(command, sep = $/, **opts) {|line| block }    -> nil | ||||||
|  |  *    IO.foreach(command, limit, **opts) {|line| block }       -> nil | ||||||
|  |  *    IO.foreach(command, sep, limit, **opts) {|line| block }  -> nil | ||||||
|  *    IO.foreach(...)                                          -> an_enumerator |  *    IO.foreach(...)                                          -> an_enumerator | ||||||
|  * |  * | ||||||
|  *  Calls the block with each successive line read from the stream. |  *  Calls the block with each successive line read from the stream. | ||||||
|  * |  * | ||||||
|  *  The first argument must be a string; |  *  When called from class \IO (but not subclasses of \IO), | ||||||
|  *  its meaning depends on whether it starts with the pipe character (<tt>'|'</tt>): |  *  this method has potential security vulnerabilities if called with untrusted input; | ||||||
|  |  *  see {Command Injection}[command_injection.rdoc]. | ||||||
|  * |  * | ||||||
|  *  - If so (and if +self+ is \IO), |  *  The first argument must be a string that is one of the following: | ||||||
|  |  * | ||||||
|  |  *  - Path: if +self+ is a subclass of \IO (\File, for example), | ||||||
|  |  *    or if the string _does_ _not_ start with the pipe character (<tt>'|'</tt>), | ||||||
|  |  *    the string is the path to a file. | ||||||
|  |  *  - Command: if +self+ is the class \IO, | ||||||
|  |  *    and if the string starts with the pipe character, | ||||||
|  *    the rest of the string is a command to be executed as a subprocess. |  *    the rest of the string is a command to be executed as a subprocess. | ||||||
|  *  - Otherwise, the string is the path to a file. |  *    See the {Note on Security}[@Note+on+Security]. | ||||||
|  * |  | ||||||
|  *  With only argument +command+ given, executes the command in a shell, |  | ||||||
|  *  parses its $stdout into lines, as determined by the default line separator, |  | ||||||
|  *  and calls the block with each successive line: |  | ||||||
|  * |  | ||||||
|  *    IO.foreach('| cat t.txt') {|line| p line } |  | ||||||
|  * |  | ||||||
|  *  Output: |  | ||||||
|  * |  | ||||||
|  *    "First line\n" |  | ||||||
|  *    "Second line\n" |  | ||||||
|  *    "\n" |  | ||||||
|  *    "Third line\n" |  | ||||||
|  *    "Fourth line\n" |  | ||||||
|  * |  * | ||||||
|  *  With only argument +path+ given, parses lines from the file at the given +path+, |  *  With only argument +path+ given, parses lines from the file at the given +path+, | ||||||
|  *  as determined by the default line separator, |  *  as determined by the default line separator, | ||||||
|  | @ -11327,6 +11328,10 @@ io_s_readlines(VALUE v) | ||||||
|  * |  * | ||||||
|  *  Returns an array of all lines read from the stream. |  *  Returns an array of all lines read from the stream. | ||||||
|  * |  * | ||||||
|  |  *  When called from class \IO (but not subclasses of \IO), | ||||||
|  |  *  this method has potential security vulnerabilities if called with untrusted input; | ||||||
|  |  *  see {Command Injection}[command_injection.rdoc]. | ||||||
|  |  * | ||||||
|  *  The first argument must be a string; |  *  The first argument must be a string; | ||||||
|  *  its meaning depends on whether it starts with the pipe character (<tt>'|'</tt>): |  *  its meaning depends on whether it starts with the pipe character (<tt>'|'</tt>): | ||||||
|  * |  * | ||||||
|  | @ -11427,6 +11432,10 @@ seek_before_access(VALUE argp) | ||||||
|  *  Opens the stream, reads and returns some or all of its content, |  *  Opens the stream, reads and returns some or all of its content, | ||||||
|  *  and closes the stream; returns +nil+ if no bytes were read. |  *  and closes the stream; returns +nil+ if no bytes were read. | ||||||
|  * |  * | ||||||
|  |  *  When called from class \IO (but not subclasses of \IO), | ||||||
|  |  *  this method has potential security vulnerabilities if called with untrusted input; | ||||||
|  |  *  see {Command Injection}[command_injection.rdoc]. | ||||||
|  |  * | ||||||
|  *  The first argument must be a string; |  *  The first argument must be a string; | ||||||
|  *  its meaning depends on whether it starts with the pipe character (<tt>'|'</tt>): |  *  its meaning depends on whether it starts with the pipe character (<tt>'|'</tt>): | ||||||
|  * |  * | ||||||
|  | @ -11498,6 +11507,10 @@ rb_io_s_read(int argc, VALUE *argv, VALUE io) | ||||||
|  *  Behaves like IO.read, except that the stream is opened in binary mode |  *  Behaves like IO.read, except that the stream is opened in binary mode | ||||||
|  *  with ASCII-8BIT encoding. |  *  with ASCII-8BIT encoding. | ||||||
|  * |  * | ||||||
|  |  *  When called from class \IO (but not subclasses of \IO), | ||||||
|  |  *  this method has potential security vulnerabilities if called with untrusted input; | ||||||
|  |  *  see {Command Injection}[command_injection.rdoc]. | ||||||
|  |  * | ||||||
|  */ |  */ | ||||||
| 
 | 
 | ||||||
| static VALUE | static VALUE | ||||||
|  | @ -11599,10 +11612,14 @@ io_s_write(int argc, VALUE *argv, VALUE klass, int binary) | ||||||
|  *  Opens the stream, writes the given +data+ to it, |  *  Opens the stream, writes the given +data+ to it, | ||||||
|  *  and closes the stream; returns the number of bytes written. |  *  and closes the stream; returns the number of bytes written. | ||||||
|  * |  * | ||||||
|  |  *  When called from class \IO (but not subclasses of \IO), | ||||||
|  |  *  this method has potential security vulnerabilities if called with untrusted input; | ||||||
|  |  *  see {Command Injection}[command_injection.rdoc]. | ||||||
|  |  * | ||||||
|  *  The first argument must be a string; |  *  The first argument must be a string; | ||||||
|  *  its meaning depends on whether it starts with the pipe character (<tt>'|'</tt>): |  *  its meaning depends on whether it starts with the pipe character (<tt>'|'</tt>): | ||||||
|  * |  * | ||||||
|  *  - If so (and if +self+ is an instance of \IO), |  *  - If so (and if +self+ is \IO), | ||||||
|  *    the rest of the string is a command to be executed as a subprocess. |  *    the rest of the string is a command to be executed as a subprocess. | ||||||
|  *  - Otherwise, the string is the path to a file. |  *  - Otherwise, the string is the path to a file. | ||||||
|  * |  * | ||||||
|  | @ -11660,6 +11677,10 @@ rb_io_s_write(int argc, VALUE *argv, VALUE io) | ||||||
|  *  Behaves like IO.write, except that the stream is opened in binary mode |  *  Behaves like IO.write, except that the stream is opened in binary mode | ||||||
|  *  with ASCII-8BIT encoding. |  *  with ASCII-8BIT encoding. | ||||||
|  * |  * | ||||||
|  |  *  When called from class \IO (but not subclasses of \IO), | ||||||
|  |  *  this method has potential security vulnerabilities if called with untrusted input; | ||||||
|  |  *  see {Command Injection}[command_injection.rdoc]. | ||||||
|  |  * | ||||||
|  */ |  */ | ||||||
| 
 | 
 | ||||||
| static VALUE | static VALUE | ||||||
|  |  | ||||||
							
								
								
									
										2
									
								
								object.c
									
										
									
									
									
								
							
							
						
						
									
										2
									
								
								object.c
									
										
									
									
									
								
							|  | @ -4389,7 +4389,7 @@ InitVM_Object(void) | ||||||
|      * |      * | ||||||
|      * === Subprocesses |      * === Subprocesses | ||||||
|      * |      * | ||||||
|      * - #`cmd`:: Returns the standard output of running +cmd+ in a subshell. |      * - #`command`:: Returns the standard output of running +command+ in a subshell. | ||||||
|      * - #exec:: Replaces current process with a new process. |      * - #exec:: Replaces current process with a new process. | ||||||
|      * - #fork:: Forks the current process into two processes. |      * - #fork:: Forks the current process into two processes. | ||||||
|      * - #spawn:: Executes the given command and returns its pid without waiting |      * - #spawn:: Executes the given command and returns its pid without waiting | ||||||
|  |  | ||||||
|  | @ -4755,6 +4755,9 @@ rb_spawn(int argc, const VALUE *argv) | ||||||
|  *  Executes _command..._ in a subshell. |  *  Executes _command..._ in a subshell. | ||||||
|  *  _command..._ is one of following forms. |  *  _command..._ is one of following forms. | ||||||
|  * |  * | ||||||
|  |  *  This method has potential security vulnerabilities if called with untrusted input; | ||||||
|  |  *  see {Command Injection}[command_injection.rdoc]. | ||||||
|  |  * | ||||||
|  *  [<code>commandline</code>] |  *  [<code>commandline</code>] | ||||||
|  *    command line string which is passed to the standard shell |  *    command line string which is passed to the standard shell | ||||||
|  *  [<code>cmdname, arg1, ...</code>] |  *  [<code>cmdname, arg1, ...</code>] | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Burdette Lamar
						Burdette Lamar