Zamieszczone przez usa 2013-05-14
Tłumaczone przez crabonature
Wykryto lukę bezpieczeństwa w modułach DL
i Fiddle
w Ruby gdzie niepewne napisy
(tainted strings - napisy, które są wprowadzane z
zewnętrznych źródeł np. pliku, klawiatury, sieci itp.
Są oznaczone specjalną flagą - Object#taint
, Object#untaint
, Object#tainted?
)
mogą być wykorzystane przez wywołania systemowe niezależnie od ustawionego
poziomu $SAFE
w Ruby. Luce tej został przypisany identyfikator CVE-2013-2065.
Wpływ
Natywne funkcje wystawione dla Rubiego z DL
lub Fiddle
nie sprawdzają wartości taint
ustawionej w przekazywanych obiektach. Może to spowodować zaakceptowanie niepewnych
obiektów jako zaufane dane wejściowe, w momencie gdy powinien zostać zgłoszony
wyjątek SecurityError
.
Przykładowy kod DL
ilustrujący lukę będzie wyglądać mniej więcej tak:
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
Przykładowy kod Fiddle
ilustrujący lukę będzie wyglądać mniej więcej tak:
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
Wszyscy użytkownicy podatnych wersji powinni natychmiast zaktualizować Ruby lub skorzystać z obejścia problemu.
Zauważ, że to nie powstrzymuje od użycia numerycznych offsetów pamięci jako wartości wskaźników. Numery nie mogą być tainted, więc kod przekazujący numeryczny offset pamięci nie może być sprawdzony. Dla przykładu:
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
W tym przypadku adres w pamięci jest przekazywany, więc zaufanie obiektu
nie może być określone przez DL
/ Fiddle
. W takim przypadku proszę
sprawdzać zaufanie danych wprowadzanych przez użytkownika przed przekazaniem
adresu w pamięci:
user_input = "uname -rs".taint
raise if $SAFE >= 1 && user_input.tainted?
my_function DL::CPtr[user_input].to_i
Obejście problemu
Gdy nie możesz zaktualizować Rubiego, ta łatka - monkey patch - może być użyta jako obejście problemu:
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
Dotyczy wersji
- Dla 1.9 wszystkie wcześniejsze wersje od 1.9.3 patchlevel 426
- Dla 2.0 wszystkie wcześniejsze wersje od 2.0.0 patchlevel 195
- Wcześniej niż rewizja trunk 40728
Wersje 1.8 nie są podatne.
Podziękowania
Podziękowania dla Vita Ondrucha za zgłoszenie tego problemu.
Historia
- Opublikowane 2013-05-14 13:00:00 (UTC)