Reputation: 4339
In my Rails controller, I take a URL that the user inputs and runs the system command wget
:
system("wget #{url}")
I'm afraid that the user might put in something like www.google.com && rm -rf .
, which would make the controller execute the command
system("wget www.google.com && rm -rf .")
which deletes everything. How should I prevent against this kind of attacks? I'm not sure what other things the user could put in to harm my system.
Upvotes: 2
Views: 665
Reputation: 94
If all you want to do is to just retrieve the content of the URL, it is better to completely avoid the use of 'system' or any other means of running a command on the server.
You can use an http client such as Httparty to fetch the URL content.
response = HTTParty.get("#{url}")
Upvotes: 2
Reputation: 62668
Per this thread:
You can avoid shell expansion by passing arguments to the script individually:
system("/bin/wget", params[:url])
Per the documentation on Kernel#system this form does not invoke a shell. Constructs like &&
are shell constructs, so if you use this form, then the param will be passed to /bin/wget
literally as an argument.
That said, still be suspicious of input, sanitize where possible, and if feasible, run it as a non-privileged (or better yet, jailed) user.
Upvotes: 3
Reputation: 34571
Joining commands together with &&
(or ;
, or |
) is a shell feature, not something that wget
itself understands. If you're using a function that passes a command line to a shell (such as the system()
function in many languages), you're at risk. If you execute the wget
program directly (rather than executing a shell and giving it a command line), you won't be at risk of that particular attack.
However, the attacker could still do other things, like abuse wget
's -O
option to overwrite files. You'd be better off not using wget
at all — if your goal is to download a file, why not just use an HTTP library to do it directly in your own program's code?
Upvotes: 2