Re: Some notes about the index-functions security vulnerability
От | Trevor Talbot |
---|---|
Тема | Re: Some notes about the index-functions security vulnerability |
Дата | |
Msg-id | 90bce5730801131959t594ea210y361af31e036745ca@mail.gmail.com обсуждение исходный текст |
Ответ на | Some notes about the index-functions security vulnerability (Tom Lane <tgl@sss.pgh.pa.us>) |
Список | pgsql-hackers |
On 1/8/08, Tom Lane <tgl@sss.pgh.pa.us> wrote: > The other issue that ought to be on the TODO radar is that we've only > plugged the hole for the very limited case of maintenance operations that > are likely to be executed by superusers. If user A modifies user B's > table (via INSERT/UPDATE/DELETE), there are a lot of bits of code that are > controlled by B but will be executed with A's permissions; so A must trust > B a whole lot. This general issue has been understood for quite some > time, I think, but maybe it's time to make a serious push to solve it. High-level brain dump, does not cover all the use cases I'm sure... Given Invoker executing code created by Definer, there are basically 3 situations: 1) Definer does not trust Invoker, but Invoker trusts Definer. -> use Invoker's permission set This is probably the case for most system/library generic functions, such as the various trigger templates They are typically owned by a superuser 2) Invoker does not trust Definer, but Definer trusts Invoker. -> use Definer's permission set This case covers most triggers, since they are there to maintain Definer's data, and Invoker's input is inherently controlled. 3) Neither trusts the other. -> use the intersection of Invoker's and Definer's permission sets This is essentially the case for any arbitrary functions floating around, where Invoker's input is not inherently controlled, and Definer is an unknown entity. Situation 1 is covered by SECURITY INVOKER, and 2 is covered by SECURITY DEFINER. Suppose another function option is added for situation 3, "SECURITY INTERSECTION". Also suppose there is a new role option, "TRUSTED" (needs a better name). * A function is created with SECURITY INTERSECTION by default. * A function's owner can choose SECURITY DEFINER. * Only a role with TRUSTED can choose SECURITY INVOKER. * Only the superuser has TRUSTED by default. The idea here is that by default, neither Invoker nor Definer need to be terribly concerned. If Definer is creating the function specifically to operate on its own data, and is checking input appropriately, SECURITY DEFINER will allow it to work. If Definer is creating the function for generic use purposes, Invoker will want to apply it to its own data, and SECURITY INVOKER is appropriate for that. A Definer's trustworthiness for all Invokers is determined by the superuser via the TRUSTED role option. > Offhand I can cite the following ways in which B could exploit A's > privileges: > * triggers Ideally Invoker's permission set would be replaced by the trigger owner's for the duration of the call. However it doesn't look like there actually is an owner concept for triggers, despite there being a TRIGGER permission for the associated table. The next appropriate option is to assign the table owner's permission set to Invoker. In the case of functions marked SECURITY INVOKER, this leaves a hole: a role that has TRIGGER permission on the table can elevate its permissions to that of the table owner's when calling that function. If the role with TRIGGER permission is not TRUSTED, it can only create new functions with SECURITY INTERSECTION, which will result in executing with its own permissions at best. This seems reasonable. > * functions in indexes > * functions in CHECK constraints > * functions in DEFAULT expressions > * functions in rules (including VIEW definitions) Replace the Invoker's permission set with the table owner's for the duration of the call. These all require you to be the owner of the associated object, so there is no potential hole as with triggers. > The first three of these are probably not too difficult to solve: we could > switch privilege state to the table owner before executing such functions, > because the backend knows perfectly well when it's doing each of those > things. But default expressions and rules get intertwined freely with > query fragments supplied by the calling user, and it's not so easy to see > how to know what to execute as which user. I'll just wave my hands wildly here and say functions in expressions supplied by the Invoker magically avoid being called with the object owner's permission set instead. I don't know how, they just do :) What this doesn't allow is actually executing things like VIEW expressions using the calling user's permission set. I don't have an actual use case for that, but I feel it's a problem somehow. I've also completely avoided things like CURRENT_USER by talking about permission sets only.
В списке pgsql-hackers по дате отправления: