SQL笔记

一、sql注入

 SQL注入可以使攻击者绕过认证机制,控制远程服务器上的数据库。 

      (注:SQL是结构化查询语言的简称,它是访问数据库的标准)

原理:SQL数据库来存放应用程序的数据。几乎所有的Web应用在后台 都使用某种SQL数据库。跟大多数语言一样,SQL语法允许数据库命令和用户数据混杂在一起的。如果开发人员不细心的话,用户数据就有可能被解释成命令, 这样的话,远程用户就不仅能向Web应用输入数据,而且还可以在数据库上执行任意命令了。

     SQL注入式攻击的主要形式有两种。一是直接将代码插入到与SQL命令串联在一起并使得其以执行的用户输入变量,由于其直接与SQL语句捆绑,故也被称为直接注入式攻击法。二是一种间接的攻击方法,它将恶意代码注入要在表中存储或者作为原数据存储的字符串。在存储的字符串中会连接到一个动态的SQL命令中,以执行一些恶意的SQL代码。注入过程的工作方式是提前终止文本字符串,然后追加一个新的命令。如以直接注入式攻击为例。就是在用户输入变量的时候,先用一个分号结束当前的语句。然后再插入一个恶意SQL语句即可。由于插入的命令可能在执行前追加其他字符串,因此攻击者常常用注释标记“—”来终止注入的字符串。执行时,系统会认为此后语句位注释,故后续的文本将被忽略,不背编译与执行。

二、.SQL注入漏洞有哪些分类?

1、按照参数类型可分为两种:数字型和字符型。

当发生注入点的参数为整数时,比如 ID,num等,这种形式的就属于数字型注入。当注入点是字符串时,则称为字符型注入,字符型注入需要引号来闭合。

2、根据数据库返回的结果,分为回显注入、报错注入、盲注。

回显注入:可以直接在存在注入点的当前页面中获取返回结果。

报错注入:程序将数据库的返回错误信息直接显示在页面中,虽然没有返回数据库的查询结果,但可以构造一些报错语句从错误信息中获取想要的结果。

盲注:程序后端屏蔽了数据库的错误信息,没有直接显示结果也没有报错信息,只能通过数据库的逻辑和延时函数来判断注入的结果。

3、按照注入位置及方式不同分为:post注入,get注入,cookie注入,盲注,延时注入,搜索注入,base64注入。

三、mysql基础

SQL的分类:

1、DDL—数据定义语言(Data Define Language):create(创建),alter(修改),drop(删除),TRUNCATE(截断),RENAME(重命名);
2、DML—数据操纵语言(Data Manipulation Language):select(查询),delete(删除),update(更新),insert(新增);
3、DCL—数据控制语言(Data Control Language):grant(添加权限),revoke(回收权限);

DDL操作:
注意:使用DDL语言时,必须在动词后跟上数据库对象名词(例如:TABLE、VIEW、INDEX、SCHEMA、TRIGGER等)。
数据库的链接 # mysql -h 127.0.0.1 -u root -p

常用的参数解释:

-A 不预读数据库信息,提高连接和切换数据库速度
--default-character-set  使用的默认字符集
-e 执行命令并退出
-h 主机地址
-p 连接到服务器时使用的密码
-P 连接的端口号

创建数据库:create database test1 ;

查看数据库:show databases;

选择数据库:use mysql;

删除数据库:drop database test1;

创建表:

CREATE [TEMPORARY] TABLE [IF NOT EXISTS] [database_name.] <table_name>

(
  <column_name>  <data_type>  [[not] null],…
)

注:TEMPORARY:指明创建临时表
  IF NOT EXISTS:如果要创建的表已经存在,强制不显示错误消息
  database_name:数据库名
  table_name:表名
  column_name:列名
  data_type:数据类型

  
查看定义:desc emp;

查看创建的表:show create table emp ;

更新表名:alter table emp rename users;

删除表:drop table emp;

修改表字段:alter table emp modify ename varchar(30);

增加表字段:alter table emp add column age int(3);

修改表字段:alter table emp change age age int(4);

删除表字段:alter table emp drop column age;

change和modify:前者可以修改列名称,后者不能change需要些两次列名称.

字段增加修改 add/change/modify/ 添加顺序:

1 add 增加在表尾.
2 change/modify 不该表字段位置.
3 修改字段可以带上以下参数进行位置调整(frist/after column_name);

alter table emp change age age int(2) after ename;
alter table emp change age age int(3) first;

 

DML语句:
插入记录:

//指定字段,
//自增,默认值等字段可以不用列出来,没有默认值的为自动设置为NULL
insert into emp (ename,hiredate,sal,deptno) values ('jack','2000-01-01','2000',1);

//可以不指定字段,但要一一对应
insert into emp values ('lisa','2010-01-01','8000',2);

批量记录:

insert into emp values ('jack chen','2011-01-01','18000',2),('andy lao','2013-01-01','18000',2);

更新记录:

update emp set sal="7000.00" where ename="jack";

update emp e,dept d set e.sal="10000",d.deptname=e.ename where e.deptno=d.deptno and e.ename="lisa";

删除记录:

//请仔细检查where条件,慎重
delete from emp where ename='jack';

查看记录:

//查看所有字段
select * from emp;

//查询不重复记录
select distinct(deptno) from emp ;
select distinct(deptno),emp.* from emp ;

//条件查询
//比较运算符: > < >= <= <> != ...
//逻辑运算符: and or ...
select * from emp where sal="18000" and deptno=2;

排序

//desc降序,asc 升序(默认)
select * from emp order by deptno ;
select * from emp order by deptno asc;
select * from emp order by deptno desc,sal desc;

限制记录数:

select * from emp limit 1;
select * from emp limit 100,10;
select * from emp order by deptno desc,sal desc limit 1;

聚合:函数:count():记录数 / sum(总和); / max():最大值 / min():最小值

select count(id) from emp ;
select sum(sal) from emp ;
select max(sal) from emp ;
select min(sal) from emp ;

group by分组:

//分组统计
select count(deptno) as count from emp group by deptno;
select count(deptno) as count,deptno from emp group by deptno;
select count(deptno) as count,deptno,emp.* from emp group by deptno;

having 对分组结果二次过滤:

select count(deptno) as count,deptno from emp group by deptno having count > 2;

with rollup 对分组结果二次汇总:

select count(sal),emp.*  from emp group by sal, deptno with rollup ;

表连接:

  • left join :左连接,返回左表中所有的记录以及右表中连接字段相等的记录;
  • right join :右连接,返回右表中所有的记录以及左表中连接字段相等的记录;
  • inner join: 内连接,又叫等值连接,只返回两个表中连接字段相等的行;
  • full join:外连接,返回两个表中的行:left join + right join;
  • cross join:结果是笛卡尔积,就是第一个表的行数乘以第二个表的行数。

内连接:只返回两个表中连接字段相等的行

select * from emp as e,dept as d where e.deptno=d.deptno;
select * from emp as e inner join dept as d on e.deptno=d.deptno;

左外连接:包含左表中所有的记录以及右表中连接字段相等的记录

select * from emp as e left join dept as d on e.deptno=d.deptno;

右外连接:包含右表中所有的记录以及左表中连接字段相等的记录

select * from emp as e right join dept as d on e.deptno=d.deptno;

子查询:

//=, !=
select * from emp where deptno = (select deptno from dept where deptname="技术部");
select * from emp where deptno != (select deptno from dept where deptname="技术部");

//in, not in 
//当需要使用里面的结果集的时候必须用in(); 
select * from emp where deptno in (select deptno from dept where deptname="技术部");
select * from emp where deptno not in (select deptno from dept where deptname="技术部");

//exists , not exists
//当需要判断后面的查询结果是否存在时使用exists();
select * from emp where exists (select deptno from dept where deptno > 5);
select * from emp where not exists (select deptno from dept where deptno > 5);

记录联合:

union:返回去重之后的结果
select ename from emp union select ename from emp;

union all:返回所有结果
select ename from emp union all select ename from emp;

DCL语句:
添加权限:

grant select,insert on test.* to 'db_user_1'@'localhost'  identified by '123456';
flush privileges;

回收权限:

revoke insert on test.* from 'db_user_1'@'localhost';
四、sql注入都存在于哪些地方

1、登入口(很可能存在万能密码)

2、网站调取页面信息时(URL:http://www.qdcn.com/?id=1)

3、个人信息页面

五、SQLmap的常见命令

--common-tables 暴力猜表名
-u #注入点
-f #指纹判别数据库类型
-b #获取数据库版本信息
-D “” #指定数据库名
-T “” #指定表名
-C “” #指定字段
–columns #列出字段
–current-user #获取当前用户名称
–current-db #获取当前数据库名称
–users #列数据库所有用户
–passwords #数据库用户所有密码
–privileges #查看用户权限
-U #指定数据库用户
–dbs #列出所有数据库
–tables -D “” #列出指定数据库中的表
–columns -T “user” -D “mysql” #列出mysql数据库中的user表的所有字段
–dump-all #列出所有数据库所有表
–exclude-sysdbs #只列出用户自己新建的数据库和表
–dbms #指定数据库(MySQL,Oracle,PostgreSQL,Microsoft SQL Server,Microsoft Access,SQLite,Firebird,Sybase,SAP MaxDB)
–os #指定系统(Linux,Windows)
-v #详细的等级(0-6)
0:只显示Python的回溯,错误和关键消息。
1:显示信息和警告消息。
2:显示调试消息。
3:有效载荷注入。
4:显示HTTP请求。
5:显示HTTP响应头。
6:显示HTTP响应页面的内容
–privileges #查看权限
–is-dba #是否是数据库管理员
–roles #枚举数据库用户角色
–union-check #是否支持union 注入
–union-cols #union 查询表记录
–union-test #union 语句测试
–union-use #采用union 注入
–method “POST” –data “” #POST方式提交数据(–method “POST” –data “page=1&id=2″)
–cookie “用;号分开” #cookie注入(–cookies=”PHPSESSID=mvijocbglq6pi463rlgk1e4v52; security=low”)
–referer “” #使用referer欺骗(–referer “http://www.baidu.com”)
–user-agent “” #自定义user-agent
–proxy “″ #代理注入
–string “” #指定关键词
–file-read #读取指定文件
–eta #盲注

六、联合查询相关语句

 

union 联合查询注入是一种常用的 SQL 注入方式。

 

使用 union 联合查询注入查询出结果。

 

  1. 必须保证有数据的显示位。
  2. 并且 union 后连接的查询的字段数一致,列的数据类型转换没有问题。

 

  • SQL UNION 操作符

 

UNION 操作符用于合并两个或多个 SELECT 语句的结果集。

 

请注意,UNION 内部的 SELECT 语句必须拥有相同数量的列。列也必须拥有相似的数据类型。同时,每条 SELECT 语句中的列的顺序必须相同。

 

  • SQL UNION 语法

 

SELECT column_name(s) FROM table_name1
UNION
SELECT column_name(s) FROM table_name2

 

注释:默认地,UNION 操作符选取不同的值。如果允许重复的值,请使用 UNION ALL。

 

  • SQL UNION ALL 语法

 

SELECT column_name(s) FROM table_name1
UNION ALL
SELECT column_name(s) FROM table_name2

 

另外,UNION 结果集中的列名总是等于 UNION 中第一个 SELECT 语句中的列名。

 

  • MYSQL union 注入流程

 

Tips:善用 order by 子句 确定列数,通过 order by n 猜出的列数超过数据库表中的列数时,会报错并且不能返回数据。

 

  1. order by 确认列数。
  2. 观察页面回显,选择合适的字段位置进行下一步注入。
  3. 查基本信息 (database () 数据库名、version () 数据库版本、user () 用户名)
  4. 查库
  5. 查表
  6. 查字段
  7. 查数据

七、如何判断整形和字符型注入

 

1、数字型注入

 

当输入的参数为整形时,如果存在注入漏洞,可以认为是数字型注入。

 

测试步骤:

 

(1) 加单引号,URL:www.text.com/text.php?id=3

 

对应的sql:select * from table where id=3’ 这时sql语句出错,程序无法正常从数据库中查询出数据,就会抛出异常;

 

(2) 加and 1=1 ,URL:www.text.com/text.php?id=3 and 1=1

 

对应的sql:select * from table where id=3’ and 1=1 语句执行正常,与原始页面如任何差异;

 

(3) 加and 1=2,URL:www.text.com/text.php?id=3 and 1=2

 

对应的sql:select * from table where id=3 and 1=2 语句可以正常执行,但是无法查询出结果,所以返回数据与原始网页存在差异

 

如果满足以上三点,则可以判断该URL存在数字型注入。

 

2、字符型注入

 

当输入的参数为字符串时,称为字符型。字符型和数字型最大的一个区别在于,数字型不需要单引号来闭合,而字符串一般需要通过单引号来闭合的。

 

例如数字型语句:select * from table where id =3

 

则字符型如下:select * from table where name=’admin’

 

因此,在构造payload时通过闭合单引号可以成功执行语句:

 

测试步骤:

 

(1) 加单引号:select * from table where name=’admin’’

 

由于加单引号后变成三个单引号,则无法执行,程序会报错;

 

(2) 加 ’and 1=1 此时sql 语句为:select * from table where name=’admin’ and 1=1’ ,也无法进行注入,还需要通过注释符号将其绕过;

 

Mysql 有三种常用注释符:

 

-- 注意,这种注释符后边有一个空格

 

# 通过#进行注释

 

/* */ 注释掉符号内的内容

 

因此,构造语句为:select * from table where name =’admin’ and 1=1—’ 可成功执行返回结果正确;

 

(3) 加and 1=2— 此时sql语句为:select * from table where name=’admin’ and 1=2 –’则会报错

 

如果满足以上三点,可以判断该url为字符型注入。

 

八、sql注入之一万能密码的原理

 

用户进行用户名和密码验证时,网站需要查询数据库。查询数据库就是执行SQL语句。
用户登录时,后台执行的数据库查询操作(SQL语句)是:
【Select user_id,user_type,email From users Where user_id=’用户名’ And password=’密码’】。
2.由于网站后台在进行数据库查询的时候没有对单引号进行过滤,当输入用户名【admin】和万能密码【2’or’1】时,执行的SQL语句为:
【Select user_id,user_type,email From users Where user_id=’admin’ And password=’2’or’1’】。
3.由于SQL语句中逻辑运算符具有优先级,【=】优先于【and】,【and】优先于【or】,且适用传递性。因此,此SQL语句在后台解析时,分成两句:
【Select user_id,user_type,email From users Where user_id=’admin’ And password=’2’】和【’1’】,两句bool值进行逻辑or运算,恒为TRUE。
SQL语句的查询结果为TRUE,就意味着认证成功,也可以登录到系统中。

 

输入用户名【admin】,密码【2’or’1】,即可登录成功。

 

上一篇:ORACLE ListAgg() WITHIN GROUP () 行转列函数的使用


下一篇:【第二阶段 day04】索引 视图