Package: ruby1.8 Version: 1.8.2-7sarge2 Severity: grave Tags: security patch Justification: user security hole
Japan Vender Status Notes (JVN) announced two vulnerabilities for Ruby. JVN#13947696: Some methods have defects that they can call other methods, which really should be prohibited, in safe level 4. * Information: * http://jvn.jp/jp/JVN%2313947696/index.html (in Japanese) * http://www.ipa.go.jp/security/vuln/documents/2006/JVN_13947696_Ruby.html (in Japanese) * Affected versions: All versions and snapshots before Ruby 1.8.4-20060516. JVN#83768862: Alias features cannot handle safe levels correclty, so it can be safety bypass. * Information: * http://jvn.jp/jp/JVN%2383768862/index.html (in Japanese) * http://www.ipa.go.jp/security/vuln/documents/2006/JVN_13947696_Ruby.html (in Japanese) * Affected versions: All versions and snapshots before Ruby 1.8.4-20060516. Since currently the upstream does not plan to release patches, I've created ones to fix them. I wish they works, but I have no confidence (especially for JVN#13947696) and would like to have them reviewed. alias_safe_level.patch: May fix JVN#83768862, based on "eval.c (rb_call0)" part and "eval.c (rb_alias)" part for http://www.atdot.net/~ko1/w3ml/w3ml.cgi/ruby-cvs/msg/16613 (and http://www.ruby-lang.org/cgi-bin/cvsweb.cgi/ruby/eval.c?cvsroot=src&r1=1.616.2.166&r2=1.616.2.167 ). avoid_modifying_untainted_objects.patch: May fix JVN#13947696, based on "re.c (rb_reg_initialize)" part for http://www.atdot.net/~ko1/w3ml/w3ml.cgi/ruby-cvs/msg/16723 (and http://www.ruby-lang.org/cgi-bin/cvsweb.cgi/ruby/re.c?cvsroot=src&r1=1.114.2.17&r2=1.114.2.18 ). avoid_modifying_untainted_objects_2.patch: May fix JVN#13947696, based on http://www.atdot.net/~ko1/w3ml/w3ml.cgi/ruby-cvs/msg/16724 (and http://www.ruby-lang.org/cgi-bin/cvsweb.cgi/ruby/dir.c?cvsroot=src&r1=1.92.2.32&r2=1.92.2.33 ). -- System Information: Debian Release: 3.1 Architecture: i386 (i686) Kernel: Linux 2.6.8-3-686 Locale: LANG=ja_JP.eucJP, LC_CTYPE=ja_JP.eucJP (charmap=EUC-JP) Versions of packages ruby1.8 depends on: ii libc6 2.3.2.ds1-22sarge3 GNU C Library: Shared libraries an ii libruby1.8 1.8.2-7sarge2 Libraries necessary to run Ruby 1. -- no debconf information
--- eval.c.orig Thu Jul 13 01:48:12 2006 +++ eval.c Thu Jul 13 01:49:37 2006 @@ -2050,7 +2050,8 @@ } } st_insert(RCLASS(klass)->m_tbl, name, - (st_data_t)NEW_METHOD(NEW_FBODY(body, def, origin), orig->nd_noex)); + (st_data_t)NEW_METHOD(NEW_FBODY(body, def, origin), + NOEX_WITH_SAFE(orig->nd_noex))); if (singleton) { rb_funcall(singleton, singleton_added, 1, ID2SYM(name)); } @@ -5561,6 +5562,11 @@ TMP_PROTECT; volatile int safe = -1; + if (NOEX_SAFE(flags) > ruby_safe_level && + !(flags&NOEX_TAINTED) && ruby_safe_level == 0 && NOEX_SAFE(flags) > 2) { + rb_raise(rb_eSecurityError, "calling insecure method: %s", + rb_id2name(id)); + } switch (ruby_iter->iter) { case ITER_PRE: itr = ITER_CUR; @@ -5664,10 +5670,6 @@ b2 = body = body->nd_next; if (NOEX_SAFE(flags) > ruby_safe_level) { - if (!(flags&NOEX_TAINTED) && ruby_safe_level == 0 && NOEX_SAFE(flags) > 2) { - rb_raise(rb_eSecurityError, "calling insecure method: %s", - rb_id2name(id)); - } safe = ruby_safe_level; ruby_safe_level = NOEX_SAFE(flags); }
--- re.c.orig Thu Jul 13 01:48:12 2006 +++ re.c Thu Jul 13 01:49:45 2006 @@ -1330,6 +1330,8 @@ { struct RRegexp *re = RREGEXP(obj); + if (!OBJ_TAINTED(obj) && rb_safe_level() >= 4) + rb_raise(rb_eSecurityError, "Insecure: can't modify regexp"); if (re->ptr) re_free_pattern(re->ptr); if (re->str) free(re->str); re->ptr = 0;
--- dir.c.orig Thu Jul 13 01:48:12 2006 +++ dir.c Thu Jul 13 01:49:53 2006 @@ -325,7 +325,17 @@ rb_raise(rb_eIOError, "closed directory"); } +static void +dir_check(dir) + VALUE dir; +{ + if (!OBJ_TAINTED(dir) && rb_safe_level() >= 4) + rb_raise(rb_eSecurityError, "Insecure: operation on untainted Dir"); + rb_check_frozen(dir); +} + #define GetDIR(obj, dirp) do {\ + dir_check(dir);\ Data_Get_Struct(obj, struct dir_data, dirp);\ if (dirp->dir == NULL) dir_closed();\ } while (0) @@ -535,6 +545,9 @@ { struct dir_data *dirp; + if (rb_safe_level() >= 4 && !OBJ_TAINTED(dir)) { + rb_raise(rb_eSecurityError, "Insecure: can't close"); + } GetDIR(dir, dirp); closedir(dirp->dir); dirp->dir = NULL;