summaryrefslogtreecommitdiff
path: root/docs/security.txt
blob: 383c9929fc9fe7bb712c3ce68d36ef305c1e61f9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
			Security and PackageKit

This document is a brief overview of security policies and notes about security
in the PackageKit project. It has been written by the PackageKit authors, and
should not be treated as independent analysis. This document has been written as
packagekitd is a system activated daemon running as the root user (uid 0), which
means the package management system is run as root also. The daemon receives
untrusted input from the client, which means the daemon is security sensitive.

First, a high level overview, in this case using the hif backend as an example:

  gpk-update-icon      gpk-application
        |                 ___/
     [D-Bus]  __[D-Bus]__/
        |    /
   packagekitd -- [D-Bus] -- polkitd-1
        |
      thread using libhif (using librepo, hawkey, etc)

packagekitd does not expose itself remotely over XMLRPC or other remote
interface, and so a remote denial of service or exploit is impossible without a
serious exploit of other services such as D-Bus. It advertises a simple interface
that can be queried by clients in unprivileged and privileged modes.
The privileged modes are controlled using PolicyKit, and policy and the
authentication mechanism is deferred to the polkitd-1 service.

When a privileged method is executed, the daemon checks with polkitd-1 daemon
for whether the client is authorized for the action it wants to perform.
This may involve the user authenticating that they are either the user (by
typing their password) or that they are an administrative user (by typing the
root password or the password of a user designated as an administrative user).
The authorization check can take some time, but the daemon can process other
requests whilst waiting for user input. Please see the the PolicyKit-1 man page
for more information.

The packagekitd daemon is started using D-Bus system activation, which means it
is started without any environment (no PATH, etc) and therefore is impossible to
exploit by preloading other libraries. It is also running as uid 0, and so
requires root privileges to inject code into it.

A typical transaction would be for the client to request a TID (transaction ID)
to which the server responds by creating a transaction instance and exposing
this on the system bus. The client then connects to this interface, and executes
the chosen method. This method will emit signals such as ::Package(), then
::Finished() and then after a number of seconds ::Destroy() which will remove
the interface from the bus.

There is a concern that a session service can be written to automatically
authenticate methods, and replace the native client, but this is not possible.

When authenticating, polkitd-1 passes a cookie to the authentication agent. If
the user enters the right password, the authentication agent calls
AuthenticationAgentResponse on the Authority with the cookie for the
authentication request. If the caller of AuthenticationAgentResponse is not
uid 0, then it is ignored.

The authentication setuid root polkit-agent-helper-1 only decides to invoke this
method if the user actually successfully authenticated. This of course relies on
polkit-agent-helper-1 being a secure program. This is easy to verify since
this is just over 300 lines of code and only depends on PAM (which is supposed
to be secure) up until we have decided that the user successfully authenticated.
Only when that is done, we initialize other libraries to send the message.

Possible attack vectors:

 * A client could cause a local DoS (denial of service) by repeatedly calling
 CreateTransaction without then calling a method to use this TID. This is mitigated by
 timing out Tid request after a present number of seconds, and the effect can be
 limited with a config variable (SimultaneousTransactionsForUid).

 * Local DoS by repeatedly calling non-privileged methods such as Resolve and
 SearchName. This could be mitigated by limiting the number of requests per
 second for a certain seat, although no code has been written to do this at
 present.

 * A privileged method could be requested and then ignored or hidden by the
 window manager. This is mitigated by not blocking the daemon when processing
 authentication, and timing-out the authentication after a number of seconds if
 authentication credentials are not supplied.

 * Passing untrusted input to the backend which could be used to crash and
 exploit the underlying package system. This is mitigated by rejecting invalid
 input to methods, and testing filenames for existence before they are passed
 to the backend.

 * Issuing a large amount of data to a method to cause a local denial of
 service, for instance calling Resolve with millions of parameters. This is
 mitigated in the daemon by checking for a sane number of requests
 (MaximumPackagesToProcess) for each method, and also limiting the total length
 of the data.

 * The HTTP and FTP proxies that are sent by the session may contain embedded
 usernames and passwords. Whilst these are sent in plain text over the system
 D-Bus (FIXME?), the database is not be readable by users (mode 0640).

 * The matching of UID and session to proxies assumes that the user cannot
 modify the login UID, and cannot spoof a session in ConsoleKit. If a user were
 able to change the apparent UID, then this would allow them to use proxy
 settings set from another user.
 This is manifested when a graphical application is run using sudo (which you
 should never do, but I digress) and different proxy settings may be used from
 the user settings. It also allows applications run using sudo to use the proxy
 specified by root, which may be different.

 * We save the UID and session to a database to get the proxy state for each
 transaction. If the user is able to create a large number of different sessions
 then this will add many entries to the database. Some rate-limiting could be
 added to ConsoleKit or PackageKit to solve this, but has not been done at this
 time.