[gajim/el6] Two security fixes from 0.15 (seen in DSA-2453-1)

Michal Schmidt michich at fedoraproject.org
Thu Apr 19 07:45:51 UTC 2012


commit 30616b553d9fff86162e05c9f90a8feba9de1b00
Author: Michal Schmidt <mschmidt at redhat.com>
Date:   Thu Apr 19 09:44:01 2012 +0200

    Two security fixes from 0.15 (seen in DSA-2453-1)
    
    - CVE-2012-2085
    - CVE-2012-2086

 gajim-CVE-2012-2085.patch |   56 +++++++++++++++
 gajim-CVE-2012-2086.patch |  171 +++++++++++++++++++++++++++++++++++++++++++++
 gajim.spec                |   13 +++-
 3 files changed, 239 insertions(+), 1 deletions(-)
---
diff --git a/gajim-CVE-2012-2085.patch b/gajim-CVE-2012-2085.patch
new file mode 100644
index 0000000..9c99fb1
--- /dev/null
+++ b/gajim-CVE-2012-2085.patch
@@ -0,0 +1,56 @@
+# HG changeset patch
+# User Yann Leboulanger <asterix at lagaule.org>
+# Date 1320788467 -3600
+# Branch gajim_0.15
+# Node ID d19b82b8763b98bd0a88c3e59fc451e3fb4f989c
+# Parent  988e38ce0e0c6a28be3648b1a2a7443e06fd756d
+execute commands without use_shell=True to prevent remote code execution, except for commands configured in triggers plugin (configured by user itself). Fixes #7031
+
+[ fixed a reject with quilt -- michich ]
+
+Index: gajim-0.14.4/src/common/helpers.py
+===================================================================
+--- gajim-0.14.4.orig/src/common/helpers.py
++++ gajim-0.14.4/src/common/helpers.py
+@@ -39,6 +39,7 @@ import errno
+ import select
+ import base64
+ import hashlib
++import shlex
+ import caps_cache
+ 
+ from encodings.punycode import punycode_encode
+@@ -372,8 +373,18 @@ def is_in_path(command, return_abs_path=
+             pass
+     return False
+ 
+-def exec_command(command):
+-    subprocess.Popen('%s &' % command, shell=True).wait()
++def exec_command(command, use_shell=False):
++    """
++    execute a command. if use_shell is True, we run the command as is it was
++    typed in a console. So it may be dangerous if you are not sure about what
++    is executed.
++    """
++    if use_shell:
++        subprocess.Popen('%s &' % command, shell=True).wait()
++    else:
++        args = shlex.split(command.encode('utf-8'))
++        p = subprocess.Popen(args)
++        gajim.thread_interface(p.wait)
+ 
+ def build_command(executable, parameter):
+     # we add to the parameter (can hold path with spaces)
+Index: gajim-0.14.4/src/notify.py
+===================================================================
+--- gajim-0.14.4.orig/src/notify.py
++++ gajim-0.14.4/src/notify.py
+@@ -313,7 +313,7 @@ def notify(event, jid, account, paramete
+         command = gajim.config.get_per('notifications', str(advanced_notif_num),
+             'command')
+         try:
+-            helpers.exec_command(command)
++            helpers.exec_command(command, use_shell=True)
+         except Exception:
+             pass
+ 
diff --git a/gajim-CVE-2012-2086.patch b/gajim-CVE-2012-2086.patch
new file mode 100644
index 0000000..d8fd406
--- /dev/null
+++ b/gajim-CVE-2012-2086.patch
@@ -0,0 +1,171 @@
+# HG changeset patch
+# User Yann Leboulanger <asterix at lagaule.org>
+# Date 1320786052 -3600
+# Branch gajim_0.15
+# Node ID 988e38ce0e0c6a28be3648b1a2a7443e06fd756d
+# Parent  f8214ad3310681dbf23a95c47b064d20c549693d
+use prepared statements in all SQL queries that contains jids to prevent SQL injection. Fixes #7034
+
+diff --git a/src/common/logger.py b/src/common/logger.py
+--- a/src/common/logger.py
++++ b/src/common/logger.py
+@@ -569,7 +569,7 @@
+         except exceptions.PysqliteOperationalError, e:
+             # Error trying to create a new jid_id. This means there is no log
+             return []
+-        where_sql = self._build_contact_where(account, jid)
++        where_sql, jid_tuple = self._build_contact_where(account, jid)
+ 
+         now = int(float(time.time()))
+         timed_out = now - (timeout * 60) # before that they are too old
+@@ -577,14 +577,13 @@
+         # 3 - 8 (we avoid the last 2 lines but we still return 5 asked)
+         try:
+             self.cur.execute('''
+-                    SELECT time, kind, message FROM logs
+-                    WHERE (%s) AND kind IN (%d, %d, %d, %d, %d) AND time > %d
+-                    ORDER BY time DESC LIMIT %d OFFSET %d
+-                    ''' % (where_sql, constants.KIND_SINGLE_MSG_RECV,
+-                            constants.KIND_CHAT_MSG_RECV, constants.KIND_SINGLE_MSG_SENT,
+-                            constants.KIND_CHAT_MSG_SENT, constants.KIND_ERROR,
+-                            timed_out, restore_how_many_rows, pending_how_many)
+-                    )
++                SELECT time, kind, message FROM logs
++                WHERE (%s) AND kind IN (%d, %d, %d, %d, %d) AND time > %d
++                ORDER BY time DESC LIMIT %d OFFSET %d
++                ''' % (where_sql, constants.KIND_SINGLE_MSG_RECV,
++                constants.KIND_CHAT_MSG_RECV, constants.KIND_SINGLE_MSG_SENT,
++                constants.KIND_CHAT_MSG_SENT, constants.KIND_ERROR, timed_out,
++                restore_how_many_rows, pending_how_many), jid_tuple)
+ 
+             results = self.cur.fetchall()
+         except sqlite.DatabaseError:
+@@ -614,18 +613,18 @@
+         except exceptions.PysqliteOperationalError, e:
+             # Error trying to create a new jid_id. This means there is no log
+             return []
+-        where_sql = self._build_contact_where(account, jid)
++        where_sql, jid_tuple = self._build_contact_where(account, jid)
+ 
+         start_of_day = self.get_unix_time_from_date(year, month, day)
+         seconds_in_a_day = 86400 # 60 * 60 * 24
+         last_second_of_day = start_of_day + seconds_in_a_day - 1
+ 
+         self.cur.execute('''
+-                SELECT contact_name, time, kind, show, message, subject FROM logs
+-                WHERE (%s)
+-                AND time BETWEEN %d AND %d
+-                ORDER BY time
+-                ''' % (where_sql, start_of_day, last_second_of_day))
++            SELECT contact_name, time, kind, show, message, subject FROM logs
++            WHERE (%s)
++            AND time BETWEEN %d AND %d
++            ORDER BY time
++            ''' % (where_sql, start_of_day, last_second_of_day), jid_tuple)
+ 
+         results = self.cur.fetchall()
+         return results
+@@ -651,13 +650,13 @@
+                 return results
+ 
+         else: # user just typed something, we search in message column
+-            where_sql = self._build_contact_where(account, jid)
++            where_sql, jid_tuple = self._build_contact_where(account, jid)
+             like_sql = '%' + query.replace("'", "''") + '%'
+             self.cur.execute('''
+-                    SELECT contact_name, time, kind, show, message, subject FROM logs
+-                    WHERE (%s) AND message LIKE '%s'
+-                    ORDER BY time
+-                    ''' % (where_sql, like_sql))
++                SELECT contact_name, time, kind, show, message, subject FROM logs
++                WHERE (%s) AND message LIKE '%s'
++                ORDER BY time
++                ''' % (where_sql, like_sql), jid_tuple)
+ 
+         results = self.cur.fetchall()
+         return results
+@@ -672,7 +671,7 @@
+             # Error trying to create a new jid_id. This means there is no log
+             return []
+         days_with_logs = []
+-        where_sql = self._build_contact_where(account, jid)
++        where_sql, jid_tuple = self._build_contact_where(account, jid)
+ 
+         # First select all date of month whith logs we want
+         start_of_month = self.get_unix_time_from_date(year, month, 1)
+@@ -684,13 +683,13 @@
+         # and take only one of the same values (distinct)
+         # Now we have timestamps of time 0:00 of every day with logs
+         self.cur.execute('''
+-                SELECT DISTINCT time/(86400)*86400 FROM logs
+-                WHERE (%s)
+-                AND time BETWEEN %d AND %d
+-                AND kind NOT IN (%d, %d)
+-                ORDER BY time
+-                ''' % (where_sql, start_of_month, last_second_of_month,
+-                constants.KIND_STATUS, constants.KIND_GCSTATUS))
++            SELECT DISTINCT time/(86400)*86400 FROM logs
++            WHERE (%s)
++            AND time BETWEEN %d AND %d
++            AND kind NOT IN (%d, %d)
++            ORDER BY time
++            ''' % (where_sql, start_of_month, last_second_of_month,
++            constants.KIND_STATUS, constants.KIND_GCSTATUS), jid_tuple)
+         result = self.cur.fetchall()
+ 
+         # convert timestamps to day of month
+@@ -706,19 +705,21 @@
+         """
+         where_sql = ''
+         if not is_room:
+-            where_sql = self._build_contact_where(account, jid)
++            where_sql, jid_tuple = self._build_contact_where(account, jid)
+         else:
+             try:
+                 jid_id = self.get_jid_id(jid, 'ROOM')
+             except exceptions.PysqliteOperationalError, e:
+                 # Error trying to create a new jid_id. This means there is no log
+                 return None
+-            where_sql = 'jid_id = %s' % jid_id
++            where_sql = 'jid_id = ?'
++            jid_tuple = (jid_id,)
+         self.cur.execute('''
+-                SELECT MAX(time) FROM logs
+-                WHERE (%s)
+-                AND kind NOT IN (%d, %d)
+-                ''' % (where_sql, constants.KIND_STATUS, constants.KIND_GCSTATUS))
++            SELECT MAX(time) FROM logs
++            WHERE (%s)
++            AND kind NOT IN (%d, %d)
++            ''' % (where_sql, constants.KIND_STATUS, constants.KIND_GCSTATUS),
++            jid_tuple)
+ 
+         results = self.cur.fetchone()
+         if results is not None:
+@@ -766,6 +767,7 @@
+         Build the where clause for a jid, including metacontacts jid(s) if any
+         """
+         where_sql = ''
++        jid_tuple = ()
+         # will return empty list if jid is not associated with
+         # any metacontacts
+         family = gajim.contacts.get_metacontacts_family(account, jid)
+@@ -775,13 +777,15 @@
+                     jid_id = self.get_jid_id(user['jid'])
+                 except exceptions.PysqliteOperationalError, e:
+                     continue
+-                where_sql += 'jid_id = %s' % jid_id
++                where_sql += 'jid_id = ?'
++                jid_tuple += (jid_id,)
+                 if user != family[-1]:
+                     where_sql += ' OR '
+         else: # if jid was not associated with metacontacts
+             jid_id = self.get_jid_id(jid)
+-            where_sql = 'jid_id = %s' % jid_id
+-        return where_sql
++            where_sql = 'jid_id = ?'
++            jid_tuple += (jid_id,)
++        return where_sql, jid_tuple
+ 
+     def save_transport_type(self, jid, type_):
+         """
diff --git a/gajim.spec b/gajim.spec
index df3d933..31d2ac3 100644
--- a/gajim.spec
+++ b/gajim.spec
@@ -2,7 +2,7 @@ Summary:	Jabber client written in PyGTK
 Name:		gajim
 %global		majorver 0.14
 Version:	0.14.4
-Release:	1%{?dist}
+Release:	2%{?dist}
 License:	GPLv3
 Group:		Applications/Internet
 URL:		http://gajim.org/
@@ -15,6 +15,10 @@ Patch2:		gajim-0.15-12438.patch
 Patch3:		gajim-0.15-13759-bac8e353d25c.patch
 Patch4:		gajim-0.15-13761-f6f78f3802c0.patch
 Patch5:		gajim-0.15-13766-f046e4aaf7d4.patch
+# user assisted code execution
+Patch6:		gajim-CVE-2012-2085.patch
+# SQL injection
+Patch7:		gajim-CVE-2012-2086.patch
 
 BuildArch:	noarch
 BuildRoot:	%(mktemp -ud %{_tmppath}/%{name}-%{version}-%{release}-XXXXXX)
@@ -75,6 +79,8 @@ Gajim does not require GNOME to run, even though it exists with it nicely.
 %patch3 -p1
 %patch4 -p1
 %patch5 -p1
+%patch6 -p1
+%patch7 -p1
 
 %build
 %configure --docdir=%{_docdir}/%{name}-%{version}
@@ -132,6 +138,11 @@ rm -rf %{buildroot}
 %{_datadir}/%{name}/src
 
 %changelog
+* Thu Apr 19 2012 Michal Schmidt <mschmidt at redhat.com> 0.14.4-2
+- Two security fixes from 0.15 (seen in DSA-2453-1):
+- CVE-2012-2085
+- CVE-2012-2086
+
 * Tue Apr 17 2012 Michal Schmidt <mschmidt at redhat.com> 0.14.4-1
 - Update to 0.14.4.
 - Apply fix for CVE-2012-2093.


More information about the scm-commits mailing list