2

I have a string:

parsed[tag] => "first_name: 'Richard'"

I need to execute code that looks like this:

client.put_if_absent("profiles", bot_client_name, {first_name: 'Richard'})

Is it possible I can use that first string to somehow act as code for the equivalent text? I tried using eval(parsed[tag]) but that was a fail.

I changed to the following:

response = "client.put_if_absent('profiles', bot_client_name, {#{parsed[tag]}})"

eval(response)

This actually works --- what can I do to reduce potential risks?

the Tin Man
  • 158,662
  • 42
  • 215
  • 303
Satchel
  • 16,414
  • 23
  • 106
  • 192
  • 3
    Don't do this. Better to use some minor parsing and use `send` if it's a white listed method name. I'd probably try to figure out ways around this requirement altogether. – Dave Newton Nov 27 '14 at 00:13
  • 3
    Where does that string come from and why can't it be in a sensible string format such as JSON? – mu is too short Nov 27 '14 at 00:15
  • I could change the string. In this case "richard" is the user input and could be anything. What would I be able to do if it were in JSON? – Satchel Nov 27 '14 at 11:02

3 Answers3

3

Please do not use eval to parse user input. That is super dangerous, and you will never get it to be safe. Your real goal here appears to be take this string "first_name: 'Richard'" and make this object {first_name: 'Richard'} from it. You don't need eval to accomplish that task.

If you're trying to take user input, and turn it into an object hash, checkout this question. How do I convert a String object into a Hash object? I recommend looking at jackquack's answer in that post to give you an idea about how you can use the methods in Ruby's powerful String library (http://www.ruby-doc.org/core-2.1.4/String.html) to parse your input.

If your user input is in a standard format like JSON, YAML, XML, etc. then you can use a library that will do all this hard work for you. If your user input is in a custom format, such as seems to be your case, then you need to roll that parsing on your own.

Community
  • 1
  • 1
Jazzepi
  • 5,259
  • 11
  • 55
  • 81
  • Using a standard format is ideal, but in a pinch semicolon-separated content is fine. `split(/\s*:\s*/)` does the job. – tadman Nov 27 '14 at 00:23
  • 1
    I used JSON.parse -- I just changed the format of the input, which I could adjust `{"first_name": ""}` via Crack – Satchel Nov 28 '14 at 01:24
  • @Angela That's definitely the right approach if you can get there :) – Jazzepi Nov 28 '14 at 12:36
0

It depends of course of what your tag will be, but what about just parsing it like this:

parsed_tag_hash = Hash[*parsed[tag].scan(/\w+/)]
# {"first_name"=>"Richard"}
client.put_if_absent("profiles", bot_client_name, parsed_tag_hash)
the Tin Man
  • 158,662
  • 42
  • 215
  • 303
oldergod
  • 15,033
  • 7
  • 62
  • 88
-1

Meta-answer, as I don't know Ruby:

Assuming that your string is user input, you need to make sure that it won't lead to anything being executed.

While this might be a tough problem in general, I think you can use known constraints about valid input for your issue to ensure it is not executable. Use regex to ensure there are no end-of-string chars or escape chars in the input that would allow eval to see it as anything other than as single string constant. HTH.

the Tin Man
  • 158,662
  • 42
  • 215
  • 303
Joe Murray
  • 585
  • 5
  • 21
  • This is bad advice. A user should never use eval for simple string parsing, which is super dangerous. There are much better ways to skin this cat. – Jazzepi Nov 28 '14 at 13:02
  • I am answering the queztion posed, not a different one about whether to do this or what alternatives would be safer. l happen to agree it is not a good or safe pattern in general. But if you want to disallow use of eval then a more strongly typed and less scripted language might be appropriate- the function is there in the language definition. – Joe Murray Nov 29 '14 at 17:40
  • This site is full of novices. It isn't responsible advice giving to lead them down a dangerous path simply because they ask how to travel that road. – Jazzepi Nov 29 '14 at 17:45