- Entropy เป็นเครื่องมือ CLI ที่สแกนหา บรรทัดที่มีเอนโทรปีสูง ในโค้ดเบสขนาดใหญ่ เพื่อค้นหาสตริงที่ดูเหมือนค่า secret
- บรรทัดที่มีเอนโทรปีสูงจะถูกมองว่าเป็นสิ่งที่ มีโอกาสเป็น secret สูง และเน้นใช้งานเพื่อค้นหาค่า secret ที่รั่วไหลอยู่ในโค้ดเบส
- รองรับการติดตั้งและการใช้งานผ่าน การติดตั้งจากซอร์สด้วย Go,
go run, Homebrew และ Docker
- สามารถใช้ตัวเลือก
-top, -ext, -ignore-ext เพื่อกำหนดจำนวนผลลัพธ์ นามสกุลไฟล์ที่จะรวม และนามสกุลไฟล์ที่จะยกเว้น
- เมื่อรันผ่าน Docker ต้องเมานต์ไดเรกทอรีปัจจุบันไปที่
/data และใส่ /data ไว้ท้ายคำสั่งเพื่อให้สแกนไฟล์ระบบภายในเครื่อง
Entropy ทำอะไร
- Entropy เป็นเครื่องมือ CLI ที่สแกนโค้ดเบสเพื่อค้นหา บรรทัดที่มีเอนโทรปีสูง
- บรรทัดที่มีเอนโทรปีสูงมักเป็นค่า secret จึงช่วยในการค้นหา การรั่วไหลของ secret ภายในโค้ดเบส
วิธีติดตั้งและการรัน
-
ติดตั้งด้วย Go
- วิธีติดตั้งที่แนะนำคือการติดตั้งจากซอร์สด้วย Go
- หลังติดตั้งแล้วให้รันด้วยคำสั่ง
entropy
go install github.com/EwenQuim/entropy@latest
entropy
- มีวิธีรันแบบคำสั่งบรรทัดเดียวให้ใช้งานด้วย
go run github.com/EwenQuim/entropy@latest
-
ติดตั้งด้วย Homebrew
- คำสั่งติดตั้งด้วย Homebrew มีดังนี้
brew install ewenquim/repo/entropy
entropy
-
รันด้วย Docker
- การรันด้วย Docker ใช้วิธีเมานต์ไดเรกทอรีปัจจุบันไปที่
/data ของคอนเทนเนอร์
docker run --rm -v $(pwd):/data ewenquim/entropy /data
ตัวอย่างตัวเลือกหลัก
-h: ดูตัวเลือกที่ใช้งานได้
entropy -h
-top: กำหนดจำนวนผลลัพธ์อันดับต้น ๆ ที่จะแสดง
-ext: กำหนดนามสกุลไฟล์ที่จะสแกน
entropy -top 20 -ext go,py,js
-ignore-ext: กำหนดนามสกุลไฟล์ที่จะยกเว้น
- สามารถส่งทั้งไฟล์และโฟลเดอร์เป็นอาร์กิวเมนต์ร่วมกันได้
entropy -top 5 -ignore-ext min.js,pdf,png,jpg,jpeg,zip,mp4,gif my-folder my-file1 my-file2
ข้อควรระวังเมื่อใช้ Docker
- ตัวเลือก
-v ของ Docker ใช้สำหรับเมานต์ไดเรกทอรีปัจจุบันเข้าไปในคอนเทนเนอร์
/data คือไดเรกทอรีเริ่มต้นที่เครื่องมือใช้ค้นหาไฟล์
- หาก ไม่เพิ่ม
/data ไว้ท้ายคำสั่ง เครื่องมือจะค้นหาภายในคอนเทนเนอร์แทนไฟล์ระบบในเครื่อง
docker run --rm -v $(pwd):/data ewenquim/entropy -top 20 -ext go,py,js /data
docker run --rm -v $(pwd):/data ewenquim/entropy -top 5 /data/my-folder /data/my-file
1 ความคิดเห็น
ความคิดเห็นจาก Hacker News
น่าสนใจ ถ้าเป็นผมคงทำประมาณนี้โดยอาศัยหลักว่า entropy สูงจะบีบอัดได้ไม่ดี
perl -lne 'next unless $_; $z = qx(echo "$_" | gzip | wc -c); printf "%5.2f %s\n", $z/length($_), $_'แต่แนวทางนี้ใช้แต่ละบรรทัดเหมือนเป็นพจนานุกรม ไม่ใช่ทั้งไฟล์ ดังนั้นบรรทัดที่สั้นมากจะบีบอัดได้ไม่ดีและทำให้มีปัญหาเล็กน้อย
มันจับบรรทัดอย่าง
return map { $_ > 1 ? 1 : ($_ < 0 ? 0 : $_) } @vs;ได้ ซึ่งแม้จะเป็นโค้ดที่ถูกต้อง แต่ก็ดูเหมือนมี entropy ค่อนข้างสูงจริง ๆในทางกลับกัน ถ้าเติมคอมเมนต์ภาษาอังกฤษธรรมชาติเข้าไป ก็หลอกไม่ให้ตรวจพบบรรทัดที่มี entropy สูงได้
ตอนนี้กำลังเดินทางเลยยังดูละเอียดไม่ได้ แต่ถ้าเอาคำสั่ง Perl นี้มาเทียบกับเครื่องมือนี้น่าจะสนุก ข้อดีของคำสั่ง Perl คือมันรันได้ทันทีบนเครื่องแทบทุกเครื่องที่ไม่ใช่ Windows ดังนั้นไม่จำเป็นต้องทรงพลังมากก็อาจถูกนำไปใช้ได้
พร้อมกับล้อ Go และโปรแกรมกระท่อนกระแท่นของผมไม่หยุด และแม้ไม่ได้ตั้งใจ วันนั้นผมก็ได้เรียน Ruby ไปเยอะเหมือนกัน
จะเอาไฟล์โค้ดทั้งหมดมาต่อกันแล้วทดสอบทีละบรรทัดทั้ง repository ก็ได้ แต่คงช้าเกินไป
xz หรือ zstd อาจเป็นตัวเลือกที่ดีกว่า และถ้ามองว่าอัตราการบีบอัดที่ดีที่สุดคือการประมาณ entropy ที่ดีกว่า ก็อาจดูผลงานที่ชนะ Hutter Prize [1] ได้
[1] http://prize.hutter1.net/
แน่นอนว่าตอนแตกไฟล์ก็คงต้องส่งพจนานุกรมนั้นเป็นอินพุตแยกต่างหากด้วย
ปัญหานี้ก้าวข้ามได้ด้วยการตั้งรหัสผ่านฐานข้อมูลทั้งหมดเป็น
abcd"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890"ว่าเป็น บรรทัดที่มี entropy สูงรหัสผ่าน: postgres
"correct horse battery staple"คงมี entropy ต่ำ เพราะเป็นแค่สตริงของคำที่ดูธรรมดาสงสัยว่ามีบทความดี ๆ ที่พูดถึง วิธีใช้ entropy กับงานแบบนี้ ไหม ผมสงสัยมานานว่าคนเขาใช้กันจริง ๆ อย่างไร และมันได้ผลไหม แต่ยังไม่เคยลงไปขุดเอง
ก่อนอื่น การนิยาม “entropy” ของข้อความก็ดูคลุมเครือแล้ว ที่นี่ใช้แบบง่าย ๆ ประมาณ
-Sum(x log(x))โดยx = countOccurences(char) / len(text)ซึ่งทำให้เกิดคำถามหลายอย่างว่าจริง ๆ แล้วมันทำงานได้ดีแค่ไหนสตริงต้องยาวแค่ไหน? ภาษาธรรมชาติมี entropy ที่เกือบคงที่ไหม? มีวิธีที่ดีกว่านี้หรือเปล่า?
ตัวอย่างเช่น
"vorpal"ควรมี entropy ต่ำกว่า"hJ6&:a"อย่าง “ชัดเจน” ตัวหลังดูเหมือนใช้ชุดอักขระที่ใหญ่กว่าภาษาธรรมชาติมาก และแม้จะไม่ใช่แบบนั้น ลำดับอักขระก็สำคัญ เพราะตัวแรกฟังดูเหมือนคำจริง ถึงจะเป็นคำที่ Carroll สร้างขึ้นก็ตามแต่ “entropy” ที่ทุกคนใช้กันนี้ไม่รู้เรื่องพวกนั้นเลย ทั้งสองคงมี “entropy” เท่ากันเป๊ะ
มันอาจทำงานได้ดีพอสำหรับเครื่องมือค้นหารหัสผ่านบน GitHub อีกตัวหนึ่ง แต่ผมสงสัยว่ามีอะไรที่ดีกว่านี้ไหม มีมาตรวัดที่วัดความสุ่มของข้อความได้อย่างมีความหมายมากกว่านี้หรือเปล่า?
โปรเจกต์แบบนี้มีเป็นสิบ ๆ และทุกคนใช้ “entropy” เหมือนเป็นเรื่องแน่นอน แต่ผมไม่เคยเห็นงานวิจัยจริงจังในหัวข้อนี้เลย
บางอย่างอาจดูซับซ้อนใน encoding หนึ่ง แต่มี entropy ต่ำใน encoding ที่ถูกต้อง
ถ้าจะตัดสิน entropy ของสัญญาณให้แม่นยำ ต้องรู้ฐานที่ถูกต้อง หรืออนุมานจากบริบท
ถ้าจะทำให้เครื่องมือในบทความต้นทางแข็งแรงขึ้น วิธีที่ดีคือเตรียมพจนานุกรมที่คำนวณไว้ล่วงหน้าสำหรับช่วงข้อความทั่วไป เช่น source code หรือภาษาธรรมชาติ แล้วใช้แต่ละพจนานุกรม encode สตริงเพื่อเปรียบเทียบ ความสามารถในการบีบอัด
สตริงที่มี entropy สูงอย่างค่าลับจะบีบอัดได้ไม่ดีด้วยพจนานุกรมทุกชุดที่มี
เหตุผลที่เราแยกข้อมูลที่ไม่สุ่มออกจากข้อมูลสุ่มได้ คือในบรรดาสถานะทั้งหมดที่เป็นไปได้ มีเพียงสับเซตเล็ก ๆ เท่านั้นที่มนุษย์ถือว่ามีประโยชน์ และเราพอรู้ว่าสับเซตนั้นมีลักษณะอย่างไร จึงพอประเมินได้ว่าสตริงหนึ่ง ๆ ถูกสร้างขึ้นจากกระบวนการแบบไหน
แน่นอนว่าการทดสอบเชิงสถิติอย่าง https://en.wikipedia.org/wiki/Diehard_tests ดีพอจะแยกข้อมูล entropy ต่ำกับ entropy สูงได้ แต่เครื่องสร้างเลขสุ่มเทียมสมัยนี้ไม่มีปัญหาในการผ่านการทดสอบเหล่านี้ทั้งหมด แม้ “entropy” จริง ๆ จะมีแค่ค่า seed กับความซับซ้อนของอัลกอริทึมก็ตาม
เครื่องมือที่น่าดูประกอบกัน:
trufflehog: https://github.com/trufflesecurity/trufflehog
detect-secrets: https://github.com/Yelp/detect-secrets
semgrep secrets: https://semgrep.dev/products/semgrep-secrets -- เป็นแบบเสียเงิน แต่บางกรณีอาจรวมอยู่ในไลเซนส์ที่มีอยู่แล้ว
ผมมองว่าโซลูชันเหล่านี้ดีกว่ามากในการค้นหาค่าลับ เมื่อเทียบกับแนวทางง่ายๆ ที่อิงเอนโทรปี
จริงอยู่ที่เอนโทรปีมีความทั่วไปมากกว่า แต่เครื่องมือเหล่านี้ก็ลงตัวดีแล้ว และผ่านการพิสูจน์กับชุดข้อมูลจำนวนมากจริงๆ
เมื่อหลายปีก่อน DrJones เคยช่วยไว้ ด้วยการถามว่า สตริงที่มีเอนโทรปีสูง คืออะไร[0] และลิงก์บทความดีๆ ที่เกี่ยวข้อง[1] ให้
[0] https://news.ycombinator.com/item?id=13304641
[1] https://www.splunk.com/en_us/blog/security/random-words-on-e...
นึกถึงโปรแกรม ent ที่ใช้กันมานาน
https://fourmilab.ch/random/
ถ้าสแกนไปถึง ประวัติ git ทั้งหมดของโปรเจกต์ได้ก็น่าจะมีประโยชน์ แม้ค่าลับจะเคยถูก commit แล้วถูกลบออกภายหลัง แต่มันก็ยังอาจหลงเหลืออยู่ในประวัติได้
ไม่เข้าใจว่าทำไมต้องติดตั้ง Go เพื่อรันเครื่องมือนี้ จุดเด่นอย่างหนึ่งของ Go คือผู้พัฒนาสามารถแจกจ่าย ไบนารีเดี่ยว ที่ใช้งานได้เลยไม่ใช่หรือ?
มีแผนจะทำ Docker image ด้วย
พูดตรงๆ คือไม่คิดว่าจะได้รับความนิยมขนาดนี้ ดังนั้น repository ยังไม่ได้อยู่ในสภาพพร้อม 100%
โมเดลภาษา อย่าง Llama 3 น่าจะสามารถโมเดลระดับความน่าประหลาดใจราย token เพื่อค้นหาบริเวณที่น่าประหลาดใจที่สุด หรือก็คือบริเวณที่มีเอนโทรปีสูงที่สุดได้
อย่างในตัวอย่างหนึ่ง ตัวอักษรทั้งชุดอาจมีเอนโทรปีสูงในบางมุมมอง แต่สำหรับโมเดลภาษาที่คุ้นเคยกับโค้ด การมี alphabet แบบ Base62 เป็นค่าคงที่ใน codebase น่าจะไม่ใช่เรื่องน่าประหลาดใจเลย