Code360 powered by Coding Ninjas X Naukri.com. Code360 powered by Coding Ninjas X Naukri.com
Table of contents
1.
Introduction
2.
Tainted Data
3.
Restricted Execution and Safe Levels
3.1.
Safe level 0
3.2.
Safe Level 1
3.3.
Safe level 2
3.4.
Safe level 3
3.5.
Safe level 4
4.
Frequently Asked Questions
4.1.
Describe what you mean by "tainted data" in Ruby.
4.2.
How can you remove taint objects?
4.3.
What does Ruby security mean?
4.4.
What purposes does Ruby programming serve?
5.
Conclusion
Last Updated: Mar 27, 2024

Security in Ruby

Author Riya Bhogra
0 upvote

Introduction

Ruby's security system gives programmers a way to create applications that interact with dubious data and dubious code. The security system is divided into two parts. The first is a system for telling safe data apart from the suspect or contaminated data. The second method uses local execution to "lock down" the Ruby environment and stop the Ruby interpreter from carrying out potentially harmful operations on contaminated data. This helps to prevent situations like SQL injection attacks, in which malicious input modifies the behavior of a program. It is possible to go beyond restricted execution so that untrusted (and potentially harmful) code can be run without worrying about erasing files, stealing data, or causing other problems.

Tainted Data

In Ruby, every object is either tainted or untainted. The literal values in the source code of a program are pure. Values that originate in the outside world are tainted.

These consist of data read from files, sockets, or other streams, as well as any strings (ARGV) or environment variables (ENV) obtained from the command line. The environment variable PATH is an exception; it becomes corrupted only when one or more of the directories it contains have world-writable permissions. The fact that taint is contagious means that products made from tainted materials are also contaminated.

You can test an object's taintedness, test whether it is tainted, and untaint a tainted object using the Object methods taint, tainted? And untaint. Only after your code has examined it and determined that it is safe despite its unsafe origin or derivation should you untaint a tainted object.

Restricted Execution and Safe Levels

Ruby can run programs with security checking enabled. The degree of the security check is determined by the global variable $SAFE. The default safe level for Ruby programs that run setuid or setgid is typically 0, but it is 1 in these cases. (In Unix, a program that runs with privileges above those of the user who invokes it is referred to by these terms.) The digits 0, 1, 2, 3, and 4 are considered safe levels under law. By giving the Ruby interpreter the -T commandline option, you can precisely set the safe level. By assigning to $SAFE, you can also specify the safe level. But keep in mind that you can only raise the value; you can never make it lower:

 

$SAFE=1                   # upgrade the safe level
$SAFE=4                   # upgrade the safe level even higher 
$SAFE=0                   # SecurityError! you can't do it


Thread-local $SAFE exists. In other words, changing the value of $SAFE in one thread will not change the value in any other threads. Threads can be sandboxed for untrusted programs using this feature:

 

Thread.start {                  # Create a "sandbox" thread 

$SAFE = 4                      # Restrict execution in this thread only 

...                                    # Untrusted code can be run here

 }


This SAFE level discussion for Ruby only applies to the reference implementation. There could be different approaches used. At the time of this writing, JRuby, in particular, makes minimal effort to mimic the reference implementation's constrained execution modes. Additionally, remember that Ruby's security model has not undergone the same thorough and in-depth examination as Java's security architecture. The following sections describe how Ruby's restricted execution policy is supposed to operate, but there may be bugs that make it possible to get around the limitations.

Safe level 0

The default safe level is level 0. There are no checks made on corrupted data.

Safe Level 1

Operations that could be harmful and use tainted data are prohibited at this level. If a piece of code is tainted, you can't evaluate it, you can't use it to require a library, you can't access a named file by opening it, and you can't connect to a network host if the hostname is tainted. This safe level should probably be used by programs that accept arbitrary input and incredibly networked servers. This aids in identifying programming errors that risky uses of tainted data

You should check the value of $SAFE if you create a library that performs highly unsafe operations, like interacting with a database server. Your library shouldn't work with tainted objects if it is 1 or higher. For instance, if the string that contains the SQL query is tainted, you shouldn't send it to the database.

The following execution limitations apply to safe level 1 code:

  • At startup, the environment variables RUBYLIB and RUBYOPT are ignored.
  • The $LOAD PATH does not contain the current directory (.).
  • It is not permitted to use the command-line options -e, -i, -I, -r, -s, -S, and -X.
  • For tainted arguments, some Dir, IO, File, and FileTest instance methods and class methods are forbidden.
  • It is forbidden to call test, eval, require, load, and trap with tainted arguments.

Safe level 2

Safe level 2 places additional restrictions on how files and processes can be altered, irrespective of taint, in addition to the restrictions level 1 places on operations on tainted data. There isn't much reason for a program to set its safe level to 2. Still, a system administrator might decide to run one of your programs at this safe level to ensure it can't make or remove directories, modify file permissions, run executables, load Ruby code from world-writable directories, and other things.


The following methods are prohibited at this safe level:

 

Dir.chdir                        File.truncate                  Process.egid= 
Dir.chroot                      File.umask                    Process.fork
Dir.mkdir                       IO.fctrl                           Process.kill 
Dir.rmdir                        IO.ioctl                          Process.setpgid 
File.chmod                    Kernel.exit!                   Process.setpriority 
File.chown                    Kernel.fork                   Process.setsid
File.flock                       Kernel.syscall               
File.lstat                        Kernel.trap

 

Furthermore, safe level 2 prevents you from loading or requiring Ruby code or from running executables located in directories that are accessible to the entire world.

Safe level 3

All the limitations of level 2 are present in safe level 3, along with the additional requirement that all objects, including literals in program source code (but excluding predefined objects in the global environment), are tainted at creation. Additionally, using the untaint method is not permitted.

Safe level 3 is a stepping stone to level 4 and is not usually utilized.

Safe level 4

Safe level 3 is increased by this level by forbidding any alterations to untainted objects (including calling taint on untainted objects). The global environment and any previously untainted objects produced by code running at lower safe levels are not subject to modification by code running at this level. By doing this, a sandbox is effectively created, allowing untrusted code to run safely. (Theoretically, at least, flaws in implementing the underlying security model might be discovered in the future.)

In levels 1, 2, and 3, it is forbidden to call eval on a tainted string. Safe level 4 permits it once more because level 4's restrictions are so strict that the evaluated string cannot cause any harm. The following describes how to evaluate any code in a level-4 sandbox:

 

def safe_eval(str) 
    Thread.start {                       # Start sandbox thread
         $SAFE = 4                      # Upgrade safe level 
         eval(str)                          # Eval in the sandbox 
    }.value                                 # Retrieve result 
end

 

You cannot use the required to load another file of Ruby code in safe level 4. Only in wrapped form and with true as its second argument load can be used. To prevent any classes, modules, or constants defined in the loaded file from impacting the global namespace, Ruby sandboxes it in an anonymous module when this happens. This means that code running at safe level 4 can load external modules' classes and modules but cannot use them.

By putting the level-4 sandbox thread into a ThreadGroup before setting $SAFE and then calling enclose on that group, you can further restrict the level-4 sandbox..

Safe level 4 forbids additional actions as part of the sandbox it creates, such as the following:

  • Require, unwrapped load, autoload, and include
  • Modifying the Object class
  • Altering untainted classes or modules
  • Metaprogramming methods
  • Manipulating threads not currently active
  • Using the thread's local data
  • Terminating the process
  • File input/output
  • Modifying environment variables
  • Seeding the random number generator with srand

Frequently Asked Questions

Describe what you mean by "tainted data" in Ruby.

Any Ruby object derived from an external source (such as a string read from a file or an environment variable) is immediately identified as tainted. As shown in the code below, if your program derives a new object from a tainted object, the new object will also be tainted.

How can you remove taint objects?

Any object's taint method can be used to make it tainted against its will. Using untaint, you can cleanse an item of its taint if the safe level is lower than 3.

What does Ruby security mean?

Built-in Rails secure password and solution features offer a high level of defense against numerous attacks that endanger its existence.

What purposes does Ruby programming serve?

Ruby is a versatile general-purpose programming language that can be used for various tasks. Building desktop programs, static websites, data processing services, and even automation tools is a breeze with Ruby. Web servers, DevOps, web scraping, and crawling are all used for it.

Conclusion

Most businesses now rely heavily on the equipment and software that helps them meet their objectives effectively and on time. Additionally, they are looking for people who are knowledgeable about the frameworks, tools, and programming languages that would be especially helpful to them during the early stages and growth stages of their companies. I hope the details above are valuable to you. The previous queries will assist you in accessing the interview. Additionally, I would advise you to pursue training and certification in the key technologies that pave the way for individuals to have successful careers.

Refer to our Guided Path on Coding Ninjas Studio to upskill yourself in Ruby-langRubyCompetitive Programming,Ruby-documentationRuby FAQ's, and many more! If you want to test your competency in coding, you may check out the mock test series and participate in the contests hosted on Coding Ninjas Studio! 

Happy learning!

Live masterclass