MS Azure SQL - How to restrict User to one [custom] schema without the ability to access [sys] and [INFORMATION_SCHEMA] - tsql

I've performed the following:
created a new [custom] schema on the [customer_db]
created new [login] & [user] in the [master] and corresponding user
in the [customer_db]
granted 'db_datareader' and 'db_denydatawriter' to [user]
ALTER AUTHORIZATION ON SCHEMA::custom TO [user]
DENY SELECT ON schema::[dbo] TO [user]
DENY SELECT ON schema::[sys] TO [user]
DENY SELECT ON schema::[INFORMATION_SCHEMA] TO [user]
...but when I am trying this new, restricted login it still allows me to see all the [sys] and [INFORMATION_SCHEMA] related tables & views
I've also tried:
DENY SELECT, VIEW DEFINITION ON SCHEMA::[sys] to [user];
GO
DENY SELECT, VIEW DEFINITION ON SCHEMA::[INFORMATION_SCHEMA] to [user];
GO
This also completed successfully but it took no effect as well.
How can I restrict specific user to a specific schema only without [sys] and [INFORMATION_SCHEMA] listings?
Note/Update:
The DENY VIEW SERVER STATE TO [user]; returns:
Msg 40520, Level 16, State 1, Line 1
Securable class 'server' not supported in this version of SQL Server.

I didn't have an install of SQL 2000 handy, but working off of a modern version of SSMS and a local SQL Server linked to an Azure SQL DB I was able to see some things which may shed some light:
First off: SQL Server in Azure mimics as closely as possible the behaviors of the on premise versions of SQL Server. It appears that the catalog of views that you showed is available for the permission level of the login we created; I may not have reproduced the exact circumstances, but I was able to see the existence of system views when my permissions should, in theory, have been restricting them from my view. This seems to go against the spirit of the concept of permissions.
However, this is not unprecedented:
SELECT * FROM sys.databases
Will return master & the current database. (Try it with your restricted permissions- it should still succeed, even though it's technically a sys view).
Yet, a similar query
SELECT * FROM sys.objects
Throws an expected error (... The SELECT permission was denied on the object 'objects', database 'mssqlsystemresource', schema 'sys'.).
Now, if you're able to select from any/all views listed, this is an entirely different behavior and contradicts the permission entirely.
This was also examined partially in this related question , this one involving sys views specifically, and has a bit of documentation on MSDN too.
EDIT: Here's one more on the INFORMATION_SCHEMA specifically

Related

How to use security policy packages on Databricks

I am trying to create data security policies on user tables on Databricks. However i have implemented this task on SQL server with below SQL Queries
CREATE FUNCTION [test].[mailfunction](#useremail AS nvarchar(100))
RETURNS TABLE WITH SCHEMABINDING AS
RETURN SELECT 1 AS mailfunction_result WHERE #useremail = SUSER_SNAME()
GO
create SECURITY POLICY [mailfunctionSecurityPolicy]
ADD FILTER PREDICATE [test].[mailfunction]([useremail]) ON
test.users WITH (STATE = OFF);
And i am trying this to implement on Databrick and created the function but i am not able to create SECURITY POLICY on Databricks.
I need to create the function or work around for Create function in databricks and need to archive role base access control on my table as we achieved in SQL side.
Also please suggest some reference code for implement Role based access and Row and Column level security and data masking implementation databricks.
Right now there is no exact the same functionality but it's coming in the near future - you can watch latest Databricks quarterly roadmap webinar to get more details about upcoming functionality for RBAC & ABAC.
But right now you can dynamic views over the tables to implement row-level access control and data masking. For this you can use current_user and is_member functions to perform checks. Like this (example from docs):
CREATE VIEW sales_redacted AS
SELECT user_id,
CASE WHEN
is_member('auditors') THEN email
ELSE 'REDACTED'
END AS email,
country, product, total
FROM sales_raw
And you can use user/group names from the data itself, it's not necessary to use hard-coded group names in the is_member call. You can see example in the following answer.

Selecting from pg_stat_user_indexes using superuser

I'm trying to setup some custom monitoring for postgres and one of the metrics I want to see is the index usage from pg_stat_user_indexes. I have multiple databases, each of them have indexes and I want a single metrics role that has access to all of them.
The problem is that when I select * from pg_stat_user_indexes using the metrics role I see no results. But if I select with the individual database role I see the stats just fine.
The metrics role is a superuser with Bypass RLS. I tried looking at pg_stat_all_indexes but I can see only pg_* stuff.
https://www.postgresql.org/docs/current/static/monitoring-stats.html#pg-stat-all-indexes-view
The pg_stat_all_indexes view will contain one row for each index in
the current database, showing statistics about accesses to that
specific index. The pg_stat_user_indexes and pg_stat_sys_indexes views
contain the same information, but filtered to only show user and
system indexes respectively.
emphasis mine
Seems like you need to be connected to the specific database you want to monitor (not to postgres db) in order to see those stats.
Bizarre.. would have at least expected to see them all in pg_stat_all_indexes - it should have been named pg_stat_all_indexes_for_current_database_plus_pg_catalog - I know.. but pg_stat_all_indexes is not all indexes at all..

In SQL Server 2008R2 can I force a View to use objects within the user's default schema instead of the schema in which the View exists?

A bit of background. I have a base application and most clients use it as standard. However some clients have small code and database customisations.
Each of these clients has their own branch and maintenance can be tricky.
I want to consolidate all these into a single database structure (not a single database - we aren't doing multi-tenancy) to enable upgrades to be applied in a much more uniform fashion.
I'm still at the proof of concept stage, but the route I was going down would be to have the standard objects stay in the schema they currently exist in (mostly dbo) and have the custom objects reside in a schema for each client.
For example, I could have dbo.users and client1.users which has some additional columns. If I set the default schema for the client to be "client1" then the following query
SELECT * FROM users
will return data from the client1 schema or the dbo schema depending on which login is connected.
This is absolutely perfect for what I'm trying to achieve.
The problem I'm running into is with Views.
I have many views which are in the dbo schema and refer to the Users table. No matter which user I connect to the database as, these views always select from dbo.users.
So I'm guessing the question I have is:
Can I prefix the tables in the view with some variable like "DEFAULT"? e.g.
SELECT u.username, u.email, a.level
FROM DEFAULT.users u INNER JOIN accessLevels a ON u.accessID = a.accessID
If this isn't possible and I'm totally barking up the wrong tree, do you have any suggestions as to how I can achieve what I'm setting out to do?
Many thanks.
Just reference the name of the schema in which the views reside...
Select a., b.
from schema1.TABLEA A
join schema2.TABLEB B on A.ID = B.ID

SELECT WHERE CASE statement

I am working on a project in which the user's access to records is restricted based on the user's User Group. I have created a global variable $usr_sec_group, and I want to add to the WHERE clause in the SELECT statement for several applications a CASE statement that applies a different filter based on the value of $usr_sec_group. I am a relative "newbie" with regards to mySQL, and my attempts at writing such a statement haven't worked. Here is the basic logic:
SELECT
field1,
field2,
etc
FROM
Organizations
CASE $user_sec_group
WHEN 1 THEN 'filter_statement_1'
WHEN 2 THEN 'filter_statement_2'
WHEN 3 THEN 'filter_statement_3'
ELSE 'filter_statement_else'
END CASE
ORDER By
field1
The 'filter_statements' could be any valid filter, such as
'oName => 'a' AND oName < 'g'
I am assuming that the problem is a relatively simple matter of syntax, but so far I haven't been able to write a CASE statement that works.
I will be grateful for some guidance!
Best regards,
Eric
Your attempted solution will not work: it's not just a question of syntax, you would have to use dynamic sql. Even if you used dynamic sql, it is not a good way to manage access permissions.
A better way is to create specific views at various levels of access and then grant appropriate access to specific users and revoke access for others:
GRANT SELECT ON MyDatabase.viewABC
TO 'someuser'#'somehost';
See
The Grant/Revoke Command
An introduction to MySQL permissions
How to grant multiple users privileges; MySQL

Website security, sql injection and file permissions

I am building a very small website (with PHP) and I have 2 big issues
The first one is about my search form
I have build a really simple search form in order to retrieve my content, then I used an online security tool and show me that my search form was vulnerable to SQLi
I had no idea abut that so I started testing some attacks I found on some sites
As far as now only 'OR 'x'='x worked (it returns the entire content of my website, is this bad? How can an attacker hurt me?
The second issue is about my photos, I am using a folder called mywebsite.com/uploads/ to access my photos
Although /upload is protected the subfolders uploads/temp and uploads/thumbs are visible through the browser
May this be hurtful too?
Any advice?
SQL injection is really bad but i like it :)
there is many types of sql injection like
remote sql injecton
blind sql injection
auto bypass sql injection
**Remote sql injection**
its the easy way to get data from site hacker use it like coders
see this example
mysql_query("SELECT * FROM `table_name` WHERE id=".$_GET['id']." ) ;
There is no security in my code
site.php?id=1
my query will execute like
mysql_query("SELECT * FROM `table_name` WHERE id=1 ) ;
if hacker he will kill your code
site.php?id=1(any thing here can make problem ex: ` ' a-z A-Z / * / " )
Because query will be like this
mysql_query("SELECT * FROM `table_name` WHERE id=1' ) ;
so single quotaion will make error in your query
and hacker can attack like this
site.php?id=1 union select 0,1,concat(user_name,0x3a,password),3,4 from users
here your query will execute like
mysql_query("SELECT * FROM `table_name` WHERE id=1 union select 0,1,concat(user_name,0x3a,password),3,4 from users) ");
and this will work :)
blind sql injection
hacker cannot work with easy way remote sql injection
because it here depend on right and false
so he will use and or
like this
and (select user_name from users) ;
if work fine the script will work good else error will happen
he can know database info like this
example admin table is admin
and (select user_name from users) ; x error
and (select user_name from admin) ; fine
auto bypass
its blicd sql injection but only true condition can access to admin
mysql_query("SELECT * FROM `users` WHERE `user_name`= ".$_POST['user']." AND `password` ='".md5($_POST['pass'])."' ");
hacker can login like this
user = anything' or 1=1 --
so your query will be like
mysql_query("SELECT * FROM `users` WHERE `user_name`= anything or 1=1 --");
anything is error user in databse
but condition or 1=1 is true
-- will ignore your password check
he can access easily
protect
addslashes _ mysql_real_escape_string _ intval ( with number only )
folder premission you can use
empty index.html , index.php ,
If you allow SQL injection, an attacker can do all sorts of bad things to your website. They can inject code to DROP DATABASE, deleting your entire database!
If you are logging into your mysql as the root user, they can potentially write to files (and create) files on your server.
The injection;
SELECT '<?php system($_GET[''cmd'']); ?>' INTO dumpfile('./command.php');
Would be a common first step to breaking into your server, allowing the attacker to execute arbitrary commands under the www-data user. From here it is trivial to recruit your server into a botnet, use it to send spam (getting you blacklisted from sending emails), or simply delete all your files just to ruin your day.
What you must do, is to sanitise all user input. So, in your search processor, you must escape any special characters from the search query before passing it onto the database, you can do this using mysql_real_escape_string();
so;
$search_query = mysql_real_escape_string($_POST['search']);
It is then safe to use $search_query in your mysql query.
SQL injections - it's bad.
someone can run any query he wants in your database, find passwords, delete your entire data etc.
you can avoid it by wrapping all user input in your queries with mysql_real_escape_string
about the directories - it really depends on the accesses you provide. if file listing is available, it doesn't really mean that someone can make changes/execute them
Ad SQL Injection:
Displaying the entire content can be a problem if you have unpublished articles or articles only available for registered users etc.
Try reading more on SQL Injections. It may be possible to execute a second query that inserts new data in your database - or worse changes data (for example passwords). There's a lot of reading material out there, a start could be: http://php.net/manual/en/security.database.sql-injection.php Sanitise all your input and remember: even if you may not find a way to do harm via a security hole it doesn't mean no one will find a way ;)
Ad the folders: you mean that any user can see the content of the folders? If so, users may see pictures they shouldn't see. If you had a good reason for protecting (no file listing?) the main directory, why not apply it to the temps/ and thumbs/ subdirectories?