Bug 728348 (CVE-2011-2899)

Summary: CVE-2011-2899 system-config-printer: possible arbitrary code execution in pysmb.py due to improper escaping of hostnames
Product: [Other] Security Response Reporter: Vincent Danen <vdanen>
Component: vulnerabilityAssignee: Red Hat Product Security <security-response-team>
Status: CLOSED ERRATA QA Contact:
Severity: medium Docs Contact:
Priority: medium    
Version: unspecifiedCC: jpopelka, twaugh
Target Milestone: ---Keywords: Security
Target Release: ---   
Hardware: All   
OS: Linux   
Whiteboard:
Fixed In Version: Doc Type: Bug Fix
Doc Text:
Story Points: ---
Clone Of: Environment:
Last Closed: 2021-10-19 21:49:16 UTC Type: ---
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: --- RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: --- Target Upstream Version:
Embargoed:
Bug Depends On: 729546, 729547, 729548, 833984    
Bug Blocks: 728350    

Description Vincent Danen 2011-08-04 19:42:34 UTC
It was reported [1] that pysmb.py in system-config-printer does not sanitize a host's netbios name or workgroup/domain name.  A specially crafted netbios name on the local network could cause pysmb.py to execute arbitrary commands based on the hostname.  This was originally reported in Ubuntu against foomatic-gui, and has been patched [2], however the origin of the script in foomatic-gui is in the system-config-printer package.

If a remote SMB server on the local network had a crafted hostname and a user ran pysmb.py, it would be possible for shell commands to be executed with the privileges of the user running pysmb.py.

The pysmb.py script in Red Hat Enterprise Linux 6 does not use os.popen().

[1] https://bugs.launchpad.net/ubuntu/+source/foomatic-gui/+bug/811119
[2] http://cvs.savannah.gnu.org/viewvc/foomatic-gui/foomatic/pysmb.py?root=foomatic-gui&r1=1.2&r2=1.3&view=patch

Comment 1 Vincent Danen 2011-08-04 19:49:29 UTC
It looks like some of the vulnerable functions are called by the system-config-printer (or printconf in Red Hat Enterprise Linux 4) GUI's, but I'm not positive that shell injection will happen there.

It also would require some trickery on the attacker's part, since the netbios name is returned in uppercase, the attacker's SMB server would have to be modified to present the netbios name in lowercase.

On Red Hat Enterprise Linux 5 this does look problematic:

# python /usr/share/system-config-printer/pysmb.py
{'IP': '192.168.251.125', 'DOMAIN': 'MYGROUP'}
{'NAME': "OH'NOTQUOTEZSIF"}
sh: -c: line 0: unexpected EOF while looking for matching `''
sh: -c: line 1: syntax error: unexpected end of file
{}
{'IP': '192.168.250.50', 'DOMAIN': 'ANNVIX'}

However, I'm not sure about RHEL4 as running the script presents some problems:

% /usr/share/printconf/util/pysmb.py
Domain=[WORKGROUP] OS=[Apple Base Station] Server=[CIFS 4.32]
Domain=[WORKGROUP] OS=[Apple Base Station] Server=[CIFS 4.32]
Receiving SMB: Server stopped responding
{}

It might be possible to get this to work on RHEL4 (it does use os.popen() as well), but it's not picking up any real samba servers like the script does on RHEL5.

Comment 2 Huzaifa S. Sidhpurwala 2011-08-10 06:12:40 UTC
So using a local samba server on the same machine i am able to reproduce this on RHEL4 as well.

Relevant config in samba.conf:

        netbios name = oh'notquotezSIF

[root@athlon3 ~]# /etc/init.d/smb start
Starting SMB services: [  OK  ]
Starting NMB services: [  OK  ]

[root@athlon3 ~]# python /usr/share/printconf/util/pysmb.py
sh: -c: line 0: unexpected EOF while looking for matching `''
sh: -c: line 1: syntax error: unexpected end of file
{}

[root@athlon3 ~]# /etc/init.d/smb stop
Shutting down SMB services: [  OK  ]
Shutting down NMB services: [  OK  ]

[root@athlon3 ~]# python /usr/share/printconf/util/pysmb.py
Domain=[WORKGROUP] OS=[Windows 5.0] Server=[Windows 2000 LAN Manager]
Domain=[WORKGROUP] OS=[Windows 5.0] Server=[Windows 2000 LAN Manager]
{}

Comment 4 Tim Waugh 2011-08-10 11:31:14 UTC
FWIW the patch at savannah introduces a typo:

@@ -59,26 +67,29 @@
                 if val.find ("~") != -1:
                     continue
 
-                if l.find (" <GROUP> ") != -1 and not dict.has_key ('GROUP'):
-                    dict['GROUP'] = l.split (" ")[0]
+                if l.find (" <GROUP> ") != -1 and not dct.has_key ('GROUP'):
+                    dct['GROUP'] = l.split (" ")[0]
===>             elif not dict.has_key ('NAME'):
                     name = l.split (" ")[0]
-                    dict['NAME'] = name
+                    dct['NAME'] = name

That line should read:

elif not dct.has_key ('NAME'):

The perils of doing "minor clean-ups" while fixing some other problem...

Comment 5 errata-xmlrpc 2011-08-23 14:41:33 UTC
This issue has been addressed in following products:

  Red Hat Enterprise Linux 5
  Red Hat Enterprise Linux 4

Via RHSA-2011:1196 https://rhn.redhat.com/errata/RHSA-2011-1196.html