How To Build Your Own Tools (reflected XSS scanner)

مقدمة

كشخص متخصص فى مجال ال cybersecurity بتشتغل بشكل يومى على أدوات مختلفة لاتمام مهام متعددة على سبيل المثال فى عملية الاستطلاع وجمع المعلومات ( reconnaissance and information gathering) ممكن تستخدم أداة مثل nmap لاجراء عملية فحص للمنافذ (port scanning), ولاكن فى بعض الاحيان ممكن تحتاج أنك تبنى أدواتك بنفسك أو تحتاج تعدل على ادوات موجودة بالفعل, وعلشان تعرف تنفذ الافكار اللى فى دماغك محتاج أدوات تانية اللى هى لغات البرمجه بالاضافة لمعرفتك وفهمك للمواضيع المتعلقة بالاداة اللى بتفكر تبنيها أو تعدل عليها

فى المقال دا هشرح ازاى تبنى (reflected xss scanner), ولاكن قبل الشرح لازم تكون فاهم يعنى ايه ثغرة ال xss وازاى بتحصل وازاى تختبرها بشكل يدوى, فهمك لكيفية أختبار ثغرة ال xss هنرتبه فى خطوات محددة وبعد كدا هنبدأ نحول الخطوات دى ل code اللى هو هيبقى الاداة بتاعتنا

الشرح

ازاى بنختبر وجود ثغرة xss بشكل يدوى؟

1- يعنى ايه xss؟

ثغرة ال cross site scripting (xss), هى ثغرة من نوع client side يعنى بتشتغل على جانب المستخدم فى المتصفح والثغرة دى بتحصل لما تطبيق الويب بيستقبل المدخلات من المستخدم (user inputs) ويرجعها بدون ما يعمل sanitization بالتالى نقدر نستغل الثغرة من خلال اننا نرسل malicious javascript code ولما تطبيق الويب يرجع البيانات, المتصفح هيشغل ال javascript code

2- خطوات اختبار ثغرة ال xss؟

1- بنجمع كل parameters اللى ممكن تطبيق الويب يستقبل بيانات من خلالها

2- بنبدأ نعملهم filter بحيث اننا نشتغل على ال parameters اللى بيحصل لها reflection

3- بنبدأ نرسل للتطبيق payloads مختلفة ونلاحظ رد التطبيق

4- لو لاحظت ان التطبيق مش بي sanitize ال output بتعرف أن التطبيق مصاب بثغرة ال xss

5- بنتأكد من وجود الثغرة عن طريق أننا بنشغل function معينه زى ()alert ونلاحظ المتصفح الخاص بينا

هنحول الخطوات دى ل pseudo code :

# xss payload
payload = "<script>alert('test xss pyload')</script>"

function scan(url):
    # send http request
    http_response = send_requst(url + payload)
    # check if payload reflected in the response
    if payload in http_response:
        print(url + " - vulnerable")
    else:
        print(url + " - not vulnerable")

ازاى هنحول ال pseudo code الى code حقيقى؟

1- محتاجين لغة برمجة (c, python, go, ...) هنستخدم python

2- محتاج تبقى عارف يعنى ايه HTTP وازى بيشتغل

3- محتاج تبقا فاهم يعنى ايه HTML

المثال رقم 1 (XSS scanner V1)

فى المثال دا هنكتب basic xss scanner عبارة عن script بياخد مجموعة من الurls وبيبدأ يرسل paylaod لكل واحد فيهم ويشوف اذا كان حصل reflection أو لا لو حصل reflection هيقولك أن الurl مصاب

أول خطوة هنعملها وهى أننا نعمل import للمكتبات اللى هنستخدمها

1- sys lib : to pass the command line arguments to our script

2- requests lib: to send HTTP requests to the web app

#!/usr/bin/python3
import sys
import requests

الخطوة الثانية وهى أننا هنكتب ال function اللى هتعمل scan لل urls

ال function بتاخد url ك argument وبترسل HTTP request مع استبدال كلمة xss اللى بتكون فى الparameter value بال payload

بعد كدا بتتأكد لو كان حصل reflection لل payload فى ال response أو لا

def scan(url):
    payload = '"><svg/onload=alert("xss scanner by aufzayed")>'
    
    try:
        # send http request to url
        http_response = requests.get(url.replace('XSS', payload))
        
        # check if payload reflected in http_response
        if payload in req.text:
            print(f'[#] {url} - Vulnerable!')
        else:
            print(f'[!] {url} - Not Vulnerable!')
    except ConnectionError:
        pass

الخطوة الاخيرة وهى أننا ناخد ال urls من خلال ال command line و نبدأ نمررهم واحد واحد للscan function

urls_file_name = sys.argv[1]
with open(urls_file_name, 'r') as urls_list:
    for url in urls_list.readlines():
        scan(url.strip())

خلينا نجرب ال script ونلاحظ النتائج

أول حاجة محتاجينها هى ال urls اللى هنعملها scan ولاكن هنستبدل ال parameters values بكلمة XSS علشان ال Scanner يستبدلها بال payload

هنجهز ال urls الخاصة بينا فى ملف

http://example.com/?param=XSS
http://example.com/search?q=XSS

هنشغل ال scanner على vulnerable web app

خلينا نتأكد من نتائج ال scanner ونلاحظ ايه الفرق بين ال vulnerable path وال not vulnerable path

لاحظ الفرق بين الصورتين: فى الصورة الاولى ال payload حصله reflection بدون أى تعديل, أما فى الصورة التانية ال payload حصلة escaping بالتالى المتصفح هيعرضه زى ما هو بدون ما يشتغل

المثال رقم 2 (XSS scanner v2)

فى المثال الأول ال tool بتاعتنا كانت بتاخد ال urls ولكن كنا بنتحتاج اننا نجهزهم الأول ونبدل ال parameter values بكلمة مميزة اللى هى XSS على سبيل المثال وبعد كدا بيتم استبدالها بال payload ولاكن علشان نعمل حاجة زى كدا بشكل يدوى حتاخد وقت كبير أو هنضطر نتسخدم أداة تانية علشان ننفذ الكلام دا بشكل سريع

فى المثال الثانى هنكتب function جديدة تنفذ العملية دى بحيث انها تاخد ال url زى ما هو وتبدل ال parameter values وترجعه لل scan function, هنحتاج نستخدم مكتبة اضافية اللى هى urllib تحديدا ال parse علشان نعمل parse لل urls

from urllib import parse

def qs_replace(url):
    parse_url = parse.urlparse(url)
    
    _split = [i.split('=') for i in parse_url.query.split('&')]
    
    for i in range(len(_split)):
        _split[i][1] = 'XSS'
    
    _query = '&'.join(['='.join(a) for a in _split])
    
    return parse_url.schema + '://' + parse_url.netloc + parse_url.path + '?' + _query

زى ما واضح فى الصور ال function أخدت ال urls وبدلت parameters values بكلمة XSS ودا سهل علينا عملية الscan بدل ما نستخدم اكثر من أداه وخلى الاداه الخاصة بينا اذكى

المثال رقم 3 (XSS scanner v3)

فى المثال دا هنضيف ميزة جديدة للأداة وهى أنها تبحث بنفسها عن parameters وترسل ال requests سواء كانت (GET) أو (POST)

هنستخدم مكتبه ثانية اسمها BeautifulSoup واللى هنستخدمها فى أننا نعمل parse لل HTML ونبحث عن ال form and input tags ونتسخرج ال attributes الخاصة بيهم زى ال action, method, name

from bs4 import BeautifulSoup

def extract_params(url):
    forms_list = []
    
    http_response = requests.get(url).content
    bsoup = BeautifulSoup(http_response, 'html.parser')
    
    # find all from tag in the html doc
    forms = basoup.find_all('form')
    
    for form in forms:
        form_data = {
            'url': '',
            'path': '',
            'method': '',
            'params': []
        }
        
        form_data['url'] = url
        form_data['path'] = form.attrs.get('action')
        form_data['method'] = form.attrs.get('method').lower()
        for input_tag in form.find_all('input'):
            form_data['params'].append(input_tag.attrs.get('name'))
        forms_list.append(form_data)
        
    return forms_list

ال function الجديدة هتسمحلنا أننا نبعت ال urls بدون parameters وال tool هتستخرجها بنفسها وتبدأ ترسل HTTP requests وتقول اذا كان فى vulnerability او لا

الخاتمة

فى النهاية عملية انشاء أو التعديل على الادوات ببتطلب منك معرفتك بالبرمجة بالاضافة لمعرفتك وفهمك للحاجة اللى عايز تعملها وقدرتك على تحويل الافكار اللى فى دماغك لكود برمجى يساعدك انك تنفذ العملية بشكل أسرع توفيرا للوقت والمجهود, أنا ذكرت 3 أمثلة علشان اوضح ازاى عملية التطور ببتم من script بسيط ل smart script مع كل function جديدة بتتضاف لل tool الخاصة بيك بتبقا أذكى وبتسهل عليك حاجات كتير

Last updated