2 คะแนน โดย GN⁺ 2024-01-07 | 1 ความคิดเห็น | แชร์ทาง WhatsApp
  • Chromium Money Tree Browser แมป รางวัล Chrome VRP เข้ากับประวัติการแก้ไขแยกตามไดเรกทอรีและไฟล์ในรีโพซิทอรี Chromium ทำให้ดูได้คร่าว ๆ ว่าเงินรางวัลด้านความปลอดภัยไปกองอยู่ตรงไหนใน code tree
  • จำนวนเงินรางวัลจะถูกเฉลี่ยแจกตามจำนวนไฟล์ที่ถูกแก้ไข เช่น ถ้าการแก้บั๊กที่ได้ รางวัล $1,000 เปลี่ยน 5 ไฟล์ แต่ละไฟล์จะถูกจัดสรร $200
  • ยอดรวมระดับบนสุดแสดงเป็น root $9,873,277 / 10,944 รายการ, chromium $9,014,838 / 10,218 รายการ, chrome $2,568,260 / 2,574 รายการ
  • พื้นที่ต่าง ๆ อย่าง chrome/browser/ui/views, extensions, media, safe_browsing, enterprise, Android, net, device, gpu, storage, base, iOS, pdf ถูกแยกย่อยลงไปถึงระดับไฟล์ และ V8 ก็มีสัดส่วนใหญ่ที่ $858,439 / 726 รายการ
  • มีคำเตือนว่าทั้งข้อมูลและ UI อยู่ในสภาพ “very very hacked together” และขอบเขตข้อมูลก็มีถึงเพียง ต้นเดือนพฤศจิกายน 2023 จึงเหมาะจะมองเป็นแผนที่สำหรับสำรวจมากกว่าข้อมูลบัญชีที่แม่นยำ

วิธีนำจำนวนเงินรางวัลไปวางทับบน code tree

  • เป็นเบราว์เซอร์ที่แสดงการเชื่อมโยงรางวัล bug bounty ของ Chrome VRP เข้ากับ tree ของไฟล์และไดเรกทอรี ใน codebase ของ Chromium
    • ถ้าการแก้ไขด้านความปลอดภัยหนึ่งรายการเปลี่ยนหลายไฟล์ ก็จะแบ่งเงินรางวัลตามจำนวนไฟล์แล้วจัดสรรให้แต่ละไฟล์
    • การเชื่อมโยงนี้ใกล้เคียงกับการใช้ดูว่า “โค้ดส่วนไหนมักถูกแก้พร้อมกับรางวัลด้านความปลอดภัย” มากกว่า
  • แค่ดูยอดรวมระดับบนสุดก็เห็นการกระจายของเงินรางวัลใน Chromium ทั้งระบบได้ในระดับหนึ่ง
    • root: $9,873,277 / 10,944 รายการ
    • chromium: $9,014,838 / 10,218 รายการ
    • chrome: $2,568,260 / 2,574 รายการ
    • chrome/browser: $2,250,643 / 1,920 รายการ

การกระจายแยกตามไดเรกทอรีที่น่าสนใจ

  • ใต้ chrome/browser/ui/views มีการกระจายของเงินรางวัลแยกละเอียดตามฟีเจอร์ UI ฝั่งผู้ใช้
    • views: $514,665 / 441 รายการ
    • tabs: $56,705 / 30 รายการ
    • eye_dropper: $47,000 / 7 รายการ
    • bookmarks: $46,697 / 31 รายการ
    • payments: $43,623 / 60 รายการ
    • media_router: $36,395 / 12 รายการ
    • tab_sharing: $30,591 / 9 รายการ
  • พื้นที่ที่เกี่ยวกับ Chrome extensions ก็ปรากฏซ้ำเป็นก้อนใหญ่เช่นกัน
    • extensions: $157,507 / 262 รายการ
    • extensions/api: $115,471 / 161 รายการ
    • api/tabs: $42,705 / 48 รายการ
    • api/debugger: $28,488 / 35 รายการ
    • api/downloads: $15,225 / 13 รายการ
    • อีกส่วนของ extensions ก็ถูกรวมไว้ที่ $132,615 / 213 รายการ โดยมี renderer, guest_view/web_view และ file_system API รวมอยู่ด้วย
  • V8 ดูเป็นพื้นที่ย่อยเดี่ยวที่ใหญ่ที่สุดในโน้ตที่ให้มา
    • V8 ทั้งหมด: $858,439 / 726 รายการ
    • v8/src: $626,845 / 503 รายการ
    • v8/test: $209,030 / 195 รายการ
    • v8/src/compiler: $151,267 / 85 รายการ
    • v8/src/heap: $91,891 / 64 รายการ
    • v8/src/builtins: $68,133 / 30 รายการ
    • v8/test/mjsunit: $164,644 / 113 รายการ
  • ฝั่ง chrome/browser จุดที่เด่นคือจุดสัมผัสกับผู้ใช้อย่าง UI, แท็บ, autofill, รหัสผ่าน, DevTools และ renderer context menu
    • chrome/browser/autofill: $114,656 / 40 รายการ
    • chrome/browser/tabs: $92,316 / 25 รายการ
    • passwords: $51,060 / 10 รายการ
    • chrome_content_browser_client.cc: $51,512 / 11 รายการ
    • devtools: $48,255 / 35 รายการ
    • renderer_context_menu: $47,842 / 16 รายการ
    • printing: $42,225 / 14 รายการ
    • payments: $41,252 / 10 รายการ
  • พื้นที่ด้านสื่อ ความปลอดภัย องค์กร และแพลตฟอร์มก็มีการรวมยอดค่อนข้างสูง
    • media: $134,523 / 65 รายการ, และส่วน chrome/browser/media แยกอีก $89,008 / 34 รายการ
    • safe_browsing: $80,161 / 31 รายการ
    • enterprise: $59,000 / 38 รายการ
    • ash: $130,389 / 161 รายการ, และอีกช่วงของ ash ต่อเนื่องที่ $56,867 / 55 รายการ
    • mojo: $112,725 / 26 รายการ
    • net: $97,558 / 175 รายการ
    • device: $61,770 / 32 รายการ
    • gpu: $51,155 / 30 รายการ
    • storage: $48,303 / 66 รายการ
    • base: $36,013 / 27 รายการ
  • Android และ iOS ก็มีการแยกการกระจายของเงินรางวัลตามโค้ดแพลตฟอร์มเฉพาะ
    • พื้นที่ Android chrome/browser ฝั่ง Java, resources และ test: $94,441 / 159 รายการ
    • เส้นทาง Android Java: $62,571 / 91 รายการ
    • Android fullscreen: $18,707 / 11 รายการ, และ FullscreenHtmlApiHandler.java อยู่ที่ $18,540 / 10 รายการ
    • iOS: $33,625 / 86 รายการ
    • ios/chrome/browser/web: $11,663 / 4 รายการ
    • ios/chrome/browser/ui: $9,884 / 24 รายการ

ไฟล์ทดสอบและข้อควรระวังในการตีความ

  • ข้อมูลทดสอบและไฟล์ regression test ก็ถูกรวมอยู่ในการกระจายของเงินรางวัลด้วย
    • test: $147,193 / 311 รายการ
    • test/data: $116,355 / 271 รายการ
    • test/data/extensions/api_test: $59,337 / 166 รายการ
    • V8 test/mjsunit/regress: $82,180 / 58 รายการ
    • V8 test/mjsunit/compiler: $46,233 / 28 รายการ
    • เพราะเมื่อการแก้ไขด้านความปลอดภัยถูกบันทึกร่วมกับการเปลี่ยนไฟล์ทดสอบ เงินรางวัลก็จะถูกกระจายไปยังไฟล์เหล่านั้นด้วย
  • วิธีคำนวณค่อนข้างเรียบง่าย จึงตีความจำนวนเงินเป็นระดับความเสี่ยงหรือสาเหตุของช่องโหว่โดยตรงได้ยาก
    • เนื่องจากเอาเงินรางวัลไปหารด้วย “จำนวนไฟล์ที่ถูกแก้ไข” จำนวนเงินของแต่ละไฟล์จึงไม่ได้หมายถึงระดับความเสี่ยงของไฟล์นั้นโดยตรง
    • ข้อมูลและ UI อยู่ในสภาพ “very very hacked together” และมีคำเตือนไม่ให้คาดหวัง UX ที่ดีหรือข้อมูลที่แม่นยำ
    • ขอบเขตข้อมูลมีถึง ต้นเดือนพฤศจิกายน 2023
  • มีลิงก์การพูดคุยที่เกี่ยวข้องให้มาด้วย

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

 
GN⁺ 2024-01-07
ความเห็นจาก Hacker News
  • ค่อนข้างคล้ายกับสิ่งที่อยากทำมานานแล้ว ผมคิดว่าน่าจะมีประโยชน์ถ้าคำนวณความเป็นไปได้ที่การเปลี่ยนแปลงบางอย่างจะก่อปัญหา โดยอิงจาก ประวัติการเปลี่ยนแปลงที่ทำให้พัง ซึ่งเคยเกิดขึ้นในไฟล์เดียวกันหรือบริเวณเดียวกันภายในไฟล์
    โดยพื้นฐานคือให้ คะแนนความเสี่ยง กับแต่ละการเปลี่ยนแปลง แล้วแสดงคะแนนนั้นในแต่ละ PR เพื่อให้ reviewer รู้ว่าควรดูโค้ดส่วนไหนอย่างระมัดระวังเป็นพิเศษ และตอน deploy ก็ไฮไลต์การเปลี่ยนแปลงที่มีความเสี่ยงด้วย
    ส่วนที่ยากคือการติดตามบริเวณโค้ดเดิมต่อไปเมื่อตำแหน่งโค้ดเลื่อนขึ้นลงเพราะมีการแทรก/ลบด้านบน อัลกอริทึมที่พึ่งพาแค่เลขบรรทัดจะมีปัญหาตรงนี้
    แต่ถึงอย่างนั้น แค่ทำระดับไฟล์เหมือนกรณีนี้ก็น่าจะมีประโยชน์พอแล้ว

    • ทำงานเรื่องนี้มานานกว่า 2 ปีแล้ว เราวิเคราะห์แต่ละการเปลี่ยนแปลงแบบ static analysis และวิเคราะห์ monorepo ทั้งหมดทุกวัน จากนั้นประมวลผลในระดับ symbol
      สำหรับการเปลี่ยนแปลงที่มีความเสี่ยงสูง เราจะรันเทสต์มากขึ้น แต่ไม่ใช่ unit test เป็น client test บางครั้งมี client test ให้เลือกถึง 100,000 รายการ จึงต้องจัดอันดับแล้วรันเพียง subset ขนาดเล็ก
      เป็นปัญหาที่ยาก ข้อสังเกตที่น่าสนใจอย่างหนึ่งคือ แม้ใน change ที่เป็นสาเหตุจะมี symbol ที่เป็นสาเหตุอยู่หนึ่งหรือสองตัว แต่ connectivity ของ symbol เหล่านั้นกลับคล้ายกับ symbol ที่ไม่ใช่สาเหตุใน change เดียวกันมาก
      อีกอย่างคือหลังการเปลี่ยนแปลง call graph ที่ถูกแก้ไขแบบ transitive มีขนาดค่อนข้างใหญ่ ความลึก 50 ก็ไม่ใช่เรื่องหายาก นอกจากระดับการทับซ้อนของ symbol ที่ได้รับผลกระทบแบบ transitive ระหว่าง change กับ test แล้ว แทบจะดึงสัญญาณที่มีประโยชน์อื่น ๆ ออกมาได้ยาก
      ระดับไฟล์และระดับ build target หยาบเกินไป ส่วน AST symbol ใช้ได้ดี
    • ไม่ควรดูแค่ตัวโค้ดเอง แต่ต้องดู ผู้เขียน ด้วย เคยมีคนที่ผมทำงานด้วยซึ่งทุกครั้งที่สร้าง PR จะใส่บั๊กเข้ามาอย่างน้อยหนึ่งตัว
    • ตอนนี้กำลังอ่านหนังสือเรื่องนี้อยู่: https://pragprog.com/titles/atcrime/your-code-as-a-crime-sce...
    • น่าจะดีถ้าดู การวิเคราะห์ data flow ของตำแหน่งโค้ด แหล่งที่มา/ผู้เขียน และโค้ดอ่อนไหวที่อยู่ใกล้เคียงร่วมกัน น่าใส่ไว้ในเครื่องมือ review ของผม
  • เจ๋งมาก แต่ดูเหมือนยังมีรายการตกหล่นอยู่บ้าง ผมมั่นใจว่าใน third_party/ffmpeg ก็มีอย่างน้อยหนึ่งรายการ
    การแก้ไขแบบนั้นมักเข้า upstream ก่อน จึงอาจตามรอยได้ยาก

    • ใช้คอมเมนต์ที่ Git Watcher ทิ้งไว้ในบั๊ก Monorail อยู่
  • เมื่อดูชุดใหญ่ ๆ ใต้ chrome/browser/ui แล้ว ทำให้นึกว่า use-after-free เกิดขึ้นมากแค่ไหนในข้อมูลที่ข้อได้เปรียบด้านประสิทธิภาพของการจัดการหน่วยความจำด้วยมือไม่ได้สำคัญนัก เช่น [1] เป็นปัญหารอบ ๆ lifecycle ของ dialog “เลือกไฟล์”
    ในภาพรวม สำหรับโค้ดแบบนี้ดูเหมือนจะดีกว่าถ้าใช้ pointer ที่ฉลาดกว่าแต่ช้ากว่าเสมอเพื่อป้องกัน [2] ดูเหมือนว่า type raw_ptr [3] พยายามช่วยในด้านนั้น และบางที crash ใน [2] อาจเป็นกรณีที่การป้องกันทำงานสำเร็จจริงก็ได้
    น่าเสียดายที่ในโปรเจกต์ไม่มีวิธีที่เหมาะนักในการ สลับ dialect ในความหมายที่กว้างขึ้น เช่น “ส่วนนี้เป็นโค้ดที่ performance-critical และได้รับการ review อย่างละเอียด” กับ “ส่วนนี้ไม่ไวต่อ performance และมีสถานะ async เยอะ จึงผิดพลาดได้ง่าย” ผมเคยคิดด้วยซ้ำว่าในกรณีหลังอาจคุ้มค่าที่จะผสมใช้ภาษาอีกภาษาที่มี GC
    หมายเหตุ ผมเคยทำงานกับโค้ดนี้เมื่อนานมาแล้ว และคงไม่แปลกใจถ้าบั๊กเหล่านี้มากกว่า 0 ตัวเป็นฝีมือผม
    [1] https://bugs.chromium.org/p/chromium/issues/detail?id=120103...
    [2] https://bugs.chromium.org/p/chromium/issues/detail?id=132323...
    [3] https://source.chromium.org/chromium/chromium/src/+/main:bas...

    • นั่นก็เหมือนการอธิบาย คีย์เวิร์ด unsafe ของ Rust
      และโค้ดประเภทนี้ก็เป็นหนึ่งในแรงจูงใจดั้งเดิมที่ทำให้ Rust เกิดขึ้นอย่างแท้จริง เพราะเป็นภาษาที่ออกแบบโดยคำนึงถึงการ implement browser ตั้งแต่แรก
    • แนวทางที่ให้ส่วนที่ performance-critical เขียนด้วย C หรือ Rust แล้วส่วนที่เหลือเป็น Python ก็แทบจะเป็นตัวอย่างของเรื่องนี้ ได้ยินมาว่า binding ระหว่าง Rust-Python ดีเป็นพิเศษ และช่วยให้ดูแลความถูกต้องในส่วนที่ performance-critical ได้ง่ายขึ้นด้วย
      ในทางกลับกัน การเรียกภาษา script จากภาษาที่เร็วก็ทำได้เหมือนกัน ทุกวันนี้ทุกคนตื่นเต้นกับ wasm แต่เกมคอมพิวเตอร์ใช้ lua เพื่อจุดประสงค์นั้นมาราว 20 ปีแล้ว เกมน่าจะเป็นหมวดหมู่ซอฟต์แวร์ที่ไวต่อประสิทธิภาพขนาดใหญ่ที่สุด
    • ด้วยเหตุผลเดียวกัน ผมเคยอยากใช้ Oilpan GC ใน browser process แต่ตอนนั้นคนฝั่ง browser ต่อต้านการใช้ไลบรารี blink อย่างหนัก
      โค้ด Chrome UI ส่วนใหญ่อย่างน้อยก็เขียนเป็น Web UI อยู่แล้ว ถ้าเป็นยุคนี้ ผมคิดว่าควรพิจารณา typescript สำหรับงาน orchestration ภายใน browser ให้มากขึ้น เป็นกลยุทธ์ที่ Electron พิสูจน์แล้ว
      แต่แนวโน้มตอนนี้ดูเหมือนจะไปทาง MiraclePtr จริง ๆ
    • raw_ptr จริง ๆ แล้วเป็น smart pointer wrapper ที่ช่วยบรรเทาการ exploit use-after-free ส่วนใหญ่: https://security.googleblog.com/2022/09/use-after-freedom-mi...
  • ผมลองย้ายสิ่งนี้ไปเป็น treemap visualization แล้ว[1]: https://vrp-treemap.surge.sh/
    ไลบรารี treemap สร้างโดย evmar ผู้คร่ำหวอดของ Chrome ซึ่งก็อยู่ในเธรดนี้ด้วย

  • เป็น visualization ที่เนี้ยบมาก แม้ตอนขยายพื้นที่จะใช้ CPU ค่อนข้างเยอะนิดหน่อย แต่ก็อยากให้ทีม Chrome มีอะไรคล้าย ๆ กันภายใน
    กล่าวคือ ดูมีประโยชน์มากจริง ๆ สำหรับการทำความเข้าใจ attack surface

  • ไอเดียดีมากและ implementation ก็ดีด้วย
    มี raw data อยู่ที่ไหนไหม? sunburst หรือ treemap ก็น่าลอง

  • ถ้าสิ่งนี้น่าจะลงไปถึงระดับ diff แล้ว การถ่วงน้ำหนักตามจำนวนบรรทัดโค้ดที่เปลี่ยนน่าจะน่าสนใจ เช่น ถ้าไฟล์ A เปลี่ยน 10 บรรทัด ไฟล์ B เปลี่ยน 1 บรรทัด ก็ถือว่าบั๊กส่วนใหญ่อยู่ในไฟล์ A ดังนั้นไฟล์ A ได้รับส่วนแบ่งเงินรางวัล 10/11 อะไรแบบนั้นหรือเปล่า?
    หรืออาจแบ่งตามจำนวนบรรทัดที่เปลี่ยน / จำนวนบรรทัดทั้งหมดของไฟล์ก็ได้ แบบนั้นจะเห็นได้ว่าแต่ละไฟล์มีบั๊กมากแค่ไหน พร้อมกับ ป้ายจำนวนเงิน

    • ถ้าทำแบบนั้นก็คงได้เอฟเฟกต์ที่ต้องการ โค้ดอย่างเทสต์มีแนวโน้มจะยืดยาวมาก แต่ช่องโหว่จริงมักจบอยู่ที่ ไม่กี่ตัวอักษร
  • ถ้าแสดง ค่าเฉลี่ยเงินรางวัล ต่อไฟล์ในแต่ละ node ด้วยก็น่าจะดี

  • เป็นข้อท้วงติงเล็กน้อย แต่ไฟล์ DEPS, AUTHORS, BUILD.gn น่าจะไม่ควรรวมเข้ามา

  • แล้วเวอร์ชันที่ normalize จำนวนเงินด้วยจำนวนบรรทัดโค้ดล่ะ?

    • สงสัยว่าถามแบบนั้นเพราะอะไร เพราะผมมองว่าในซอฟต์แวร์และความปลอดภัย จำนวนบรรทัดโค้ดเป็นเกณฑ์ที่แทบไม่มีความหมาย
    • หรืออาจ normalize ด้วยจำนวนคำที่ถูกทุ่มให้กับบั๊กก็ได้ ใช้เป็นตัวชี้วัดแทนความซับซ้อนได้