1 คะแนน โดย GN⁺ 2024-04-03 | 1 ความคิดเห็น | แชร์ทาง WhatsApp
  • การโจมตี xz แบ่งเป็น การฉีดโค้ดเชลล์ในขั้น configure และการฉีดไฟล์อ็อบเจ็กต์ในขั้น make โดยการวิเคราะห์นี้ติดตามกระบวนการที่สคริปต์ใน tarball แจกจ่ายของ xz 5.6.0·5.6.1 สอดแทรกไฟล์อ็อบเจ็กต์แบ็กดอร์เข้าไปในบิลด์
  • โค้ดอันตรายและไฟล์อ็อบเจ็กต์ถูกซ่อนไว้ด้วยการบีบอัดและเข้ารหัสให้ดูเหมือน ไฟล์อินพุตทดสอบแบบไบนารี ใน tests/files และคำอธิบายใน README เดิมที่บอกว่าเป็น “ไฟล์ทดสอบที่ทำด้วยมือ” ก็ช่วยให้การพรางตัวแนบเนียนขึ้น
  • โค้ดที่ถูกเพิ่มใน m4/build-to-host.m4 จะค้นหา bad-3-corrupt_lzma2.xz แล้วกู้คืนด้วย tr และ xz -d ก่อนรันด้วย /bin/sh และใน 5.6.1 ยังมี กลไกขยาย สำหรับค้นหาสคริปต์เพิ่มเติมจากไฟล์ทดสอบใหม่ด้วย
  • สคริปต์ configure จะแก้ src/liblzma/Makefile และ libtool เพื่อให้รันสคริปต์ที่ซ่อนไว้อีกครั้งระหว่าง make พร้อมปรับแฟล็ก -z,now และแฟล็กที่เกี่ยวกับ PIC เพื่อให้ ifunc resolver ถูกเรียกในช่วงลิงก์แบบไดนามิกตอนเริ่มต้น
  • ในขั้น make จะดึงและถอดรหัสอ็อบเจ็กต์อันตรายจาก good-large_compressed.lzma แล้วสลับผลลัพธ์การบิลด์ของ crc64_fast.c และ crc32_fast.c เพื่อให้สามารถดักการเรียก RSA_public_decrypt ผ่าน _get_cpuid ได้

โครงสร้างทั้งหมดของการโจมตี

  • Andres Freund แจ้ง การมีอยู่ของการโจมตี xz ต่อเมลลิงลิสต์ oss-security@openwall เมื่อ 2024-03-29
    • วันก่อนหน้านั้นก็ได้แจ้ง Debian security และลิสต์แบบปิด distros@openwall ด้วย
    • จุดเริ่มต้นคือเขาพบอาการผิดปกติที่เกี่ยวกับ liblzma ระหว่างติดตั้ง Debian sid ได้แก่การใช้ CPU สูงขณะล็อกอิน SSH และข้อผิดพลาดจาก Valgrind
  • การโจมตีประกอบด้วยสองขั้นหลัก
    • มีการฉีดโค้ดเชลล์ระหว่าง configure
    • โค้ดเชลล์นี้จะฉีดโค้ดเชลล์เข้า make อีกครั้ง และเพิ่มไฟล์อ็อบเจ็กต์อันตรายเข้าไปในบิลด์ระหว่าง make
  • หากเก็บไฟล์อ็อบเจ็กต์อันตรายไว้ในรีโพซิทอรีตรง ๆ เช่น evil.o ก็จะน่าสงสัยเกินไป ดังนั้นผู้โจมตีจึงซ่อนโค้ดเชลล์และไฟล์อ็อบเจ็กต์ไว้ใน ไฟล์อินพุตทดสอบแบบไบนารี โดยบีบอัดและเข้ารหัสไว้
  • ไดเรกทอรี tests/files มีอยู่ตั้งแต่ก่อนที่ Jia Tan จะเข้ามา และ README อธิบายว่าเป็นไฟล์สำหรับทดสอบตัวถอดรหัส .xz, .lzma, .lz โดยบางไฟล์สร้างขึ้นเองด้วย hex editor พร้อมอธิบายว่า “ไม่มีซอร์สโค้ดไหนดีกว่าไฟล์นั้นเอง”
  • ผู้โจมตีใช้บริบทนี้ทำให้ดูเหมือนแค่เพิ่มไฟล์ทดสอบใหม่ไม่กี่ไฟล์

จุดรันที่แบ็กดอร์ตั้งเป้าไว้

  • ผลสุดท้ายของสคริปต์คือทำให้ฟังก์ชัน _get_cpuid ในไฟล์อ็อบเจ็กต์อันตรายถูกเรียกเป็นส่วนหนึ่งของ GNU indirect function(ifunc) resolver
  • โดยทั่วไป ifunc resolver อาจถูกเรียกแบบหน่วงระหว่างการรันโปรแกรมได้ แต่ในทางปฏิบัติมักมีการเรียกทั้งหมดตั้งแต่ช่วงต้นของการลิงก์แบบไดนามิกและแมป GOT·PLT เป็นแบบอ่านอย่างเดียวเพื่อเหตุผลด้านความปลอดภัย
  • ifunc resolver อันตรายจึงสามารถทำงานได้ในช่วงเริ่มต้นที่ GOT·PLT ยังเขียนได้อยู่
  • แบ็กดอร์จะค้นหา RSA_public_decrypt ในตารางแล้วแทนที่ด้วยเวอร์ชันของผู้โจมตี
  • ฟังก์ชันที่ถูกแทนที่จะรันโค้ดของผู้โจมตีเมื่อมีการนำเสนอใบรับรอง SSH ที่ถูกต้อง

ขั้น configure: การอำพรางใน build-to-host.m4

  • xz-utils ใช้ GNU autoconf และโดยทั่วไป configure กับไฟล์ m4 สนับสนุนจะถูกรวมมาใน tarball แจกจ่าย ไม่ใช่ในซอร์สรีโพซิทอรี
  • การโจมตีเริ่มจากการเพิ่มไลบรารีช่วยเหลือที่ไม่คาดคิด m4/build-to-host.m4 เข้าไปใน tarball ของ xz 5.6.0 และ xz 5.6.1
  • build-to-host.m4 ที่เป็นอันตรายมีการแก้ไขที่ดูสมเหตุสมผลเมื่อเทียบกับไฟล์มาตรฐาน
    • เพิ่ม serial จาก 3 เป็น 30
    • เปลี่ยนปีลิขสิทธิ์จาก 2023 เป็น 2023-2024
    • เพิ่มการเปลี่ยนแปลง shell·m4 บางส่วนที่สังเกตได้ยาก
  • แกนจริงคือโค้ด grep -aErls "#{4}[[:alnum:]]{5}#{4}$" $srcdir/ ที่ค้นหารูปแบบเฉพาะภายในแพ็กเกจแจกจ่าย
    • ไฟล์ที่ตรงกับแพตเทิร์นนี้คือ ./tests/files/bad-3-corrupt_lzma2.xz
    • ผลลัพธ์คือ gl_am_configmake จะชี้ไปยังไฟล์ทดสอบนี้
  • gl_path_map ถูกตั้งเป็น tr "\t \-_" " \t_\-" เพื่อสลับแท็บ·ช่องว่าง และขีดล่าง·ขีดกลางกันไปมา

การกู้คืนสคริปต์แรกที่ซ่อนไว้

  • gl_[$1]_prefix จะดึงส่วนหลังจุดสุดท้ายของชื่อไฟล์ออกมา จึงได้ค่าเป็น xz
    • ชื่อดูเหมือน prefix แต่จริง ๆ แล้วคือส่วนขยายไฟล์
    • มันจึงกลายเป็นชื่อคำสั่งบีบอัดที่มีแนวโน้มว่าจะติดตั้งอยู่แล้วบนเครื่องบิลด์
  • สตริงคำสั่งที่ถูกสร้างขึ้นหลังจากนั้น แม้ภายนอกจะดูเหมือนใช้ sed "r\n" แต่จริง ๆ แล้วใกล้เคียงกับ cat ที่ถูกทำให้อ่านยาก มากกว่า
    • sed แบบ r\n เป็นคำสั่งให้พยายามอ่านไฟล์ \n ที่ไม่มีอยู่จริง จึงไม่เกิดอะไรขึ้น
    • เพราะไม่มี -n จึงพิมพ์อินพุตออกมาตามเดิม
  • คำสั่งที่ถูกรันจริงมีรูปแบบดังนี้
cat ./tests/files/bad-3-corrupt_lzma2.xz | tr "\t \-_" " \t_\-" | xz -d
  • คำสั่งนี้ถูกประเมินผ่าน AC_CONFIG_COMMANDS ระหว่างการรัน config.status
  • เอาต์พุตที่กู้คืนได้มี ####Hello#### และ ####World#### ปรากฏอยู่ และตาม README แล้ว สตรีมแรกและสตรีมที่สามของ bad-3-corrupt_lzma2.xz เป็น xz stream ที่ถูกต้อง ส่วนสตรีมตรงกลางเท่านั้นที่ข้อมูล LZMA2 เสียหาย

ความต่างระหว่าง 5.6.0 กับ 5.6.1

  • สคริปต์แรกที่กู้คืนได้จาก xz 5.6.0 จะตัดช่วงไบต์เฉพาะออกจาก good-large_compressed.lzma แล้วแปลง ก่อนคลายเป็น raw LZMA stream และส่งต่อให้ /bin/sh
  • สคริปต์แรกของ xz 5.6.1 มีบรรทัดที่พยายามออกจากการทำงานหากไม่ใช่ Linux อยู่ห้าครั้ง
    • [ ! $(uname) = "Linux" ] && exit 0
    • หลังจากนั้นในสคริปต์ยาวที่เป็นเป้าหมายการวิเคราะห์ก็ยังมีบรรทัดตรวจ Linux เฉพาะของ 5.6.1 อยู่ด้วย
    • บรรทัดนั้นมีบั๊กเพราะไม่มีช่องว่างรอบ = จึงทำงานไม่ถูกต้อง
  • 5.6.1 ใช้จำนวนไบต์สุดท้ายของ head, ออฟเซ็ตของ tail, และอาร์กิวเมนต์ tr ต่างจาก 5.6.0
    • ในตัวอย่าง 5.6.1 จะดึง 16×2048+939 = 33,707 ไบต์
    • หลังจากนั้นใช้ 31,233 ไบต์สุดท้ายด้วย tail -c +31233
  • pipeline สำหรับการดึงข้อมูลประกอบด้วยขั้นต่อไปนี้
    • คลาย good-large_compressed.lzma ด้วย xz -dc
    • ดึงช่วงไบต์ที่ต้องการด้วย pipeline ของ head
    • เลือกช่วงท้ายด้วย tail
    • ใช้รหัสแทนที่แบบง่ายด้วย tr
    • คลาย raw LZMA stream ด้วย xz -F raw --lzma1 -dc
    • รันผลลัพธ์ด้วย /bin/sh

กลไกขยายของ 5.6.1

  • ในสคริปต์ยาวมีหลายจุดที่ eval ตัวแปรซึ่งไม่ได้ถูกตั้งค่าไว้
    • ตัวอย่าง: eval $zrKcVq, eval $zrKcSS
    • อาจเป็นจุดขยายสำหรับการดีบักเอาต์พุต หรือสำหรับตั้งค่าจากกลไกอื่นในอนาคต
  • หากมี config.status สคริปต์จะอ่าน LD, CC, GCC, srcdir, build, enable_shared, enable_static, gl_path_map เป็นต้น
  • โค้ดขยายที่เพิ่มใหม่ใน 5.6.1 จะค้นหาสตริงเวทสองตัวใน tests/files
    • สตริงเริ่มต้น: ~!:_ W
    • สตริงสิ้นสุด: |_!{ -
  • หากทั้งสองสตริงอยู่ในไฟล์เดียวกัน ก็จะดึงไบต์ระหว่างนั้นออกมา แล้วผ่าน tr และการคลาย raw LZMA2 ก่อนนำเอาต์พุตไป eval
  • กลไกนี้ดูเหมือนถูกเตรียมไว้เพื่อใส่สคริปต์ใหม่ลงในไฟล์ทดสอบอื่นในภายหลัง โดยไม่ต้องสร้างเหตุผลใหม่ว่ามีการสร้างไฟล์ทดสอบไบนารีเดิมขึ้นมาอีกครั้ง

เงื่อนไขการรันในขั้น configure

  • สคริปต์จะออกจากการทำงานอย่างเงียบ ๆ หากเงื่อนไขที่จำเป็นต่อแบ็กดอร์ไม่ตรง
  • ต้องเปิดใช้ GNU ifunc support
    • ต้องมี ["HAVE_FUNC_ATTRIBUTE_IFUNC"]=" 1" ใน config.status
    • ต้องมี define HAVE_FUNC_ATTRIBUTE_IFUNC 1 ใน config.h
  • ต้องเปิดการบิลด์ shared library
    • enable_shared ต้องเป็น yes
  • เป้าหมายการบิลด์ต้องเป็น x86-64 Linux
    • build ต้องตรงกับเงื่อนไข ^x86_64 และ linux-gnu$
  • ซอร์สที่เกี่ยวกับ CRC ifunc ต้องยังอยู่ครบ
    • crc64_fast.c
    • crc32_fast.c
    • crc_x86_clmul.h
  • ยังตรวจเงื่อนไขของคอมไพเลอร์และลิงเกอร์ด้วย
    • GCC=yes
    • CC=gcc
    • เอาต์พุตของ LD -v ต้องมี GNU ld
  • ต้องมีไฟล์ทดสอบที่บรรจุแบ็กดอร์คือ good-large_compressed.lzma และ bad-3-corrupt_lzma2.xz

การแก้ไข Makefile และ libtool

  • หากมี debian/rules หรือ RPM_ARCH=x86_64 โค้ดสำหรับแก้ src/liblzma/Makefile จะถูกรันในขั้น configure
  • ก่อนอื่นจะตรวจว่ามีหลายบรรทัดใน Makefile ที่จะใช้เป็นจุดแทรกในภายหลังหรือไม่
    • 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" หรือไม่
  • หลังจากนั้นจะใช้ sed -i แทรกบรรทัดที่มีลักษณะดังนี้กระจายไว้หลายจุดใน Makefile
    • 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 แม้ชื่อจะดูเหมือนไดเรกทอรี แต่จริง ๆ แล้วชี้ไปยังไฟล์
  • บรรทัดที่ถูกเพิ่มไม่ได้ถูกรวมไว้ที่เดียว แต่แทรกกระจายไปทั่ว Makefile เพื่อให้ Makefile ที่ถูกสร้างขึ้นดูซับซ้อนอย่างเป็นธรรมชาติ

แฟล็กลิงเกอร์และการรันซ้ำแบบรีเคอร์ซีฟ

  • สคริปต์ในขั้น configure จะเพิ่ม -Wl,--sort-section=name,-X เข้าไปใน liblzma_la_LDFLAGS
  • หาก LDFLAGS เดิมไม่มี -z,now หรือ -z -Wl,now ก็จะเพิ่ม -z,now เข้าไปด้วย
  • -Wl,now ทำให้ dynamic loader แก้ทุกสัญลักษณ์ตั้งแต่ตอนเริ่มโปรแกรม จึงบังคับพฤติกรรมแบบ LD_BIND_NOW
    • ระหว่างกระบวนการนี้ ifunc resolver จะถูกรันตั้งแต่เริ่มต้น
    • แบ็กดอร์จึงทำงานได้ตอนที่ GOT·PLT ยังเขียนได้อยู่
  • แฟล็ก PIC ใน libtool ถูกเปลี่ยนเป็นดังนี้
    • เดิม: -fPIC -DPIC
    • เปลี่ยนเป็น: -fPIC -DPIC -fno-lto -ffunction-sections -fdata-sections
  • สคริปต์ยังเพิ่ม AM_V_CCLD และชิ้นส่วนเชลล์ยาว ๆ เข้าไปใน Makefile ด้วย
    • ตอนท้ายจะรัน sed rpath $(am__test_dir) | $(am__dist_setup)
    • sed rpath เองก็ทำหน้าที่เป็น cat แบบทำให้อ่านยากเช่นกัน
  • ผลคือระหว่าง make จะมีการรัน pipeline ต่อไปนี้อีกครั้ง
cat ./tests/files/bad-3-corrupt_lzma2.xz |
tr "\t \-_" " \t_\-" |
xz -d |
/bin/sh

ขั้น make: การดึงไฟล์อ็อบเจ็กต์

  • ในขั้น make สคริปต์จะถูกรันอีกครั้งในไดเรกทอรี src/liblzma
  • เพราะไม่มี config.status ในไดเรกทอรีปัจจุบัน จึงข้ามส่วนแก้ไข Makefile ของขั้น configure ไป
  • แต่ถ้ามี .libs/liblzma_la-crc64_fast.o และ .libs/liblzma_la-crc32_fast.o ก็จะถือว่ากำลังอยู่ระหว่าง make แล้วรันโค้ดถัดไป
  • ใน 5.6.1 ยังเพิ่ม extension hook สำหรับขั้น make เข้ามาใหม่ด้วย
    • สตริงเริ่มต้น: jV!.^%
    • สตริงสิ้นสุด: %.R.1Z
    • ไม่มีไฟล์ทดสอบใดมีสตริงเหล่านี้ จึงดูเป็นโครงสร้างสำหรับขยายในอนาคต
  • ยังตรวจอีกครั้งว่าซอร์สที่เกี่ยวกับ CRC ifunc อยู่ในสภาพที่คาดไว้
  • รวมถึงตรวจว่าแฟล็กคอมไพล์และลิงก์ที่เพิ่มไว้ในขั้น configure ถูกใช้งานอยู่หรือไม่
    • ../../libtool ต้องมีแฟล็ก PIC ที่เพิ่มไว้
    • liblzma_la_LINK ต้องมี -z,now หรือ -z -Wl,now
    • หากมี lazy อยู่จะออกจากการทำงาน

การถอดรหัสและเลือกอ็อบเจ็กต์อันตราย

  • สคริปต์จะเลือกค่าออฟเซ็ตหนึ่งในสองค่าตามเนื้อหาใน gettext.m4
    • เนื่องจาก gettext.m4 ใน tarball xz ที่แจกจ่ายไม่มีสตริงที่ตรวจหา ในบิลด์ตัวอย่างจึงใช้ข้อมูลอินพุตทั้งหมด
  • จะคลาย good-large_compressed.lzma อีกครั้ง แล้วดึง 33,707 ไบต์ด้วย pipeline head ที่ตั้งไว้ก่อนหน้าในตัวแปร i
  • จากนั้นแบ่งเอาต์พุตเป็นหน่วยไบต์แล้วใช้ awk รัน ฟังก์ชันถอดรหัสคล้าย RC4
    • เวอร์ชัน 5.6.1 จะวนลูปที่สองไปถึง 8192
    • เวอร์ชัน 5.6.0 จะวนลูปในตำแหน่งเดียวกันไปถึง 4096
  • เอาต์พุตที่ถอดรหัสแล้วจะถูกคลายต่อด้วย xz -dc --single-stream
    • --single-stream จะหยุดที่ xz EOF marker แรก จึงไม่อ่านช่วงข้อมูลที่ถูกตัดออกมาก่อนหน้านี้ด้วย tail
  • ผลลัพธ์สุดท้ายถูกเขียนไปที่ liblzma_la-crc64-fast.o

การสลับอ็อบเจ็กต์ CRC

  • สคริปต์จะสำรองผลลัพธ์บิลด์จริง .libs/liblzma_la-crc64_fast.o ไว้เป็น .libs/liblzma_la-crc64-fast.o ที่ชื่อคล้ายกัน
    • อาศัยความต่างระหว่างขีดล่าง (crc64_fast) กับขีดกลาง (crc64-fast)
  • จากนั้นจะคอมไพล์ crc64_fast.c ที่ถูกแก้ด้วย sed แล้วใส่ไฟล์อ็อบเจ็กต์อันตราย liblzma_la-crc64-fast.o ที่ดึงออกมาเป็นอินพุตร่วม เพื่อเขียนทับ .libs/liblzma_la-crc64_fast.o
  • โค้ด C ที่ถูกแทรกจะสร้าง _is_arch_extension_supported ขึ้นใหม่ และเรียก _get_cpuid ภายใน
  • crc64_resolve เดิมจะถูกเปลี่ยนให้เรียก _is_arch_extension_supported() แทน is_arch_extension_supported()
  • _get_cpuid เป็นฟังก์ชันที่มาจากไฟล์อ็อบเจ็กต์แบ็กดอร์ และจะทำงานเพิ่มเติมก่อนคืนค่าข้อมูล cpuid
    • โดยเฉพาะคือแก้ GOT·PLT เพื่อดักการเรียก RSA_public_decrypt

การจัดการฝั่ง crc32 และการเก็บกวาด

  • หากการแก้ไขฝั่ง crc64 สำเร็จ สคริปต์จะใช้การแก้ไขคล้ายกันกับ crc32_fast.c ด้วย
  • ฝั่ง crc32 จะไม่เพิ่มไฟล์อ็อบเจ็กต์แบ็กดอร์เข้าไป
    • เพื่อหลีกเลี่ยงการใส่อ็อบเจ็กต์แบ็กดอร์ซ้ำสองครั้งในบิลด์
  • ยังไม่ชัดเจนว่าทำไมต้องดักทั้ง crc32 และ crc64 ifunc
    • จากการวิเคราะห์ดูเหมือนเพียงตัวเดียวก็เพียงพอแล้ว
    • อาจต้องการให้โค้ด dispatch ทั้งสองส่วนดูคล้ายกันเมื่อดูในดีบักเกอร์
  • หากคอมไพล์ทั้งสองตัวสำเร็จ ก็จะ relink ไฟล์ .la ด้วย liblzma_la_LINK
  • ถ้าลิงก์สำเร็จแต่ไม่มี .libs/liblzma.so จะถือว่าล้มเหลวและกู้คืนไฟล์สำรอง
  • ไม่ว่าจะสำเร็จหรือไม่ จะลบ .libs/liblzma.a, .libs/liblzma.la, .libs/liblzma.lai, .libs/liblzma.so* เสมอ
    • โดยตั้งสมมุติฐานว่าขั้นลิงก์เดิมของ Makefile จะสร้างขึ้นใหม่อีกครั้งหลังจากนั้น
  • ในเส้นทางล้มเหลว จะคืนค่าอ็อบเจ็กต์สำรองของ crc32·crc64 กลับเป็นชื่อเดิม
  • ท้ายที่สุดจะลบไฟล์ชั่วคราวและไฟล์สำรอง เพื่อฉีดอ็อบเจ็กต์อันตรายเข้าไปในผลลัพธ์ของ make โดยไม่ทิ้งร่องรอย

1 ความคิดเห็น

 
GN⁺ 2024-04-03
ความคิดเห็นจาก Hacker News
  • ในฐานะคนที่ไม่ชอบ autotools มานาน ก็อยากจะบอกว่าเหตุการณ์นี้พิสูจน์ว่าจุดยืนของผมถูกต้อง แต่ถ้าเป็นระบบ build ที่ซับซ้อนพอจะรองรับ หลายแพลตฟอร์ม ได้ มันก็หลีกเลี่ยงไม่ได้ที่จะกลายเป็นสิ่งที่เข้าใจยากจนมีคนยัดอะไรแบบนี้เข้าไปได้
    ถึงอย่างนั้น การที่ซอฟต์แวร์จำนวนมากถูก build ด้วย สคริปต์เชลล์แบบ cargo cult ขนาดมหึมา ที่แทบไม่มีใครเข้าใจทั้งหมดจริง ๆ ก็เป็นปัญหามาก

    • ผมคิดว่าสาเหตุพื้นฐานคือ bash และภาษาที่มีไวยากรณ์ซับซ้อนอัดแน่นถูกใช้อย่างแพร่หลาย
      ถ้า build script เขียนด้วย Python การ obfuscate backdoor คงยากกว่านี้มาก เพราะทุกคนคงเห็นว่ามันเป็นโค้ดแปลก ๆ แต่โค้ด bash มักถูกมองว่าเป็นเรื่องปกติ แม้จะอ่านไม่ออกก็ตาม
    • ผมเข้าใจคำวิจารณ์ต่อ autotools และไม่เคยอิจฉาคนที่ต้องดูแลสคริปต์ configure เลย แต่ในฐานะผู้ใช้ ผมคิดถึงยุคที่การติดตั้งซอฟต์แวร์แทบทุกตัวจบได้ด้วย ./configure && make && make install
    • autotools ควรหายไปได้แล้ว แต่ use case พื้นฐานส่วนใหญ่ที่ทำให้ระบบ build ซับซ้อน สุดท้ายก็ย้อนกลับมาที่ การจัดการและการตรวจจับ dependency
      การขาด best practice อย่างสิ้นเชิงสำหรับ flow นี้คือรากของความซับซ้อน ดังนั้นภายใต้เงื่อนไขแบบนี้ ไฟล์ตั้งค่า build อย่าง mybuild.toml ไฟล์เดียวจึงแก้ไม่ได้
    • เห็นด้วย และสุดท้ายเมื่อพยายามรองรับแพลตฟอร์มที่กว้างขนาดนี้ ก็จำเป็นต้องมีระบบซับซ้อนขึ้นมา และนั่นทำให้ต้องถามว่าเรากำลังยอมรับความเสี่ยงใหญ่แค่ไหน
      อีกอย่างก็สงสัยว่าทำไมการ build สิ่งอย่างไลบรารีบีบอัดข้อมูล ซึ่งโดยเนื้อแท้แล้วควรทำแค่คณิตศาสตร์กับการจัดสรรหน่วยความจำ ถึงต้องใช้ระบบที่ซับซ้อนด้วย
    • ผมก็คิดเหมือนกัน มีแรงยั่วยวนมากที่จะโทษ m4 สำหรับเรื่องทั้งหมดนี้ แต่นั่นน่าจะเป็นเสียงจาก trauma มากกว่า
  • ในฐานะนักพัฒนา เรื่องนี้น่าทึ่งมาก และสิ่งที่ดูในสายตาผมเหมือน วิธีโจมตีระดับสุดยอด อาจเป็นแค่ระดับต้นถึงกลางสำหรับคนที่ทำงานในขั้นนี้ก็ได้
    ใน HN ยังมีสิ่งที่ระดับสูงกว่านี้มาก ดังนั้นถ้ามีเงินหรือแรงจูงใจอื่นมากพอ ผมคิดว่านี่เป็นเพียงจุดเริ่มต้นของสิ่งที่เป็นไปได้เท่านั้น เมื่อคิดถึงแพ็กเกจจำนวนมหาศาลบน GitHub และไลบรารีนับล้าน vector นี้มีประสิทธิภาพเกินไป ผมจึงมั่นใจว่าในอีกไม่กี่เดือนข้างหน้าจะมีกรณีคล้ายกันถูกเปิดเผยออกมาเป็นร้อย
    ผมกังวลกับบริษัทฮาร์ดแวร์ผู้บริโภคและ prosumer ตั้งแต่ Philips Hue ไปจนถึง Alexa, SumUp, ผู้ผลิตกล้อง, Netgear, TP-Link ภายในผลิตภัณฑ์เต็มไปด้วยไลบรารีโอเพนซอร์ส และผมมั่นใจ 100% ว่าทีมพัฒนาส่วนใหญ่ไม่ได้ใช้เวลาไปกับการมองหา vector การแทรกแบบลับ ๆ แบบนี้

    • ผมเข้าใจยากกับตรรกะที่ว่า “ทีมพัฒนาส่วนใหญ่ไม่ได้ใช้เวลาไปกับการมองหา vector การแทรกแบบลับ ๆ แบบนี้” และรู้สึกเหมือนฝ่ายที่ตำหนิ dependency hell กำลังใช้สถานการณ์นี้ทำให้ผู้ดูแลโอเพนซอร์สดูแย่ลง
      องค์กรเชิงพาณิชย์ที่ชูเรื่องความน่าเชื่อถือจะทำ การวิเคราะห์ supply chain ก่อนรับ dependency มาใช้ ดังนั้นโดยปกติจึงยอมจ่ายเงินให้ Red Hat เพื่อดูแล Linux distribution ที่เสถียร และโปรเจกต์อย่าง FreeBSD จึงจำกัดซอฟต์แวร์ที่รวมมากับการติดตั้งพื้นฐานอย่างเข้มงวด
      ถ้าคุณได้รับผลกระทบจากเรื่องนี้ก็น่าเสียดาย แต่นั่นเป็นความรับผิดชอบของคุณเอง ถ้ากังวลว่านักพัฒนาซอฟต์แวร์ที่คุณใช้ฟรีเหมือนเบียร์ฟรีจะเปลี่ยนใจกลายเป็นอีกคน ก็ต้องให้แรงจูงใจที่ทำให้เขาไม่ทำแบบนั้น คือจ่ายเงิน หรือไม่ก็ fork โปรเจกต์แล้วใส่มาตรการความปลอดภัยของตัวเอง
      ถ้ากังวลว่าจะเกิด supply chain attack ใน dependency ของซอฟต์แวร์เชิงพาณิชย์ ก็ต้องเจรจาสัญญาที่รวมการชดเชยความเสียหายนั้นไว้ด้วย ถ้าไม่เต็มใจทำแบบนั้นก็ไม่เป็นมืออาชีพ
      เพิ่มเติมคือ ผมพูดอย่างจริงจังว่าแม้แต่ dependency พื้นฐานที่สุดอย่าง SSH ก็ต้องตรวจสอบ supply chain
    • จริง ๆ แล้วตรงกันข้าม นักพัฒนาและผู้ดูแลที่รู้ดีกว่าเราบรรยายเหตุการณ์นี้ว่าเป็น การโจมตีที่ซับซ้อนอย่างยิ่ง
      บทความด้าน infosec ช่วงแรก ๆ ก็อธิบายได้แค่บางส่วนของโค้ด และยังไม่ครอบคลุมกลยุทธ์ทั้งหมดของการโจมตี เพราะทั้งการโจมตีและโค้ดมีความซับซ้อน การที่บทวิเคราะห์ช่วงแรกอธิบายการโจมตีแตกต่างกันก็เพราะมันไม่ใช่เรื่องเข้าใจง่าย และภายหลังจึงมีบทความทำนองว่า “ในที่สุดก็ดูเหมือนจะเป็นการโจมตี remote code execution” ออกมา
      ตอนนี้มีแม้กระทั่ง scanner สำหรับตรวจหาช่องโหว่บนเซิร์ฟเวอร์แล้ว ทุกคนเลยพูดได้ว่า “อ้อ นั่นเป็นการโจมตีที่เรียบง่ายและโง่มาก ทำไมถึงไม่เจอเร็วกว่านี้นะ?” เท่านั้นเอง
    • เพราะอย่างนั้น ผมจึงไม่เห็นว่า TP-Link จะได้ประโยชน์อะไรจากการทำ firmware เราเตอร์บนฐาน OpenWRT ผมอยากให้เครื่องของผมรัน โปรเจกต์ upstream แบบบริสุทธิ์ หรืออะไรสักอย่างที่ตาม upstream โดยการออกแบบ
      เรื่องนี้ใช้กับทุกอุปกรณ์เหมือนกัน ผมไม่ชอบที่ Android ต้องใช้ kernel เก่า และก็ไม่ชอบที่ macOS เคยรันสายตระกูล Darwin/BSD ที่ล้าสมัย ผมกังวลกับความพยายามที่ต้องใช้ในการ backport
      แน่นอนว่านี่ไม่ได้หมายความว่าโอเพนซอร์สไม่มีช่องโหว่
    • องค์กรที่ดำเนินงานได้ค่อนข้างถูกต้องย่อมมีกลไกสำหรับรับอัปเดตเมื่อ dependency มีปัญหาด้านความปลอดภัย บางอุตสาหกรรมยังถูกหน่วยงานกำกับดูแลหรือหน่วยงานรับรองอย่าง PCI กำหนดให้ทำด้วย
      บางทีสิ่งที่ควรกลัวมากกว่าคือ backdoor ที่มองไม่เห็นภายในซอฟต์แวร์ proprietary ซึ่งแทบจะไม่ถูกค้นพบเลย
  • ดูเหมือนว่ายังไม่มีใครพูดถึง infographic ของ Thomas Roccia ที่นี่: https://twitter.com/fr0gger_/status/1774342248437813525

    • หลายส่วนให้ความรู้สึกเหมือนพยายามเชื่อมเบาะแสแบบฝืน ๆ โดยไม่มีหลักฐาน
      ตัวอย่างเช่น oss-fuzz build xz โดย clone repository บน GitHub โดยตรง backdoor อยู่เฉพาะใน tarball ไม่ได้อยู่ใน repository ดังนั้น oss-fuzz ไม่มีทางพบ backdoor ได้ เพราะฉะนั้น PR ของ oss-fuzz นั้นอาจเป็นการเปลี่ยนแปลงจริงที่ไม่เกี่ยวกับ backdoor ก็ได้
    • Jia Tan ขอให้ distribution ต่าง ๆ อัปเดตอย่างรวดเร็วก่อนการเปิดเผยไม่นาน
      มีความเป็นไปได้แค่ไหนที่มีบัญชีหรือบุคคลอื่นรอบตัว Andreas Freund ที่รู้ก่อนหน้านั้นว่า backdoor กำลังจะถูกเปิดเผย เรื่องนี้ยังทำให้คิดว่าอาจยังมี คนวงในคนอื่น อยู่แถว ๆ นั้น
    • เอกสารนี้แค่แสดงให้เห็นบางส่วนในระดับสูงว่า exploit ถูกฝังเข้าไปใน liblzma อย่างไร แต่ไม่ได้พูดเลยว่า exploit ทำงานอย่างไรหรือมีเนื้อหาอะไร
    • ถ้าดู timeline การโจมตีเริ่มจากการเพิ่มรายการ ignore ลงในไฟล์ .gitignore ทุกวันนี้ตรวจจับเรื่องแบบนี้ได้ยาก
  • ส่วนที่สะดุดตาที่สุดจากมุมมองของผู้สังเกตการณ์ที่ไม่รู้อะไรคือสิ่งนี้
    “ไฟล์จำนวนมากถูกสร้างขึ้นด้วยมือด้วย hex editor ดังนั้นจึงไม่มี ‘ซอร์สโค้ด’ ที่ดีกว่าตัวไฟล์เอง” เข้าใจได้ว่าในไลบรารีสำหรับพาร์สอย่าง liblzma อาจเป็นแบบนั้น ผู้โจมตีน่าจะดูเหมือนแค่เพิ่มไฟล์ทดสอบใหม่ไม่กี่ไฟล์
    ตัวไฟล์เองก็น่ากลัวอยู่ แต่ก็พอเข้าใจเหตุผลได้ ถึงอย่างนั้นอย่างน้อยก็น่าจะแยกออกจากขั้นตอน build ได้ไม่ใช่หรือ
    “โดยปกติสคริปต์ configure และไลบรารีสนับสนุนจะถูกเพิ่มเฉพาะใน tarball สำหรับแจกจ่าย ไม่ใช่ในซอร์สรีโพซิทอรี การแจกจ่าย xz ก็เป็นแบบนี้”
    พักความโกรธตามธรรมเนียมต่อ autotools ไว้ก่อน ผมไม่เข้าใจว่าทำไมไฟล์ทดสอบต้องอยู่ใน tarball ด้วย การทดสอบที่เป็นอันตรายอาจทำให้เครื่องของนักพัฒนาติดเชื้อได้ก็จริง แต่ถ้า tarball มีไว้เพื่อ build ผลลัพธ์สุดท้าย ก็น่าจะมีนโยบายรวมเฉพาะสิ่งที่จำเป็นไม่ใช่หรือ โดยเฉพาะอย่างยิ่งเมื่อไฟล์ทดสอบเป็น ก้อน binary ที่ audit ไม่ได้

    • การรันเทสต์ใน CI เพื่อตรวจสอบว่าหลัง build แล้วไม่มีปัญหาในสภาพแวดล้อมเฉพาะนั้นค่อนข้างพบได้ทั่วไป
      แต่ครั้งล่าสุดที่เราทำแบบนั้น เราเลือกใช้ Git upstream และสร้างผลลัพธ์ autoconf ที่จำเป็นเอง แนวคิดเรื่อง release tarball ที่มีสิ่งซึ่งไม่มีใน Git อยู่ด้วยนั้นไม่เคยถูกใจเลย
    • ถึงแม้จะมีโค้ด autoconf ที่สร้างขึ้นแล้วอยู่บ้าง สิ่งเหล่านั้นก็ยังเป็น source tarball อยู่ดี
      ควรต้องสามารถคอมไพล์โค้ดบนเครื่องเป้าหมายแล้วรันเทสต์ได้
    • นอกจากการตรวจสอบว่าโปรแกรมที่คอมไพล์บนเป้าหมายทำงานได้ถูกต้องแล้ว หากต้องการคอมไพล์ด้วย profile-based optimization ก็จำเป็นต้องมีตัวอย่างการรันสำหรับใช้ปรับให้เหมาะสม จึงต้องมีเทสต์
  • “ความแตกต่างแรกคือสคริปต์ทำให้แน่ใจว่า ถ้าไม่ได้รันบน Linux จะต้องจบการทำงานอย่างแน่นอน แบบแน่เสียยิ่งกว่าแน่”
    การตรวจซ้ำ ๆ นั้นเป็นปริศนาจริง ๆ สมมติฐานของผมคือผู้โจมตีอาจใส่การทำซ้ำเพื่อให้ดูสมจริงเหมือน input ทดสอบของไลบรารีบีบอัด

    • อาจมีจุดประสงค์เพื่อกันพื้นที่สำหรับแก้สคริปต์ เพราะสามารถเขียนทับไบต์ช่วงต้นของสคริปต์ได้
      หรือไม่ก็แค่ขี้เกียจ
    • ผมก็คิดว่าแปลกเหมือนกัน ตอนต้นของสคริปต์ยังมีไบต์สุ่มต่าง ๆ แปะอยู่ด้วย และไม่ใช่ข้อความ แต่เป็น ไบต์สุ่ม จริง ๆ เพียงแต่มีเครื่องหมายแฮชนำหน้า จึงถูกทำเป็นคอมเมนต์และไม่กระทบกับสคริปต์
      ดูเหมือนจงใจ แต่ไม่รู้ว่ามีไว้ทำไม ตอนแรกคิดว่าอาจเพิ่มมาเพื่อเติมขนาด เพราะ xz อาจข้ามการบีบอัดถ้า input สั้นหรือไม่ซับซ้อนเกินไป แต่พอลบออกแล้วบีบอัดใหม่ด้วย xz ก็ยังบีบอัดได้ตามปกติ และ plaintext เดิมก็ไม่เหลืออยู่ในไบต์ของ archive ที่บีบอัดแล้ว
      สิ่งที่พบระหว่างพยายามทำซ้ำไบต์ที่แน่นอนของไฟล์ .xz ที่ commit ใน Git คือ xz stream ของสคริปต์นั้นดูเหมือนไม่ได้ถูกบีบอัดด้วย preset มาตรฐานของ xz ต้องใช้ xz --lzma2=dict=65536 -c stream_2 ถึงจะทำซ้ำได้ และ preset แบบตัวเลขมาตรฐานทั้งหมดเลือก ขนาดพจนานุกรม ที่ต่างออกไป เรื่องนี้ก็ดูเหมือนจงใจ แต่ยังไม่เข้าใจเหตุผล
    • อาจมีจุดประสงค์เพื่อทำให้บางส่วนของไฟล์ทดสอบที่ถูกบีบอัดมีขนาดใหญ่ขึ้นหรือทำให้วิเคราะห์ยากขึ้นก็ได้
      ถ้าไม่มีการทำซ้ำ ภายในไฟล์บีบอัดอาจเกิด binary แปลก ๆ ที่ไปกระตุ้นเครื่องมือความปลอดภัยหรือแอนติไวรัสก็ได้
    • มันเป็นปริศนาจริงหรือ? ผู้โจมตีคงเล็งเป้าไปที่ Linux x86 และการรองรับ IFUNC ก็ไม่ได้รับประกันว่าจะทำงานบนแพลตฟอร์มอื่น
    • หากรันบนที่ไม่ใช่ Linux อาจแครชหรือทิ้งร่องรอยจนถูกจับได้เพราะความแตกต่างของระบบปฏิบัติการ
  • เป็นเรื่องตลกร้ายที่เทคโนโลยีสมัยใหม่ซับซ้อนอย่างโหดร้ายและเข้าใจยากโดยไม่จำเป็น และมันก็แย่ลงเรื่อย ๆ เหมือนนักพัฒนาจะสนุกกับมันแบบซาดิสต์

    • นี่น่าจะเป็นการตีความที่แย่ที่สุด
      เป็นเรื่องน่าทึ่งทีเดียวที่เครื่องมือต่าง ๆ ไล่ตามความซับซ้อนของผลิตภัณฑ์ที่เราสร้างขึ้นได้ พูดตามตรง ในกรณีส่วนใหญ่ มันก็แค่ง่ายขึ้นกว่าเดิม และใกล้เคียงกับการที่ผู้คนไม่อยากเรียนรู้สิ่งใหม่มากกว่า
  • ใครก็ตามที่จ้างคนเหล่านี้ให้แทรกซึมเข้าไปในโปรเจกต์นี้ คงทุ่มเวลาอย่างมหาศาลเพื่อทำให้มันหลบการตรวจจับได้เป็นเวลานาน โชคดีที่มันซับซ้อนเกินไปจนพวกเขาพิจารณาองค์ประกอบทั้งหมดไม่ครบ
    ดังนั้นในแง่ความปลอดภัย ผมจึงคิดว่าโอเพนซอร์สจะดีกว่าซอร์สปิดเสมอ แน่นอนว่าเหตุการณ์นี้เผยให้เห็น ข้อบกพร่องขนาดใหญ่ของซัพพลายเชน และยังแสดงให้เห็นว่าองค์ประกอบพื้นฐานของ FOSS ถูกประเมินค่าต่ำเกินไปเพียงใด จนผู้ดูแลมีความเปราะบางต่อการถูกชักจูง
    แต่ถ้าการโจมตีแบบเดียวกันเกิดขึ้นภายในบริษัทเอกชนล่ะ? เป็นไปได้สูงว่าอาจไม่ต้องใช้แม้แต่การทำให้อ่านยากขั้นสูงด้วยซ้ำ แค่มี PR ที่ใหญ่พอและเดดไลน์ที่ใกล้เข้ามา ก็สามารถแอบใส่สิ่งแบบนี้เข้าไปในระบบที่ใช้งานจริงได้ด้วยความพยายามขั้นต่ำ กว่าบริษัทจะรู้ตัวว่าเกิดอะไรขึ้น ก็คงบินไปยังประเทศที่ไม่มีสนธิสัญญาส่งผู้ร้ายข้ามแดนแล้ว และกำลังขายข้อมูลที่รั่วไหลผ่าน Tor หรือดาร์กเว็บอยู่

    • ผมคิดว่านี่มี อคติจากผู้รอดชีวิต อยู่ เราจะรู้ได้อย่างไรว่ามีความพยายามคล้ายกันกี่ครั้งที่สำเร็จ? ในบรรดาสิ่งที่ถูกพบ มีกี่อย่างที่ถูกมองข้ามว่าเป็นแค่ความผิดพลาดธรรมดา? เช่น เราแน่ใจได้อย่างไรว่า Heartbleed ไม่ได้ถูกใครบางคนใส่เข้าไปโดยเจตนา และคนคนนั้นไม่ได้ร่ำรวยมหาศาลไปแล้วในตอนนี้
      ถ้าคุณถูกจ้างเข้าบริษัทเอกชน บริษัทจะรู้ว่าคุณเป็นใคร นั่นเองเป็นแรงยับยั้งทันทีต่อการทำสิ่งน่าสงสัย บน GitHub ไม่มีใครรู้ว่าคุณเป็นใคร การใส่แบ็กดอร์เข้าโปรเจกต์โดยไม่ถูกจับได้อาจยากกว่า แต่ถึงถูกจับได้ก็ไม่มีความเสี่ยงที่ต้องรับ คุณสามารถลองต่อไปได้มากเท่าที่ต้องการ Jia Tan ยังคงไม่ถูกจับ และไม่จำเป็นต้องวางแผนชีวิตทั้งหมดเพื่อไปอยู่ในประเทศที่ไม่มีสนธิสัญญาส่งผู้ร้ายข้ามแดนด้วย เว้นแต่เขาจะอยู่ที่นั่นอยู่แล้ว
    • เห็นด้วยยาก บริษัทเอกชนส่วนใหญ่คงต้องการ การพบหน้ากัน ตอนเข้าทำงาน แม้จะเป็นงานรีโมตเต็มรูปแบบ ก็ยังมีความคาดหวังว่าสักวันหนึ่งจะได้พบเพื่อนร่วมงานตัวจริง และโดยปกติน่าจะเกิดขึ้นก่อนจะมีคอมมิตที่มีนัยสำคัญ บริษัทที่คุ้มค่าต่อการแทรกซึมแทบจะแน่นอนว่าจะต้องมีการตรวจสอบประวัติ
      และแม้จะเข้าไปได้แล้ว ก็ไม่สามารถคอมมิตเข้าโปรเจกต์เป้าหมายได้ตามใจชอบ ผู้จัดการของคุณและผู้จัดการเหนือขึ้นไปมีลำดับความสำคัญอื่น การบริหารที่มักทำงานผิดปกติของบริษัทแสวงหากำไรกลับทำหน้าที่เป็นแรงยับยั้งในกรณีนี้ คุณไม่เพียงต้องให้เหตุผลกับตัวโค้ดเอง แต่ยังต้องอธิบายด้วยว่าทำไมตั้งแต่แรกคุณถึงทำงานนั้นอยู่
    • ออกนอกประเด็นเล็กน้อย แต่ในมุมของสหรัฐฯ ทุกวันนี้จริง ๆ แล้วมี ประเทศที่ไม่มีสนธิสัญญาส่งผู้ร้ายข้ามแดน อยู่มากแค่ไหน
      แม้แต่ประเทศที่ความสัมพันธ์ตึงเครียด หากสะดวกทางการเมืองก็อาจส่งตัวให้เป็นส่วนหนึ่งของการเจรจาได้ รัสเซียเองก็คงไม่เก็บ Snowden ไว้ หากเขาไม่ได้เปิดโปงความลับของรัฐ ถ้าเป็นแค่การรั่วไหลข้อมูลธรรมดา ๆ เขาอาจถูกนำไปแลกตัวกับโอลิการ์ชที่ถูกจับคดีฟอกเงินที่อื่นก็ได้
    • การสำรวจโปรเจกต์เล็ก ๆ ที่ดูค่อนข้างไม่เป็นอันตรายแต่ถูกใช้แทบทุกที่ เพื่อดูว่าสามารถถูกจัดการด้วยวิธีเดียวกันได้หรือไม่ หรือเคยมีเรื่องคล้ายกันเกิดขึ้นแล้วหรือเปล่า น่าจะเป็นโปรเจกต์สำหรับวิชาเรียนที่น่าสนใจ
      แค่ทำรายการออกมาก็น่าจะมีประโยชน์แล้ว
  • บทเรียนจากเหตุการณ์นี้คือ เราอาจไม่ควรอนุญาตให้ผู้มีส่วนร่วมหลักของโปรเจกต์โอเพนซอร์สสำคัญมี ความเป็นนิรนาม การโจมตีนี้สำเร็จ และผู้โจมตีคงจะหลุดรอดไปโดยไม่ต้องรับผลใด ๆ เพราะเขาไม่เปิดเผยตัวตน

    • ไม่เห็นด้วย
      มาตรการแบบนั้นจะไม่ช่วย และสำหรับผู้กระทำระดับรัฐหรือ ภัยคุกคามขั้นสูงแบบต่อเนื่อง ที่คล้ายกัน ก็หลบเลี่ยงได้ง่าย ๆ ด้วยการเพิ่มขั้นตอนขโมยตัวตนเข้าไปในกระบวนการโจมตี หรือใช้เจ้าหน้าที่ที่สามารถปกป้องได้แม้แบ็กดอร์ถูกพบ
      ในทางกลับกัน อุปสรรคทางเทคนิคที่จำเป็นสำหรับกระบวนการแบบนั้นมีแนวโน้มจะสร้างความเสียหายใหญ่หลวงต่อชุมชนโอเพนซอร์สโดยรวม
      ทางแก้ในที่นี้คือเรียนรู้จากการโจมตีนี้ แล้วเปลี่ยนไปใช้แนวปฏิบัติที่ทำให้การโจมตีคล้ายกันยากขึ้น ไฟล์ที่ไม่ได้อยู่ในรีโพซิทอรีไม่ควรถูกใส่ไว้ใน release tarball เด็ดขาด โค้ดที่ถูกสร้างขึ้นทั้งหมดควรต้องถูกเช็กอิน และสคริปต์บิลด์ควรสร้างโค้ดอนุพันธ์ขึ้นใหม่ แล้วล้มเหลวหากแตกต่างจากโค้ดที่เช็กอินไว้ ข้อมูลที่เข้าใจยากไม่ควรเข้าถึงได้ระหว่างกระบวนการบิลด์รีลีส และการทดสอบที่พึ่งพาข้อมูลไบนารีควรถูกบิลด์แยกจากไบนารีรีลีสอย่างสมบูรณ์
    • มีปัญหาสองข้อ
      ข้อแรก ผู้มีส่วนร่วมสำคัญจำนวนมาก โดยเฉพาะในสายความปลอดภัย นิยมทำงานแบบ ใช้นามแฝง ด้วยเหตุผลที่สมเหตุสมผล การบังคับให้เปิดเผยตัวตนจะผลักพวกเขาออกไป
      ข้อสอง หากหน่วยข่าวกรองอยู่เบื้องหลังอย่างที่หลายคนคาดเดา หน่วยงานแบบนั้นก็สามารถสร้างตัวตน “จริง” ขึ้นมาได้อยู่ดี สุดท้ายจะเป็นการกีดกันคนที่เป็นประโยชน์ แต่กันผู้โจมตีไม่ได้
    • ไม่เพียงบังคับใช้ไม่ได้ แต่อาจไม่ใช่ความคิดที่ดีด้วย เพราะถ้ารู้ตัวตนของผู้ดูแลโปรเจกต์โอเพนซอร์สสำคัญ ก็จะทำให้ กดดันพวกเขา ได้ง่ายขึ้น
    • ถ้านี่เป็นผู้กระทำระดับรัฐ ซึ่งดูเหมือนจะเป็นเช่นนั้นจริง ๆ แล้วจะตรวจสอบอะไรได้บ้าง? ใบขับขี่ หมายเลขประกันสังคม บัตรประชาชน หนังสือเดินทาง หรืออะไรก็แล้วแต่ พวกเขาคงทำเอกสารที่ถูกกฎหมายขึ้นมาได้
      ถ้ารัฐบาลเข้ามาเกี่ยวข้อง ก็ไม่มีขีดจำกัด วิธีเดียวคือบังคับให้ไปปรากฏตัวจริงในสถานที่ที่เชื่อถือได้ แล้วก็ได้แต่หวังว่าสถานที่นั้นจะไม่อยู่ในเขตอำนาจของผู้โจมตี
    • ใครเป็นคนกำหนดว่าอะไรคือ โปรเจกต์สำคัญ
      ถ้ามีใครสร้างไลบรารีขึ้นมา แล้วคนอื่นเริ่มเอาไปใช้ เขาจะถูกบังคับให้เปิดเผยตัวตนหรือ? ผู้ดูแลได้รับเงินหรือเปล่า?
  • ไม่ว่าจะซอร์สปิดหรือโอเพนซอร์ส ถ้าเคยทำงานพัฒนา คุณจะรู้ว่านักพัฒนาครึ่งหนึ่งแทบจะอนุมัติ PR แบบขี้เกียจ ๆ ไปเลย Linus Torvalds เป็นข้อยกเว้นที่หาได้ยาก ที่คอยชี้ปัญหาตลอดทั้งวัน

    • เห็นด้วย
      ถ้าใครเข้มงวดพอที่จะใส่ใจตรวจจริง ๆ คนคนนั้นก็มักถูกมองว่าเป็นตัวปัญหาที่ขวางการพัฒนา เกิดความตึงเครียดกับทีมเพราะถูกมองว่าจับผิด
      พูดตามตรง ตอนนี้ผมก็มีสถานการณ์คล้ายกันอยู่ คนที่เข้มงวดไม่ใช่ผม แต่เป็นนักพัฒนาคนหนึ่งที่ผมจ้างมา น่าเสียดายที่พฤติกรรมละเอียดรอบคอบของเขาไม่ได้รับการประเมินในทางที่ดี จนต้องเอาเขาออกจากทีม การที่เขามาจากยุโรปตะวันออกและมักให้ฟีดแบ็กแบบตรงมาก ๆ ก็ไม่ได้ช่วยนัก
  • ยูทิลิตี Unix ผ่านการพิสูจน์มาเป็นเวลานานแล้ว ผมอยากให้ตรึงเคอร์เนลและยูทิลิตีหลักไว้ แล้วไม่ต้องเปลี่ยนมัน ถ้าไม่ได้จำเป็นจริง ๆ
    ถ้ามันไม่เสียก็อย่าไปซ่อม นั่นแหละ จักรวรรดิซอฟต์แวร์ ดูเหมือนกำลังควบคุมไม่อยู่

    • ทุกอย่างเสียหมดแล้ว มันคือผลสะสมของการแฮ็กแบบลวก ๆ เพื่อให้พอทำงานได้ในวันนี้ ผ่านเวลา 50 ปีและนักพัฒนาหนึ่งล้านคน
      บางครั้งก็มีตัวอย่างที่ส่องสว่างของสิ่งที่ถูกสร้างมาอย่างถูกต้องอยู่บ้าง แต่โดยรวมแล้วควรมองว่าสิ่งเหล่านั้นถูกกลืนหายไปหมดแล้ว