Tuesday, November 27, 2007

Your favorite "better than C" scripting language is probably implemented in C

I was writing an application front-end in Ruby/Gnome2 and I needed to produce an error message for the user that contained a string the user had previously input. My MessageDialog code looked like this:
-------------------------------------------------------------------------
dialog = Gtk::MessageDialog.new(@main_app_window, Gtk::Dialog::MODAL,
Gtk::MessageDialog::INFO,
Gtk::MessageDialog::BUTTONS_CLOSE,
"%s - Was your string!" % my_string)
-------------------------------------------------------------------------
As you can see the variable my_string is placed in the message dialog text using a format specifier correctly according to the man page. I started to wonder what happened if this string contained a format specifier, would the underlying C libraries and bindings display it correctly? Surprise!



No it was not displayed correctly. In fact it was vulnerable to a format string attack straight from the year 2001. UGH! Now you might argue - "Your fault for not sanitizing your string". Well thats true to a point. But the MessageDialog interface is just a very deep abstraction layer to a printf() style function in the GTK C library. But unlike those functions MessageDialog is not well documented as an 'easily mis-used' function.

Programmers typically trust their API to correctly sanitize and display their input, especially in scripting languages. This is because in scripting languages programmers feel they are safe from traditional C language vulnerabilities. This isn't always the case when your abstraction layers don't handle data correctly. My audit to find the offending code took about ten minutes but I narrowed it down to

ruby-gnome2-all-0.16.0/gtk/src/rbgtkmessagedialog.c

Where it calls GTK like this:
w = gtk_message_dialog_new(NIL_P(parent) ? NULL : GTK_WINDOW(RVAL2GOBJ(parent)),
RVAL2GFLAGS(flags, GTK_TYPE_DIALOG_FLAGS),
RVAL2GENUM(type, GTK_TYPE_MESSAGE_TYPE),
RVAL2GENUM(buttons, GTK_TYPE_BUTTONS_TYPE),
(const gchar*)(NIL_P(message) ? "": RVAL2CSTR(message)));

The variable 'message' is passed directly to GTK. I don't blame GTK authors for this one, it would be like blaming libc authors for printf()'s ability to print a variable without a format specifier. The GTK MessageDialog page shows the function prototype for gtk_message_dialog_new()

GtkWidget* gtk_message_dialog_new
(GtkWindow *parent, GtkDialogFlags flags, GtkMessageType type,
GtkButtonsType buttons, const gchar *message_format, ...);


parent: transient parent, or NULL for none
flags: flags
type: type of message
buttons: set of buttons to use
message_format: printf()-style format string, or NULL
...: arguments for message_format

So GTK is clearly expecting a proper format string, which should be properly passed to it by whatever API called it.

Example vulnerable code:
-------------------------------------------------------------------------
#!/usr/bin/env ruby

# ruby rubber.rb %x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x

require 'gtk2'

my_string = ARGV[0]

dialog = Gtk::MessageDialog.new(@main_app_window, Gtk::Dialog::MODAL,
Gtk::MessageDialog::INFO,
Gtk::MessageDialog::BUTTONS_CLOSE,
"%s - Was your string!" % my_string)
dialog.run
dialog.destroy
-------------------------------------------------------------------------
To avoid this issue in your ruby code you could use the markup member. This will use the Pango markup language on your text. Its a workaround but it gets the job done.
-------------------------------------------------------------------------
my_string = ARGV[0]

dialog = Gtk::MessageDialog.new(@main_app_window, Gtk::Dialog::MODAL,
Gtk::MessageDialog::INFO,
Gtk::MessageDialog::BUTTONS_CLOSE)

dialog.markup = "#{my_string} - Was your string!"
dialog.run
dialog.destroy
-------------------------------------------------------------------------
Or alternatively you could do something like "my_string = my_string.gsub(/%/, "%%")" before calling messagedialog.

Using google we can find some other projects vulnerable to similar bugs. Most just stick #{my_string} in the message, including example applications from the official Ruby/Gnome2 website.


That about wraps up this post. Other Ruby/Gnome2 API's may have similar 'functionality'. This should teach all the scripters out there a security lesson. Always remember your favorite "better than C" scripting language is probably implemented in C. Ruby/Gnome2 authors have been notified and they have committed a patch to SVN.

Thursday, November 22, 2007

What Every Programmer Should Know About Memory (PDF)

I just came across this PDF on reddit.com titled "What every programmer should know about memory". Its written by Ulrich Drepper from RedHat, you should know who he is.

Link to PDF

It's going to take me awhile to get through this (its 114 pages long) - but so far its a decent read. I'm currently cheating and searching through it for things that interest me. I'm currently taking in section 7.3 'Measuring Memory Usage'. This section is particularly interesting to me because I've been toying with a project of mine lately that collects massive amounts of data. Searching and sorting that data efficiently has not been easy.

Ulrich states in the PDF that using libc's malloc to store a linked list you populate for later retrieval and use is probably a bad idea. This is true, because theres no guarantee malloc will return memory that is close or even near to the next member in the linked list. There are alternatives to using the traditional libc malloc library such as obstack and Google's TCMalloc.

There's lots of other good stuff in his paper, take a look for yourself.