8 ms·
So why does this feature require real database users? Why couldn't a statement be added like "SET current_user = some_id;" that is called once per connection an
by orf 11y ago
So why does this feature require real database users? Why couldn't a statement be added like "SET current_user = some_id;" that is called once per connection and have the row level security authenticate against that? Sure, it's not real security, but it's a step up from a single user being able to select everything in your database through a single SQLi as long as you ensure that the "current_user" is the first statement executed.
- merb 11y agoActually you could do that. First your user needs the right to create roles and then you can switch the current user via: http://www.postgresql.org/docs/current/static/sql-set-role.html http://www.postgresql.org/docs/current/static/sql-set-role.h... It's not really the use case for RLS, but its possible. START TRANSACTION; SET LOCAL ROLE rating_role1; SELECT * FROM ratings2; ROLLBACK; Works just fine. Edit: Updated
- orf 11y agoDoes it? If someone had SQLi and could execute statements then couldn't they do "RESET ROLE;" or "ROLLBACK;", then do "SET ROLE admin", or am I missing something? I'm talking about something in-between having 1 database role per user and 1 per app, a configurable string/ID/etc that can be set only once per connection, right at the start. That way a SQLi could only pull records from their user and not all of them.
- merb 11y agoas already said your application connects with user 'xyz' this guy needs the 'CREATEROLE' permission. Than this guy could Create Roles and Switch to them: loki=# CREATE ROLE demo CREATEROLE LOGIN PASSWORD '123'; CREATE ROLE loki=# CREATE DATABASE demo123 OWNER demo; CREATE DATABASE loki=# \q schmitch@SHANGHAI:~$ psql -h localhost -U demo -W demo123 Password for user demo: psql (9.5.2) Type "help" for help. demo123=> CREATE ROLE hase123 WITH ADMIN demo; CREATE ROLE demo123=> SET ROLE hase123; SET demo123=> SELECT CURRENT_USER, SESSION_USER; current_user | session_user --------------+-------------- hase123 | demo (1 row) demo123=> RESET ROLE; RESET demo123=> SELECT CURRENT_USER, SESSION_USER; current_user | session_user --------------+-------------- demo | demo (1 row) So inside a Connection / Transaction you could easily switch users and create them. Also you can't switch to a Role you aren't admin, the only odd thing is, is that they could DROP roles and that they could create roles with more permissions than they have.
- Jweb_Guru 11y agoSET LOCAL ROLE will automatically roll back once the transaction is done.
- merb 11y agoThanks I updated my upper example. ;)
- takeda 11y agoWhile merb provided a workaround, RLS is not intended for web applications that uses a single account for all database communication. Your application should be enforcing this and be written in a way that SQL injections are impossible. This is more for scenarios such as: - a DBA needs access to work on a database, but perhaps he/she should not have access to certain financial information which would enable them to do insider trading. - or perhaps SaaS allows for their users to have direct read access to their database (probably not smart anyway), but want to make sure an user can access information about different users.
- orf 11y agoThat's fair enough, it's very impressive and it seems like a great addition to PG. > Your application should be enforcing this and be written in a way that SQL injections are impossible. I wholeheartedly agree, but it's wishful thinking. It's still the OWASP #1 critical vulnerability and it's still everywhere.
- takeda 11y ago> I wholeheartedly agree, but it's wishful thinking. It's still the OWASP #1 critical vulnerability and it's still everywhere. It's everywhere, because you need to be aware about the problem to mitigate it. The way to mitigate it is that you should never build SQL command in your language (concatenating, formatting etc). Instead you should use variable binding / parametrized queries. When you do you that you ensure that there's separation between an SQL statement and the data and no untrusted data can affect the SQL statement. If you are programming in Python and use PsycoPG2 then first section talks about it[1][2]. [1] http://initd.org/psycopg/docs/usage.html http://initd.org/psycopg/docs/usage.html [2] http://initd.org/psycopg/docs/usage.html#sql-injection http://initd.org/psycopg/docs/usage.html#sql-injection
- snuxoll 11y agoA problem with SET ROLE in particular, however, is that it takes an identifier, not a string - it cannot be parameter. However, PostgreSQL does have a quote_ident function you can use to prevent arbitrary SQL injection (this won't prevent you from injecting a specific DB role, but honestly this is fairly trivial to secure at the application level).