Untrusted environment: Difference between revisions
Content deleted Content added
Added Go |
Added FreeBASIC |
||
(25 intermediate revisions by 9 users not shown) | |||
Line 3:
The intention is that the definition is to be interpreted broadly; different languages will solve this task in very different ways and with (generally) incomparable results.
=={{header|6502 Assembly}}==
{{trans|Z80 Assembly}}
There is no trusted mode on the 6502. The program counter executes whatever it sees, and there are no segfaults, page faults, or what have you. Arbitrary code execution can be a risk, but can also be used by the programmer to speed up certain tasks, allow for opcodes an assembler doesn't support, etc.
=={{header|68000 Assembly}}==
The original 68000 has a "Supervisor Mode" and a "User Mode." There is little difference between the two except that Supervisor Mode has a separate stack pointer and allows certain commands that modify the full 16-bit processor status register as opposed to just the low byte of the status register. However, there is very little in protection from arbitrary code execution, as there is no way to prevent executing code from RAM. Whatever the program counter sees is what it executes, regardless of whether it should.
=={{header|8080 Assembly}}==
{{trans|Z80 Assembly}}
There is no trusted mode on the 8080. The program counter executes whatever it sees, and there are no segfaults, page faults, or what have you. Arbitrary code execution can be a risk, but can also be used by the programmer to speed up certain tasks, allow for opcodes an assembler doesn't support, etc. Some machines even require arbitrary code execution to properly function, such as the Game Boy, which must jump to internal RAM in order to use direct memory access to quickly display hardware sprites.
=={{header|C}}==
C is a double edged sword. It was designed to allow programmers to do virtually anything and everything. The aim was as a high level language to be close as possible at the computer hardware (CPU and memory). This gives the property of C to being fast. Therefore its possible to write large parts for Operating Systems with it. The ability to access memory at the bit level, embed assembly directly and yet be readable ( or unreadable ) by humans, resulted in a language which forms the foundation of the world as we know it.
In other words, there is no check. Users and programmers can do anything they want. There is no sandbox, no off-limits area. Unless it is explicitly forbidden by the compiler or the operating system, a C program without sufficient and necessary checks will result in 'unintended and unforeseen' consequences with the 'appropriate' inputs.
Line 19 ⟶ 30:
Beware of allowing user input to fed to the reverse polish calculator. It has the ability to run shell commands, and this could be a security risk:
<
=={{header|FreeBASIC}}==
FreeBASIC does not have built-in functions specifically designed to handle untrusted input or code. However, there are general practices that can be followed to mitigate the risks associated with untrusted input:
# '''Input Validation''': Always validate user input before using it. This can help prevent issues like SQL injection, buffer overflow, etc.
# Prevent execution of untrusted code: FreeBASIC does not have a function to execute code dynamically (such as eval in JavaScript). But this is a good thing from a security point of view, as it reduces the risk of arbitrary code execution.
# Error Handling: Always include error handling in your code. This can prevent unexpected behavior and give you more control over what happens when an error occurs.
# '''Limiting system access''': Be careful when using system-level commands (such as SHELL). These can potentially be exploited to execute arbitrary commands on the host system.
# '''Safe Libraries and Functions''': Use libraries and functions that are known to be safe. Avoid using outdated or insecure features.
=={{header|Go}}==
Line 29 ⟶ 48:
The following example shows how to use a combination of reflection and pointer arithmetic to indirectly (and unsafely) change the contents of a byte slice.
<
import (
Line 47 ⟶ 66:
}
fmt.Println(string(bs))
}</
{{out}}
Line 90 ⟶ 109:
Of course, no system is perfect and a number of vulnerabilities have been discovered in these mechanisms over the years and will doubtless continue to be discovered in the future given the ubiquity of the Java Platform and hence its attractiveness to hackers.
=={{header|Lua}}==
Lua supports protected calls and custom environments. Details have changed through various versions, and the specifics can become quite involved if/as needed, however the following might suffice as a simple example for Lua 5.2 or 5.3.
<syntaxhighlight lang="lua">local untrusted = [[
print("hello") -- safe
for i = 1, 7 do print(i, i*i) end -- safe
setmetatable(_G, malicious) -- unsafe
]]
sandbox = { print=print }
local ret, msg = pcall(load(untrusted,nil,nil,sandbox))
print("ret, msg:", ret, msg)</syntaxhighlight>
{{out}}
<pre>hello
1 1
2 4
3 9
4 16
5 25
6 36
7 49
ret, msg: false [string " print("hello")..."]:3: attempt to call global 'setmetatable' (a nil value)</pre>
=={{header|Nim}}==
Nim can compile to native code (via C, C++ or Objective-C) or to Javascript. When compiling to native code, as other languages such as Ada, it includes checks to insure than code is safe.
So, in release mode which is the mode to prefer, assignments , indexing, accesses via references, overflows ar checked. So, for instance, in normal code there is no way to get a buffer overflow as this would raise an IndexDefect exception.
Nim insures (except if explicitly specified otherwise) that memory is initialized with binary zeros, which avoids random behaviors. That means also that all pointers and references are initialized to nil which will avoid undefined behavior when dereferencing a non explicitly initialized pointer.
Nim uses copy semantic which means that assignments always copy the value and not the address. This avoids aliasing which is unsafe, but this may produce less efficient code. Fortunately, the compiler is smart enough to avoid most of the copies. Nevertheless, the programmer should be aware of this and take care of that.
The compiler does many checks to detect possible violation of memory safety. All is done to make sure that, unless explicitly required, no memory corruption is possible.
However, as a system language, Nim allows to do unsafe operations. These operations are unsafe:
– calling an external procedure (typically using C interface);
– converting from a type to another type using a cast (but normal conversions are safe);
– using pointers (allocating memory, dereferencing, freeing memory); but references are safe as all is managed by the GC;
– taking the address of an object (which means in fact to use pointers).
There is no simple way to do arithmetic operations on addresses. This is of course possible using casts between addresses/pointers and integers but this is almost never necessary.
Nim allows to deactivate and reactivate checks in some zones using pragmas. It allows also to remove almost all checks by using option <code>-d:danger</code> when compiling. In this mode, the code is the most efficient, but at the price of safety.
=={{header|PARI/GP}}==
GP has a default, <code>secure</code>, which disallows the <code>system</code> and <code>extern</code> commands. Once activated this default cannot be removed without input from the user (i.e., not a script).
<
system("del file.txt");
default(secure,0); \\ Ineffective without user input</
=={{header|Perl}}==
Perl can be invoked in taint mode with the command line option <code>-T</code>. While in this mode input from the user, and all variables derived from it, cannot be used in certain contexts until 'sanitized' by being passed through a regular expression.
<
my $f = $ARGV[0];
open FILE, ">$f" or die 'Cannot open file for writing';
print FILE "Modifying an arbitrary file\n";
close FILE;</
=={{header|Phix}}==
'''with safe_mode''' disables most potentially dangerous features such as file i/o, and invoking c_func/proc() or using inline assembly outside of Phix\builtins\, which should make it safer to try out code from an untrusted source. It behaves identically to a -safe command line option, however relying on the latter risks leaving a dangerous file lying around that might accidentally be run without the proper command line flag in some idle moment much later, whereas of course if you put it in the source, that's not such an issue.
<!--<syntaxhighlight lang="phix">(phixonline)-->
<span style="color: #000080;font-style:italic;">-- demo\rosetta\safe_mode.exw
--
-- (distributed version has several more similar scraps,
-- this is just enough to give you the basic flavour.)
--</span>
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span> <span style="color: #000080;font-style:italic;">-- (erm, it kinda is anyway...)</span>
<span style="color: #008080;">with</span> <span style="color: #008080;">safe_mode</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">cl</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">command_line</span><span style="color: #0000FF;">()</span>
<span style="color: #0000FF;">?</span><span style="color: #000000;">cl</span>
<span style="color: #008080;">if</span> <span style="color: #7060A8;">find_any</span><span style="color: #0000FF;">({</span><span style="color: #008000;">"-safe"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"--safe"</span><span style="color: #0000FF;">},</span><span style="color: #000000;">cl</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">then</span> <span style="color: #0000FF;">?</span><span style="color: #000000;">9</span><span style="color: #0000FF;">/</span><span style="color: #000000;">0</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #000080;font-style:italic;">-- disallow inline assembly (at compile time):
--#ilASM{ mov eax,1 }
-- The above would be rejected outright by pwa/p2js anyway, with or without safe_mode</span>
<!--</syntaxhighlight>-->
Note that builtins\VM\pDiagN.e has to switch it off (eg to write an ex.err file when the program crashes), which is trivial to do but only via #ilASM{}, so a malicious programmer simply cannot, that is, as long as you actually use safe_mode, and don't ever put untrusted code into the builtins\ directory. Special allowances are made for mpfr.e (aka gmp) and pGUI.e (aka IUP), since they're not inherently dangerous; there might be some other libraries that deserve similar treatment.
As mentioned above, "with javascript_semantics" is itself a kind of safe mode anyway, that is if you run it in a browser, but it won't help in any way to stop the same file doing rude things should it be run on desktop/Phix.
Standard disclaimer applies:<br>
Everything this relies on was added for this task in less than 24 hours.<br>
In no way do I even begin to think this is secure or complete, but just
yesterday (at the time of writing) it was 100% totally insecure: there
was no "with safe_mode" option, no -safe command line option, nothing
at all to check or even store that option in the compiler, or runtime.
Should you want this to be improved, simply add more tests to demo\rosetta\safe_mode.exw, and
obviously complain if/should they not entirely meet your expectations.
=={{header|Racket}}==
The <tt>racket/sandbox</tt> library provides a way to construct limited evaluators which are prohibited from using too much time, memory, read/write/execute files, using the network, etc.
<
#lang racket
(require racket/sandbox)
(define e (make-evaluator 'racket))
(e '(...unsafe code...))
</syntaxhighlight>
The idea is that a default sandbox is suitable for running arbitrary code without any of the usual risks. The library can also be used with many different configurations, to lift some of the restriction, which is more fitting in different cases.
=={{header|Raku}}==
(formerly Perl 6)
Raku doesn't really provide a high security mode for untrusted environments. By default, Raku is sort of a walled garden. It is difficult to access memory directly, especially in locations not controlled by the Raku interpreter, so unauthorized memory access is unlikely to be a threat with default Raku commands and capabilities.
It is possible (and quite easy) to run Raku with a restricted setting which will disable many IO commands that can be used to access or modify things outside of the Raku interpreter. However, a determined bad actor could theoretically work around the restrictions, especially if the nativecall interface is available. The nativecall interface allows directly calling in to and executing code from C libraries so anything possible in C is now possible in Raku. This is great for all of the power it provides, but along with that comes the responsibility and inherent security risk.
Really, if you want to lock down a Raku instance so it is "safe" for unauthenticated, untrusted, general access, you are better off running it in some kind of locked down virtual machine or sandbox managed by the operating system rather than trying to build an ad hoc "safe" environment.
=={{header|REXX}}==
Line 136 ⟶ 240:
For example, given ''cat.rexx'':
<
{{out}}
Line 150 ⟶ 254:
=={{header|Ruby}}==
Ruby handles untrusted input with the global variable <code>$SAFE</code>. Settings higher than 0 invoke an increasing level of sandboxing and general paranoia.
<
$SAFE = 4
cgi = CGI::new("html4")
eval(cgi["arbitrary_input"].to_s)</
=={{header|Rust}}==
While Rust does not have a sandboxed execution mode of its own, it has some of the best support available for compiling to WebAssembly, which ''is'' explicitly designed to be sandboxed and has multiple runtime environments in development.
=={{header|Scala}}==
Talking about high-level computer programming languages, they aim to address problems in a user domain rather than problems close to the machine as assembly languages do. The machine is already shielded by this aim and prevents the programmer from irrelevant machine details. A high-level language has in respect with an assembler no 'right on the bare silicon' programmers nor memory model.
Another objective of a high-level language is to be platform-independent and consequently being machine-independent.
Scala is supported for the following target platforms:
* the JVM 'Write once, run anywhere' platform,
* embedded and mostly sandboxed ECMAScript (JavaScript) engines (internet browser, Node.js),
* on the Microsoft .Net platform (obsolete)
* Scala Native for the LLVM infrastructure (generates machine-code)
Each of these target platforms, and subsequently the operating system, has its own specific vulnerabilities and countermeasures.
It's better to solve the problems there where they arise.
=={{header|Tcl}}==
Tcl allows evaluation of untrusted code through ''safe interpreters'', which are evaluation contexts where all unsafe operations are removed. This includes access to the filesystem, access to environment variables, the opening of sockets, description of the platform, etc.
<
$context eval $untrustedCode</
Because the only way that Tcl code can perform an operation is by invoking a command
It is possible to profile in restricted versions of operations to allow things like access to built-in packages.
<
$context eval $untrustedCode</
These work by installing aliases from the otherwise-removed commands in the safe interpreter to implementations of the commands in the parent master interpreter that take care to restrict what can be accessed. Note that the majority of unsafe operations are still not present, and the paths supported to the packages are virtualized; no hole is opened up for performing unsafe operations unless a package author is deliberately careless in their C implementation.
Line 171 ⟶ 295:
Variable references should be contained in double quotes to prevent an empty string causing an error as a result of omission during evaluation:
<
num=`expr "$num" + 1` # The quotes are an improvement</
=== Do not allow users to run programs that can launch a new shell ===
Line 185 ⟶ 309:
However, the restricted shell is not completely secure. A user can break out of the restricted environment by running a program that features a shell function. The following is an example of the shell function in vi being used to escape from the restricted shell:
<
:set shell=/bin/sh
:shell</
=== Use a chroot jail ===
Sometimes chroot jails are used to add a layer of security to
<
cd ~/jail;
chroot ~/jail;
setuid(9); # if 9 is the userid of a non-root user
rm /etc/hosts # actually points to ~/jail/etc/hosts</
=={{header|Wren}}==
Wren code is effectively sand-boxed by its VM, is limited in what it can do and is therefore pretty safe in itself.
However, it has no way of telling whether any input is from an untrusted source except that, when it is being embedded, input can only arrive via the host application which is therefore responsible for checking its authenticity.
A possible vulnerability is that Wren modules are always imported in source code rather than binary form and there is no 'signing' mechanism. It would therefore be possible for someone to replace a 'bona fide' module with a malicious one without either Wren's VM or the host application realizing this had been done.
=={{header|Z80 Assembly}}==
There is no trusted mode on the Z80. The program counter executes whatever it sees, and there are no segfaults, page faults, or what have you. Arbitrary code execution can be a risk, but can also be used by the programmer to speed up certain tasks, allow for opcodes an assembler doesn't support, etc. Some machines even require arbitrary code execution to properly function, such as the Game Boy, which must jump to internal RAM in order to use direct memory access to quickly display hardware sprites.
=={{header|zkl}}==
|