SQL注入攻击及防御01
实验简介
在owasp年度top10安全问题中,注入高居榜首。SQL注入攻击指的是通过构建特殊的输入作为参数传入web应用程序,而这些输入大都是SQL语法里的一些组合,通过执行SQL语句进而执行攻击者所要的操作,其主要原因是程序没有细致地过滤用户输入的数据,致使非法数据侵入系统。
1.对于Web应用程序而言,用户核心数据存储在数据库中,例如MySQL、SQL Server、Oracle;
2.通过SQL注入攻击,可以获取、修改、删除数据库信息,并且可以通过提权来控制web服务器等其他操作;
3.SQL注入即攻击者通过构造特殊的SQL语句,入侵目标系统,致使后台数据库泄露的过程;
4.因为SQL注入漏洞造成的严重危害性,所以常年稳居 OWASP TOP10的榜首!
SQL语句是不可能修改的,只能对输入想方法。
SQL注入危害
1.拖库导致用户数据泄露;
2.危害web等应用的安全;
3.失去操作系统的控制权;
4.用户信息被非法买卖;
5.危害企业及国家的安全!
SQL基础回顾
常见的数据库对象:
- 表(table,数据实际存储在磁盘上,占用磁盘空间):基本的数据存储集合,由行和列组成。
- 视图(view,虚表,数据部存储在磁盘上,不占用磁盘空间):从表中抽出的逻辑上相关的数据集合。
- 序列(sequence):提供有规律的数值,主要用于提供主键值。
- 索引(inddex,实际存储子啊磁盘上,占用磁盘空间):适当的创建索引可提高对数据的查询效率。
- 同义词(synonym):给对象起别名,简化缩写。
- 约束:增强数据的完整性;完整性约束是一种规则,存储在数据字典中,不占用任何数据库空间。
- 过程和函数:区别为调用方式不同。过程和函数都以编译后的形式存放在数据库中,每个函数的参数个数>=0,返回值为1个。过程的参数个数>=0,没有返回值。
- 包:将过程、函数和数据结构捆绑在一起的容器,分别为两部分:
–包规范:函数头、过程头、外部可视数据结构;
–包主体:所有被捆绑的过程和函数的声明、执行、异常处理部分 - 触发器(triggers):触发器是一种自动执行响应数据库变化的程序。可以设置为在触发器事件之前或之后触发或执行。
- 数据字典:由Oracle Server自动创建的一组表且包含数据库信息。
登录OWASP
项目环境:OWASP
表1 : dvwa.users
表2 : wordpress.wp_users
表3 : mysql.user
mysql -uroot -powaspbwa #登录数据库
查看数据库
mysql>show databases;
#显示当前所在库
mysql>select database();
#显示当前用户
mysql>select user();
#显示当前时间
mysql>select now();
#进入指定数据库
mysql>use dvwa;
mysql>select database();
查看数据库中的表
#查看当前数据库中的表
mysql>show tables;
#查看表的结构,大写命令才会被自动补全
mysql>DECSCRIBE users;
#创建表
mysql>create table users;
#查看表的详细属性
mysql>show create table users;
# 查看表的详细属性时加一个‘\G’可以看的舒服一点
mysql>show create table users\G
查看表的记录
区分一下语句!!!!自要记得查资料
DDL语句(操纵数据库):create、drop、alter、truncate
DML语句(操纵数据):insert、update、delete、select
DCL语句(控制权限):grant、revoke
DQL语句(查询语言):query、select
DDL(Data Definition Language)数据库模式定义语言
参考网址
数据定义语言,这些语句定义了不同的数据段,数据库,表,列,索引等数据库对象。
- create关键字:只能在数据库下创建表
use 数据库名; //使用某个指定的数据库
create table 表名称(字段1 类型,字段2 类型); //在一个数据库中创建一个表
create table hero_table ( id int,name varchar(10)); //创建表
//创建表并增加约束
CREATE TABLE 表名称 (
字段1 类型1 约束1 约束1,
字段2 类型2 约束2 约束2
);
//创建表并增加约束
CREATE TABLE hero_table4 (
id INT(11) NOT NULL PRIMARY KEY,
NAME VARCHAR(10) NOT NULL UNIQUE KEY
)
//只复制表结构及约束,但不复制数据
CREATE TABLE 复制出的表 LIKE 原表
//复制表结构及数据,但不复制约束
CREATE TABLE 复制出的表 AS SELECT * FROM 原表
- alter关键字
//添加字段
ALTER TABLE 表名称 ADD 字段名 字段约束
ALTER TABLE 表名称 ADD COLUMN 字段名 字段约束
//添加索引
ALTER TABLE 表名称 ADD INDEX 索引名称 (字段名)
//添加主键
ALTER TABLE 表名称 ADD PRIMARY KEY (字段名)
ALTER TABLE 表名称 ADD UNIQUE KEY (字段名)
//添加外键约束
ALTER TABLE 需要添加外键表名称 ADD FOREIGN KEY 外键名(设为外键的字段) REFERENCES 被添加外键表名称(设为被添加外键的字段)
//修改字段类型
ALTER TABLE 表名称 CHANGE COLUMN NAME 修改字段 修改为字段类型
ALTER TABLE 表名称 MODIFY COLUMN 修改字段 修改为字段类型
//修改与删除表中default
ALTER TABLE 表名称 ALTER COLUMN 字段名 SET DEFAULT '修改的值' #设置default
ALTER TABLE 表名称 ALTER COLUMN 字段名 DROP DEFAULT #删除default
//禁用和启用约束
ALTER TABLE 表名称 DISABLE KEYS #禁用约束
ALTER TABLE 表名称 ENABLE KEYS #启用约束
//删除表字段
ALTER TABLE 表名称 DROP COLUMN 字段名
//删除主键
ALTER TABLE 表名称 DROP PRIMARY KEY
//删除索引
ALTER TABLE 表名称 DROP INDEX 索引的字段名
//删除外键约束
ALTER TABLE 表名称 DROP FOREIGN KEY 外键的字段名
//修改表名
ALTER TABLE 修改前表名称 RENAME 修改后表名称
- drop关键字
DROP DATABASE 数据库名 #删除数据库
DROP TABLE 表名称 #删除表
- truncate关键字
与drop区别:truncate只删除数据不删除表的结构(定义),释放空间
truncate table 表名称; #清空表的内容
DML(Data Manipulation Language)数据操纵语言
参考网址1
参考网址2
数据操纵语句,用于添加,删除,更新和查询数据库记录,并检查数据完整性。
- insert关键字
INSERT [INTO] tbl_name(col1,col2,col3) values(var1,var2,var3)
- delete关键字
DELETE [LOW_PRIORITY] [QUICK] [IGNORE] FROM tbl_name
[PARTITION (partition_name [, partition_name] ...)]
[WHERE where_condition]
[ORDER BY ...]
[LIMIT row_count]
- update关键字
UPDATE [LOW_PRIORITY] [IGNORE] table_reference
SET assignment_list
[WHERE where_condition]
[ORDER BY ...]
[LIMIT row_count]
- select关键字
SELECT
[ALL | DISTINCT | DISTINCTROW ]
[HIGH_PRIORITY]
[STRAIGHT_JOIN]
[SQL_SMALL_RESULT] [SQL_BIG_RESULT] [SQL_BUFFER_RESULT]
[SQL_CACHE | SQL_NO_CACHE] [SQL_CALC_FOUND_ROWS]
select_expr [, select_expr ...]
[FROM table_references
[PARTITION partition_list]
[WHERE where_condition]
[GROUP BY {col_name | expr | position}
[ASC | DESC], ... [WITH ROLLUP]]
[HAVING where_condition]
[ORDER BY {col_name | expr | position}
[ASC | DESC], ...]
[LIMIT {[offset,] row_count | row_count OFFSET offset}]
[PROCEDURE procedure_name(argument_list)]
[INTO OUTFILE 'file_name'
[CHARACTER SET charset_name]
export_options
| INTO DUMPFILE 'file_name'
| INTO var_name [, var_name]]
[FOR UPDATE | LOCK IN SHARE MODE]]
DCL(Data Control Language)数据控制语言
参考网址
数据控制语句,用于控制不同数据段直接的许可和访问级别的语句。定义了数据库,表,字段,用户的访问权限和安全级别。
- grant关键字
GRANT
priv_type [(column_list)]
[, priv_type [(column_list)]] ...
ON [object_type] priv_level
TO user [auth_option] [, user [auth_option]] ...
[REQUIRE {NONE | tls_option [[AND] tls_option] ...}]
[WITH {GRANT OPTION | resource_option} ...]
GRANT PROXY ON user
TO user [, user] ...
[WITH GRANT OPTION]
object_type: {
TABLE
| FUNCTION
| PROCEDURE
}
priv_level: {
*
| *.*
| db_name.*
| db_name.tbl_name
| tbl_name
| db_name.routine_name
}
user:
(see Section 6.2.4, “Specifying Account Names”)
auth_option: {
IDENTIFIED BY 'auth_string'
| IDENTIFIED WITH auth_plugin
| IDENTIFIED WITH auth_plugin BY 'auth_string'
| IDENTIFIED WITH auth_plugin AS 'auth_string'
| IDENTIFIED BY PASSWORD 'auth_string'
}
tls_option: {
SSL
| X509
| CIPHER 'cipher'
| ISSUER 'issuer'
| SUBJECT 'subject'
}
resource_option: {
| MAX_QUERIES_PER_HOUR count
| MAX_UPDATES_PER_HOUR count
| MAX_CONNECTIONS_PER_HOUR count
| MAX_USER_CONNECTIONS count
}
- revoke关键字
REVOKE
priv_type [(column_list)]
[, priv_type [(column_list)]] ...
ON [object_type] priv_level
FROM user [, user] ...
REVOKE ALL [PRIVILEGES], GRANT OPTION
FROM user [, user] ...
REVOKE PROXY ON user
FROM user [, user] ...
DQL(Data Query Language)数据查询语言
参考网址1
参考网址2
数据库查询语句,用于查询。
#查看表中内容
mysql>select * from users;
#查看表中的内容,在语句后面加‘\G’,使其直观显示
mysql>select * from users\G
#查看表中的指定字段,前提是知道表的结构
mysql>desc users;
mysql>select user_id,password avatar from users; #字段要用逗号隔开,如果不隔开自动认为一个字段,空格后是显示的别名
mysql>select user_id,password,avatar from users;
简单查询示例
当前库dvwa dvwa.users
mysql> select * from users;
mysql> select user_id,first_name,last_name from users;
其他库mysql.user
mysql> desc mysql.user
mysql> select * from myssql.user;
mysql> select user,password,host from mysql.user;
其他库 wordpress.user
mysql> desc wordpress.wp_user;
mysql> select * from wordpress.wp_users;
mysql> select user_login,user_pass from wordpress.wp_users;
//条件查询示例
mysql> select user,password,host from mysql.user where user='root';
mysql> select user,password,host from mysql.user where user='root' and host='localhost';
mysql> select user,password,host from mysql.user where user='root' or host='localhost';
mysql> desc dvwa.users;
mysql> select user_id,first_name,last_name from dvwa.users where first_name='yangge';
mysql> select user_id,first_name,last_name from dvwa.users where first_name='yangge' or 1=1;
mysql> select user_id,first_name,last_name from dvwa.users where first_name='admin' and 1=2;
mysql> mysql> select user_id,first_name,last_name from dvwa.users where user_id=2;
mysql> mysql> select user_id,first_name,last_name from dvwa.users where user_id=7;
mysql> mysql> select user_id,first_name,last_name from dvwa.users where user_id=7 or 1=1;
//联合查询
mysql> select user,password from mysql.user;
mysql> select user_login,user_pass from wordpress.wp_users;
mysql> select user,password from mysql.user union select user_login,user_pass from wordpress.wp_users;
mysql> select user,password,host from mysql.user union select user_login,user_pass from wordpress.wp_users;
ERROR 1222(21000):the used SELECT statements have a different number of columns
注意:union查询前后字段数必须相同
mysql> select user,password,host from mysql.user union select user_login,user_pass,3 from wordpress.wp_users;
1.注意!!!where语句后的条件等号后面不加引号时为字段名,加引号为字段值
mysql> select user,password,host from mysql.user where user=root;
当然,数字除外。(因为纯数字不能作为字段名,所以肯定是字段值)
2.SQL注入的大前提是原来的语句不能动,只能在后面添加(加戏…)
本例中1=1可以换成其他的,‘1’=‘1’,0=0等均可以,只要肯定成立即可。
mysql> select user_id,first_name,last_name from dvwa.users where first_name='yangge' or 1=1;
SQL查询中只能查询开发人员已经定义好的数据库或表的内容。
3.联合查询:在union后再加一个sql语句
SQL语句中后面略掉分号,加‘\c’表示该语句不再执行。
(1)语句前后字段数目应相同,如果不够,可以用数字补充缺少的字段(因为数字虽然不可以用作字段名,但是在查询中使用时不会报错)
(2)不知道前面sql语句的字段数目,要自己去猜。
mysql> select * from dvwa.users union select 1;
mysql> select * from dvwa.users union select 1,2;
mysql> select * from dvwa.users union select 1,2,3;
mysql> select * from dvwa.users union select 1,2,3,4;
mysql> select * from dvwa.users union select 1,2,3,4,5;
mysql> select * from dvwa.users union select 1,2,3,4,5,6;
# 猜对的时候会显示结果,不然会显示error1222(21000)。根据查询的结果进行下面的查询
mysql> select * from dvwa.users union select user_login,user_pass,1,2,3,4,5,6 from wordpress.wp_users;
# 不想要前面的结果,使其不成立即可。
mysql> select * from dvwa.users where 1=2 union select user_login,user_pass,1,2,3,4,5,6 from wordpress.wp_users;
(3)使用limit限制查询结果的数目。
显示的时候以前面SQL语句的字段名为主,但是字段值是我们想要的后面的SQL查询结果
字段值是我们想要的后面的SQL查询结果,前面的只是个幌子,所以不要在意结果中显示的字段名
information_schema
(1)数据库名、表名
information_schema保存整个数据库中所有数据库(库名:TABLE_SCHEMA)、表(表名:TABLE_NAME)的元数据(meta data),即数据库字典。不保存其他内容。
====查询整个数据库库名、表名 information_schema.tables====
mysql> select * from information_schema.TABLES\G #查看information_schema里的所有信息
mysql> select DISTINCT TABLE_SCHEMA from information_schema.TABLES; #等价于 show databases; #DISTINCT:去重
#GROUP_CONCAT:分组 GROUP BY根据库名分组
mysql> select TABLE_SCHEMA,TABLE_NAME from information_schema.TABLES\G #查看所有库名、表名
mysql> select TABLE_SCHEMA,GROUP_CONCAT(TABLE_NAME) from information_schema.TABLES GROUP BY TABLE_SCHEMA\G
mysql> select TABLE_NAME from INFORMATION_SCHEMA.tables where TABLE_SCHEMA='dvwa';#等价于 show tables;
综上所述,不需要去看表名,可以直接从数据库字典information_scema查询
(2)数据库库名、表名、字段名
字段名:COLUMN_NAME
===查询数据库库名、表名、字段名 information_schema.colums ===
mysql> select * from information_schema.columns\G #得到所有表的所有列的信息
mysql> select column_name from INFORMATION_SCHEMA.columns; #获得所有库的所有表的所有列的名字(没有大的意义)
mysql> select column_name from INFORMATION_SCHEMA.columns where table_schema='dvwa' and table_name='users'; #获得某个库的某个表的所有列名
mysql> select column_name from INFORMATION_SCHEMA.columns where table_name='USER_PRIVILEGES' #查询用户权限表
mysql> select column_name from INFORMATION_SCHEMA.columns where table_name='SCHEMA_PRIVILEGES'