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;