os-command-injection¶
Ensure secure usage of os commands
Using functions that allow invoking OS system commands is insecure when arbitrary user input is allowed to modify the intended system command execution. In many cases, there is an alternative to invoking a system command directly such as using an abstraction for accessing the file system. Whenever it is strictly required that user input influences the system command, it's always best to use a whitelist of safe commands (or arguments).
Examples¶
Insecure Example
import os
from flask import request
@app.route('/')
def index():
directory_name = request.args.get("directory") # User input
return os.system("ls -lah %s" % directory_name) # User can append any other shell command
class SomeController < ApplicationController
def index
directory_name = params[:directory] # User input
# In Ruby ``, %x(...), system(), exec() are all insecure with user input
command_injection_1 = `ls -lah #{directory_name}`
command_injection_2 = system("ls -lah #{directory_name}")
command_injection_3 = exec("ls -lah #{directory_name}")
command_injection_4 = %(ls -lah #{directory_name})
render :text => command_injection_1
end
end
package main
import (
"fmt"
"os"
"os/exec"
)
func main() {
action := os.Args[1]
out, err := exec.Command("bash", "-c", "git "+action).Output()
if err != nil {
fmt.Println("Execution failed")
} else {
fmt.Println(string(out))
}
}
Secure Example
import os
from flask import request
@app.route('/')
def index():
directory_name = request.args.get("directory") # User input
if directory_name == "documents" or directory_name == "images":
return os.system("ls -lah %s" % directory_name)
else:
return "Unauthorized directory"
class SomeController < ApplicationController
def index
directory_name = params[:directory] # User input
# Only allow a whitelist of directories
if directory_name == "documents" || directory_name == "images"
render :text => `ls -lah #{directory_name}`
else
render :text => "Unauthorized directory"
end
end
end
package main
import (
"fmt"
"os"
"os/exec"
)
func main() {
actions := map[string]string{
"status":"status",
"diff": "diff",
// ...
}
if len(os.Args) != 2 {
fmt.Println("Please provide a command")
os.Exit(1)
}
if action, ok := actions[os.Args[1]]; ok {
out, err := exec.Command("bash", "-c", "git "+action).Output()
if err == nil {
fmt.Println(string(out))
} else {
fmt.Println("Boom")
}
} else {
fmt.Println("Unauthorized command provided")
}
}