Locking Ruby in the Safe
Walter Webcoder has a great idea for a portal site: The Web Arithmetic
Page. Surrounded by all sorts of cool mathematical links and banner
ads that will make him rich is a simple central frame, containing a
text field and a button. Users type an arithmetic expression into the
field, press the button, and the answer is displayed. All the world's
calculators become obsolete overnight, and Walter cashes in and retires to
devote his life to his collection of car license plate numbers.
Implementing the calculator is easy, thinks Walter. He accesses the
contents of the form field using Ruby's CGI library, and uses
method to evaluate the string as an expression.
cgi = CGI::new("html4")
# Fetch the value of the form field "expression"
expr = cgi["expression"].to_s
result = eval(expr)
rescue Exception => detail
# handle bad expressions
# display result back to user...
Roughly seven seconds after Walter puts the application online, a
twelve-year-old from Waxahachie with glandular problems and no real
life types ``
'' into the form and, like his
application, Walter's dreams come tumbling down.
Walter learned an important lesson: All external data is
dangerous. Don't let it close to interfaces that can modify your
In this case, the content of the form field was the
external data, and the call to
was the security breach.
Fortunately, Ruby provides support for reducing this risk. All
information from the outside world can be marked as
. When running in a safe mode, potentially dangerous
methods will raise a
if passed a tainted object.