Geschrieben von usa am 14.5.2013
Übersetzt von Marcus Stollsteimer
Es besteht eine Verwundbarkeit in DL und Fiddle in Ruby, wodurch als “tainted” eingestufte Strings unabhängig von dem durch Ruby festgelegten $SAFE-Level in Systemaufrufen verwendet werden können. Dieser Schwachstelle wurde die CVE-Nummer CVE-2013-2065 zugewiesen.
Auswirkungen
Native Funktionen, die mittels DL oder Fiddle von Ruby aus aufgerufen werden, überprüfen nicht den “taint”-Status der ihnen übergebenen Objekte. Dies kann dazu führen, dass als “tainted” eingestufte Objekte als Eingabe akzeptiert werden anstatt eine SecurityError-Ausnahme auszulösen.
Betroffener Code für DL kann etwa folgendermaßen aussehen:
def my_function(user_input)
handle = DL.dlopen(nil)
sys_cfunc = DL::CFunc.new(handle['system'], DL::TYPE_INT, 'system')
sys = DL::Function.new(sys_cfunc, [DL::TYPE_VOIDP])
sys.call user_input
end
$SAFE = 1
my_function "uname -rs".taint
Betroffener Code für Fiddle kann etwa folgendermaßen aussehen:
def my_function(user_input)
handle = DL.dlopen(nil)
sys = Fiddle::Function.new(handle['system'],
[Fiddle::TYPE_VOIDP], Fiddle::TYPE_INT)
sys.call user_input
end
$SAFE = 1
my_function "uname -rs".taint
Alle Nutzer eines betroffenen Releases sollten dringend aktualisieren oder einen der folgenden Workarounds anwenden.
Beachten Sie, dass dies eine Verwendung von numerischen Memory-Offsets als Pointer-Werte nicht verhindert. Zahlen können nicht als “tainted” markiert werden, so dass Code, der einen numerischen Memory-Offset übergibt, nicht überprüft werden kann. Zum Beispiel:
def my_function(input)
handle = DL.dlopen(nil)
sys = Fiddle::Function.new(handle['system'],
[Fiddle::TYPE_VOIDP], Fiddle::TYPE_INT)
sys.call input
end
$SAFE = 1
user_input = "uname -rs".taint
my_function DL::CPtr[user_input].to_i
In diesem Fall wird der Speicherort übergeben und der “taint”-Status des Objekts kann von DL / Fiddle nicht festgestellt werden. Überprüfen Sie in solchen Fällen den “taint”-Status der Benutzereingabe vor der Übergabe des Speicherorts:
user_input = "uname -rs".taint
raise if $SAFE >= 1 && user_input.tainted?
my_function DL::CPtr[user_input].to_i
Workarounds
Wenn ein Upgrade von Ruby nicht möglich ist, kann der folgende Monkeypatch als Notlösung verwendet werden:
class Fiddle::Function
alias :old_call :call
def call(*args)
if $SAFE >= 1 && args.any? { |x| x.tainted? }
raise SecurityError, "tainted parameter not allowed"
end
old_call(*args)
end
end
Betroffene Versionen
- Alle Versionen von Ruby 1.9 vor Ruby 1.9.3 patchlevel 426
- Alle Versionen von Ruby 2.0 vor Ruby 2.0.0 patchlevel 195
- Alle Trunk-Versionen vor Revision 40728
Ruby 1.8 ist nicht betroffen.
Danksagung
Vielen Dank an Vit Ondruch für das Melden dieses Problems.
Verlauf
- Erstmals veröffentlicht am 2013-05-14 13:00:00 (UTC)