数据库概论.陈立军.04.SQL 安全性

在线 SQL

  • http://sqlfiddle.com/
  • MySQL 5.6

SQL 安全性

  • 数据库的安全性是很重要的

主体

  • 主体(principal)
    • 是可以授予权限以访问特定数据库对象的对象,包括登录用户角色应用程序

SQL Server 下三个级别的主体

Windows 级别的主体

  • Windows 域用户帐号/组、本地用户帐号/组,基于 Windows 身份验证
  • 创建Windows登录名
1
create login login_name from windows
1
create login [ljchen-PC\SQLUser] from windows
  • 删除Windows登录名
1
drop login login_name
  • 拒绝和允许 Windows 用户访问 SQL Server
1
2
deny connect SQL to login_name
grant connect SQL to login_name
  • 查看Windows登录名
1
sys.server_principals
1
2
3
select name,type,sid,principal_id
from sys.server_principals
where type_desc='WINDOWS_LOGIN'

SQL Server 级别的主体

  • SQL Server 级别的登录名和固定服务器角色

  • 创建 SQL Server 登录名

1
create login login_name
1
2
3
create login sweetHeart
with password='123456'
default_database='demoDB'
  • 查看 SQL Server 登录名
1
2
3
select name,type,sid,principal_id
from sys.server_principals
where type_desc='SQL_LOGIN'

数据库级别的主体

  • 数据库用户、数据库角色、应用程序角色

  • 创建 SQL Server 数据库用户

1
create user user_name
1
2
3
create user Carefully
for login [ljchen-PC\SQLUser]
with default_schema=Finance
  • 删除数据库用户
1
drop user
  • 报告数据库用户信息
1
sp_helpuser

角色

  • 角色是一组相关权限的集合,即将多个不同的权限集合在一起就形成了角色
  • 如果直接把权限分给用户,权限授予关系非常繁琐
  • 通常数据库上的权限是和职位(角色)对应的

  • 查看 SQL Server 固定服务器角色
1
2
3
select name
from sys.server_principals
where type_desc='SERVER_ROLE'
  • 添加登录名到固定服务器角色
1
sp_addsrvrolemember
1
sp_addsrvrolemember 'sweetHeart', 'sysadmin'
  • 从固定服务器角色删除登录名
1
sp_dropsrvrolemember
  • 添加用户名到数据库角色
1
sp_addrolemember
1
exec sp_addrolemember 'db_datawriter', 'Carefully'
  • 从数据库角色删除用户名
1
sp_droprolemember
  • 查看 SQL Server 固定数据库角色
1
sp_helpdbfixedrole
  • 查看角色成员
1
sp_helprolemember

客体

  • 客体
    • 安全对象(securable)
    • 主体所操纵的对象
  • 服务器范围:登录名、数据库和端点
  • 数据库范围:数据库用户、角色、架构
  • 架构范围:各种对象,如表、视图、函数、存储过程等

权限

  • 权限(permission)
    • 允许主体在安全对象上执行操作
  • 权限的转授和回收
    • 允许用户把已获得的权限转授给其他用户,或者把已授给其他用户的权限再回收上来

权限图

  • 结点是用户,根结点是 DBA
  • 有向边 \(U_i\to\;U_j\),表示用户 \(U_i\) 把某权限授给用户 \(U_j\)
  • 一个用户拥有权限的充分必要条件是在权限图中有一条从根结点到该用户结点的路径
  • 回收某个结点权限的时候,需要把这个结点转授的权限收回
    • 上面一行
      • 回收 U1 的时候,需要回收 U4 的权限
    • 下面一行
      • 只回收 U2,结果是第二张小图
      • 回收 U2、U3,需要把 U2、U3 之间的权限都回收

报告可用权限

1
sys.fn_builtin_permissions
1
2
3
4
5
6
select class_desc,
permission_name,
covering_permission_name,
parent_class_desc,
parent_covering_permission_name
from sys.fn_builtin_permissions('object')

授权命令

1
2
3
4
grant 权限
on 对象名
to {用户[,用户]...|public}
[with grant option]
  • with grant option:获得权限的用户可以把权限再授予其它用户
  • 表级权限
    • select, update, insert, delete, index, alter, drop, resource 等以及它们的总和 all
  • 为什么需要 references 权限
    • 是否允许其他用户定义外码来参照这个表?
    • 可能出现泄密的可能

回收权限

1
2
3
revoke 权限
on 对象
from {用户[,用户]...|public}
  • 授权路径的起点一定是 DBA
  • 收回权限时,若该用户已将权限转授给其它用户,则也一并收回
1
2
3
4
5
6
7
8
9
10
/* 授予权限 */
grant select, insert
on S
to Liming
with grant option

/* 回收权限 */
revoke insert
on S
from Liming

当前用户

1
2
3
declare @usrchar(30)
set @usr=user
select 'The current user is: ' + @usr
  • 实现精细存取控制
    • 普通员工只能查看自己的记录
    • 部门经理可以查看他所管理的员工
    • 人力资源代表可以查看所有员工
  • 不同的用户执行相同的命令,可能返回的结果是不一样的
1
2
3
select *
from S
where SNAME = user

审计

  • 审计就是对指定用户在数据库中的操作情况进行监控和记录,用以审查用户的相关活动
    • 数据被非授权用户删除,用户越权管理,权限管理不正确,用户获得不应有的系统权限等
  • 审计就是监视和收集关于指定数据库获得的数据
    • 哪些表经常被修改,用户共执行了多少次 I/O 操作等,为优化提供依据

SQL Server

  • 服务器审核
1
create server audit MyServerAuditto file ...
  • 服务器审核规范
1
2
3
4
create server audit specification MyServerAuditSpe
for server audit MyServerAudit
alter server audit specification MyServerAuditSpe
add (SERVER_PRINCIPAL_CHANGE_GROUP)
  • 数据库审核规范
1
2
3
4
create database audit specification MyDBAudit
for server audit MyServerAudit
alter database audit specification MyDBAudit
add (SELECTONS)
  • 查看审核历史
1
2
select event_time, succeeded, statement
from sys.fn_get_audit_file(…)

加密

短语加密

1
encryptByPassPhrase({ 'passphrase', 'cleartext'})
1
select encryptByPassPhrase('hello','whoami')

还原数据

1
decryptByPassPhrase( { 'passphrase', 'ciphertext' })
1
2
select decryptByPassPhrase('hello',
0x0100000021D68E2E078E3EA6752239788B69D8B9BF1AD542A7C9774C9CAF66304F215F49)

非对称密钥加密

1
create asymmetric key myAsym_key
1
2
insert into emp(ename, salary)
values('tom', EncryptByAsymkey(Asymkey_ID('myAsym_key'),100000000))
1
2
3
4
5
select DecryptByAsymkey(
Asymkey_ID('myAsym_key'), salary
)
from emp
where name='tom'

对称密钥加密

1
create symmetric key mySym_key
1
2
insert into emp(ename,salary)
values('tom', EncryptBykey(Key_GUID('mySym_key'),100000000))
1
2
3
4
select DecryptByKey(
Key_GUID('mySym_key'),salary)
from emp
where name='tom'

SQL 注入

一个例子

  • 认证过程发出的查询语句
1
2
3
SELECT * FROM users
WHERE username='jake'
and PASSWORD='jakespasswd'
  • 攻击者篡改这个SQL语句
    • 这样的话始终为真
1
2
3
SELECT * FROM users
WHERE username='jake'
and(PASSWORD='jakespasswd' or 'x'='x')
  • 现在这种情况比较少,数据库会先对用户的输入进行一个检查

基于视图的安全性控制

  • 授权 Tom 只有察看职工平均工资的权限
  • 定义一个视图,仅授予用户这个权限
1
2
3
4
5
create view avg_sal
as (
select avg(sal)
from PROF
)
1
grant SELECT on avg_sal to 'Tom'

资源控制:Oracle

  • PROFILE

统计数据库安全

  • 要求:用户只能查询数据的聚集值,不能访问个体

漏洞

  • 漏洞一:个体太少
    • 查询选修 ”古典哲学史“ 的学生的平均成绩(假设只有一个人选)
    • 解决方案:可以做一个限制,如果返回记录数小于设定值 k 条,则不返回结果
  • 漏洞二:多次查询,太多交叠
    • Q1:查询 n 个学生的总成绩为 x
    • Q2:查询 n 个学生+A 的总成绩为 y
    • A 的总成绩为 y-x
    • 解决方案:两个查询的交不能多于m

解决方案

  • 查询引用的数据不能少于 n
  • 两个查询的交不能多于 m
  • 推出个体信息至少需要 \(1+\dfrac{n-2}{m}\) 次查询

例子

  • Student (ID, GPA),ID从1 到 50
  • 任何查询结果只能是一个聚集值
  • 每次至少使用 4 条元组
  • 任何两个查询的交不能大于 2 条元组
  • 给出一个查询集合,使得能确定 ID=9 的 GPA
1
2
3
4
5
6
/* 我的一个解答 */
1 2 3 9;
4 5 6 9;
1 2 4 5;
1 3 4 6;
2 3 5 6;

隐私保护

数据发布

  • 数据脱敏处理
    • 例如把个体姓名抹去

  • 还是可能会出现数据泄露的问题

连接推理

  • [Swe00] 的研究表明,87%的美国人口信息可以通过性别、出生日期、5位邮政编码进行个人重建

k-anonymity

  • k 匿名
  • 有相同的准标识属性组(QI)的元组至少有 k 个(2-anonymous)