2 पॉइंट द्वारा GN⁺ 2024-05-26 | 1 टिप्पणियां | WhatsApp पर शेयर करें
  • Go का checksum database और public module proxy उन repositories को भी स्वीकार कर सकते हैं जिनमें Go code नहीं है, जिससे मनमाने Git repository data को Go infrastructure में लोड करने और फिर दोबारा डाउनलोड करने का रास्ता बनता है
  • sum.golang.org/lookup/$module@$version request किसी ऐसे module version से मिलती है जो record नहीं हुआ है, तो वह origin server से fetch करती है, और इस प्रक्रिया में proxy.golang.org पर भी उस repository का zip उपलब्ध हो जाता है
  • Homebrew की Ruby repository और Rust repository fork checksum database में मौजूद थे, और प्रयोगों में नए Go modules ही नहीं, बल्कि Go files के बिना repositories भी pseudo-version के रूप में register होने में सफल रहे
  • Module zip पर compressed और uncompressed दोनों के लिए अधिकतम 500 MiB की सीमा है, लेकिन developer machines और CI/CD की download restrictions को bypass करने, payload storage, और C2 implementation के लिए यह आकार काफी बड़ा है
  • sum.golang.org के लगभग 15.9 लाख unique paths में से GitHub paths लगभग 15.1 लाख हैं, यानी करीब 95%; इससे Go ecosystem की GitHub पर निर्भरता और public proxy के दुरुपयोग की संभावना दोनों सामने आती हैं

Go checksum database में मिली non-Go repositories

  • Go के checksum database को देखते समय modules table में github.com/homebrew/homebrew-core बहुत बड़ी संख्या में दिखाई दिया
    • github.com/homebrew/homebrew-core: 39,438
    • github.com/Homebrew/homebrew-core: 30,896
    • github.com/concourse/concourse: 25,372
    • github.com/openshift/release: 24,065
    • github.com/cilium/cilium: 22,138
  • Homebrew repository को Ruby इस्तेमाल करने के लिए जाना जाता है, और repository तथा cloned files में भी go.mod या Go source files नहीं मिलीं
  • Uppercase/lowercase का अंतर Go documentation के case encoding rules से समझाया जाता है
    • Uppercase letters को ! और संबंधित lowercase letter के रूप में encode किया जाता है, ताकि case-insensitive file systems पर भी example.com/M और example.com/m को साथ में store किया जा सके
  • github.com/Edu4rdSHL/rust-headless-chrome भी Go से असंबंधित Rust repository fork है, फिर भी checksum database में दिखाई देता है

/lookup repositories को कैसे fetch करता है

  • Go modules documentation के Go Modules Reference के अनुसार, Go command checksum database query करते समय पहले /lookup endpoint से record data लाती है
  • अगर module version अभी log में record नहीं हुआ है, तो checksum database response देने से पहले origin server से उस module को fetch करने की कोशिश करता है
  • Endpoint format $base/lookup/$module@$version है
    • यह $module के $version के लिए log record number, go.sum lines, और signed tree description लौटाता है
  • github.com/homebrew/homebrew-core के pseudo-version को query करने पर checksum record और go.mod hash लौटता है
  • अगर repository में version tags नहीं हैं, तो Go के pseudo-version rules इस्तेमाल होते हैं

नया Go module register करने का प्रयोग

  • नया Go module github.com/gdbinit/fluxmatter बनाने के बाद lookup request से registration status जांचा गया
  • @latest query ने canonical version न होने की error लौटाई
    • bad request: version "latest" is not canonical
  • @v0.0.0 query ने उस revision को न जानने की error लौटाई
    • not found: ... invalid version: unknown revision v0.0.0
  • लेकिन checksum database को फिर से sync कर query करने पर module register हो चुका था
    • github.com/gdbinit/fluxmatter|v0.0.0-20240524163826-a7e64ffd69f2|2024-05-24T16:40:51.203837Z
  • proxy.golang.org/github.com/gdbinit/fluxmatter/@latest ने pseudo-version और GitHub origin info लौटाई, और उस version की zip file download और compression verification भी संभव थी
  • Initial seeding के लिए exact version specify करना जरूरी नहीं था; module path और version जैसा दिखने वाला value रखने वाली सिर्फ lookup query से ही यह काम कर गया

Go code के बिना repositories भी public proxy पर load हो जाती हैं

  • बिल्कुल Go code न रखने वाली github.com/gdbinit/readmem repository के साथ भी वही प्रयोग सफल रहा
  • lookup request ने v0.0.0 revision को न जानने की error लौटाई, लेकिन checksum database में यह pseudo-version के रूप में register हो गई
    • github.com/gdbinit/readmem|v0.0.0-20131006075740-407cb0a56933|2024-05-24T16:45:35.88456Z
  • proxy.golang.org के @latest ने उस repository का pseudo-version और Git origin info लौटाया
  • Download की गई zip में Go files नहीं थीं, बल्कि Entitlements.plist, README, Xcode project files, main.c आदि थे
  • इस प्रयोग में GitHub repository का इस्तेमाल किया गया, लेकिन कोई working VCS हो तो अन्य hosting sites पर भी यह संभव हो सकता है

GitHub पर निर्भरता और size limits

  • Checksum database में unique paths की संख्या 1,591,375 थी, और उनमें से github.com% paths 1,515,957 थे
  • Unique paths में से लगभग 95% GitHub पर hosted हैं {p:95}
  • यह आंकड़ा raw statistics है, जिसमें forks या वास्तविक Go code न रखने वाले targets को हटाया नहीं गया है
  • Go module zip पर File path and size constraints लागू होते हैं
    • module zip file अधिकतम 500 MiB
    • files का कुल uncompressed size भी अधिकतम 500 MiB
    • go.mod file अधिकतम 16 MiB
    • LICENSE file भी अधिकतम 16 MiB
  • यह limit users, proxy, और module ecosystem के अन्य हिस्सों पर denial-of-service attacks को कम करने की व्यवस्था है
  • दुरुपयोग की संभावना को देखते हुए 500 MiB काफी बड़ा size है

संभावित दुरुपयोग scenarios

  • Public Go proxy का इस्तेमाल developer machines या CI/CD servers पर destination download restrictions को bypass करने के लिए किया जा सकता है
    • यह मानते हुए कि private GOPROXY नहीं है
    • Malware payload को repository में upload कर सकता है और जरूरत पड़ने पर proxy से download कर सकता है
    • Original source गायब हो जाने पर भी checksum database entry में सिर्फ छोटा-सा trace बच सकता है
  • proxy.golang.org पर DoS करना मुश्किल हो सकता है
    • मनमानी Git repository को proxy से download करवाने के लिए request किया जा सकता है
    • संभावित attack तरीका यह हो सकता है कि बहुत सारे GitHub URLs collect कर lookup API पर बड़ी संख्या में requests भेजी जाएं
    • Server implementation ज्ञात नहीं है, लेकिन work queue जैसी parallel processing limits हो सकती हैं
    • GitHub-side bandwidth protection भी काम कर सकती है
    • Storage space को target करने वाला DoS भी संभव हो सकता है, लेकिन यह केवल अनुमान है
  • C2(command and control) को proxy.golang.org के ऊपर आसानी से बनाया जा सकता है
    • @latest query से किसी specific module का latest version पाया जा सकता है
    • Payload एक simple file हो सकता है, या go.mod या Go source file के अंदर छिपाया जा सकता है
    • Single repository के इस्तेमाल से बचने के लिए module DGA इस्तेमाल किया जा सकता है

C2 download flow

  • Implant को command प्राप्त करनी हो तो वह ये steps कर सकता है
  • यह flow इतना simple है कि Go code की 300 lines से कम में भी implement किया जा सकता है

निष्कर्ष और बाकी सवाल

  • Go checksum database और proxy documented procedure के अनुसार unrecorded modules को origin server से fetch कर store कर सकते हैं
  • मौजूदा स्थिति Go infrastructure की गंभीर समस्या जैसी नहीं दिखती, लेकिन इसका दुरुपयोग आसानी से हो सकता है और improvement की गुंजाइश है
  • Go code न रखने वाली repositories को proxy और checksum database पर upload होने देने के पीछे कोई documented reason या private reason हो सकता है
  • यह जांचने के लिए कि क्या कोई पहले से इसका दुरुपयोग कर रहा है, लगभग 16 लाख unique repositories और latest local database के आधार पर करीब 2.2 करोड़ entries की जांच करनी होगी
  • कुछ valid non-Go projects database में क्यों हैं, यह अभी भी एक खुला सवाल है

1 टिप्पणियां

 
GN⁺ 2024-05-26
Hacker News रायें
  • कोई भी online service जहाँ users material upload करते हैं और वह material public दिखता है, अंततः command-and-control, copyright infringement और CSAM hosting के लिए इस्तेमाल होने लगती है
    file hosting के अलावा भी महत्वपूर्ण उपयोग होने की वजह से जिन services को block करना मुश्किल होता है, उनके साथ यह खास तौर पर होता है; Twitter[1], Telegram[2], PGP key infrastructure[3] में यह पहले ही हो चुका है, और GitHub जैसे obvious targets की तो बात ही क्या
    [1] https://pentestlab.blog/2017/09/26/command-and-control-twitt...
    [2] https://www.blazeinfosec.com/post/leveraging-telegram-as-a-c...
    [3] https://torrentfreak.com/openpgp-keyservers-now-store-irremo...

    • Gmail, Google Groups, Google Drive, Gchat के साथ भी ऐसा ही था, और stored data का public होना भी जरूरी नहीं था
      Gmail के मामले में credentials distribute कराके login करवाया गया, फिर IMAP से upload किए गए attachments पढ़वाए गए
      मैं पूर्व Google SAD-SRE (Spam, Abuse, Delivery) था
    • PyPI में भी packages में मनमानी non-Python files डाली जा सकती हैं, इसलिए यह ऐसे उपयोग के लिए आसान दिखता है
      Python code string के अंदर file को Base64 में encode करके डालना भी संभव है
    • पता नहीं यह पहले से हुआ है या नहीं, लेकिन एक कम obvious target HuggingFace लगता है
  • मैं Googler हूँ और यह मेरी निजी राय है; इस field को अच्छी तरह नहीं जानता
    उम्मीद है कि Go team ने GCP और Drive वालों के साथ collaborate किया होगा, क्योंकि malicious file hosting एक ऐसी समस्या है जिससे Google हमेशा निपटता रहता है
    यह उन दूसरे endpoints से बहुत अलग नहीं है जहाँ Google पहले से लोगों को arbitrary data डालने देता है

    • मैं पूर्व Googler हूँ और Go Dev Tools team को अच्छी तरह नहीं जानता, लेकिन जिन बड़ी companies में मैंने काम किया है या करीबी दोस्तों से सुना है, उनमें Google इस तरह के internal collaboration में शायद सबसे बेहतर है
      Google central team के जरिए infrastructure manage करने और उसे पूरी company में share करने में बहुत सक्षम है। बस messenger apps को छोड़ दें तो; और यह पूरी तरह अनुमान है, लेकिन Go team शायद internal blob storage इस्तेमाल कर रही होगी और abuse response तथा file scanning को automatic handle करने वाली internal infra team भी होगी
  • PyPI पर non-Python projects भी काफी हैं
    Python में users library code compile नहीं कर सकते, इसलिए compiled binary वाले wheel distribute करने की क्षमता चाहिए
    ऐसा code अक्सर C में लिखा जाता है, लेकिन Golang[1] भी संभव है, और उदाहरण तो नहीं मिला पर लगता है मैंने इसे libraries के बजाय applications distribute करने में भी इस्तेमाल होते देखा है
    C में app लिखकर PyPI पर upload करना और users से pip install से install करने को कहना काफी cool है
    [1] https://github.com/popatam/gopy_build_wheel_example

    • मान लें Python usage requirement भी जोड़ दी जाए, तब भी कोई malicious तरीके से comply करना चाहे तो उसे बस minimal Python stub code देना होगा, है न
      यह ऐसा हुआ जैसे Linux हो और ls Python में लिखा गया हो; ऐसे खेल में न पड़ना ही बेहतर लगता है
    • जब तक pip package download करने के लिए venv/virtualenv/pipenv/pyenv जैसे environment के अंदर होना जरूरी नहीं करता था, तब यह use case कहीं ज्यादा उपयोगी रहा होगा
    • pip install cmake भी है, और proprietary binaries भी pip install nvidia-cudnn-cu12 की तरह संभव हैं
    • हाल में PyPI को FFmpeg और Eigen जैसे non-Python tools के लिए बहुत इस्तेमाल कर रहा हूँ
      इसी वजह से मैं Homebrew को पूरी तरह छोड़ पाया
  • हो सकता है यह भोली सोच हो, लेकिन समझ नहीं आता कि यह GitHub repository में files upload करने से कैसे अलग है
    क्या फर्क बस इतना है कि GitHub में account बनाना पड़ता है? GitHub पर भी arbitrary data store किया जा सकता है, और 500MB limit भी नहीं है

    • GitHub anonymous requests पर काफी सख्त request limits लगाता है
  • CUE का module system आखिरकार release हो रहा है, और MVS Go जैसा है लेकिन OCI infrastructure के ऊपर बनाया गया है
    dependency management systems में रुचि हो तो ये links देखें
    proposal: https://github.com/cue-lang/proposal/tree/main/designs/modul...
    custom registry: https://cuelang.org/docs/tutorial/working-with-a-custom-modu...
    road map: https://github.com/orgs/cue-lang/projects/10/views/8
    0.9.0-alpha-5 से modules default रूप से enabled हैं: https://github.com/cue-lang/cue/releases/tag/v0.9.0-alpha.5
    Go Sum में Trillian project transparency log को underpin करता है: https://github.com/google/trillian
    CUE की योजना attestation जैसे OCI options पर सवार होने की है

    • समझ नहीं आता कि इसका linked article से क्या संबंध है
  • golang proxy और sumdb का सहारा लेकर—यानी उनका दुरुपयोग करके—मनमाने URL के checksum के लिए मुफ्त transparency log बनाने के विचार से थोड़ा खेलकर देखा
    https://getsum.pub/

  • हो सकता है मैं ही बेवकूफ हूँ, लेकिन मुझे समझ नहीं आ रहा कि यहाँ ठीक-ठीक समस्या क्या है
    proxy का non-Go repositories को cache करना थोड़ा wasteful हो सकता है, लेकिन ऐसा न भी करे तो क्या Go repositories को cache करवाकर वैसे भी arbitrary data store नहीं करवाया जा सकता?
    अगर मैं कुछ miss नहीं कर रहा, तो यह पूरी तरह कोई बड़ी बात नहीं लगती

    • लगता है आपने कुछ miss नहीं किया
      यहाँ नई बात बस इतनी दिखती है कि बिना security वाला public proxy, proxy करने के लिए चीज़ें स्वीकार करता है और उन्हें बिना security के तरीके से publicly serve करता है
      लेख में कहा गया है कि कुछ monitored networks arbitrary web URLs की तुलना में golang proxy URLs पर ज़्यादा भरोसा कर सकते हैं, इसलिए इसे reputation filters bypass करने वगैरह में इस्तेमाल किया जा सकता है, लेकिन ऐसे तरीके पहले से कई हैं और यह तरीका खास नहीं लगता
  • विषय से थोड़ा हटकर, domain देखकर pun अशुभ लगा तो put.as चेक किया, और वह काफी हद तक वही निकला जिसकी उम्मीद थी

    • https://put.as/ थोड़ा NSFW है
    • काम पर उसे खोलने की गलती कर दी
    • यह Spanish plural word भी है। लेकिन…
  • यह पहले से ज्ञात issue है: https://github.com/golang/go/issues/31866

    • वह fix accidental गलती रोकने में मदद करेगा, लेकिन जो जानबूझकर करना चाहता है, वह root में .mod और .go files जोड़ दे तो काफी नहीं होगा?
    • Marwan का इस issue में होना बिल्कुल हैरानी की बात नहीं है
      उन्होंने और Aaron ने Athens बनाया था, और जहाँ तक मुझे पता है Marwan ने ही वह पहला Go download protocol implementation लिखा था जिस पर Athens आधारित था
      इस issue को रोचक बनाने वाली बात यह है कि Athens पहले से ही module verification की preliminary check के रूप में बताए गए go mod download -json command का इस्तेमाल करता है
      कुल मिलाकर, अगर repository Go module commands द्वारा समझे जाने वाले module के रूप में pass हो जाए, तो Athens उसे serve करता है
      ज़्यादा forbidden शब्दों में कहें तो, आपको module version, pseudo-version और +incompatible बना सकना चाहिए, और उस module व उसकी dependencies को valid checksum बनाना चाहिए
      module checksum फिलहाल .mod और सभी files, तथा हर dependency को recursively शामिल करने से जुड़ा है
      इसलिए लेखक ने जैसा कहा, design के हिसाब से basic Go program भर हो तो arbitrary files के लिए काफी जगह मिल सकती है
  • W3C ने web पर हर चीज़ को मजबूती से cache किए जा सकने की बुनियाद रखी, फिर भी general-purpose proxy caches इतने कम हैं, यह अजीब है
    क्या publishers बिना ज़रूरत छोटे Cache-Control: max-age या Vary: Cookie responses भेज रहे हैं?
    क्या ISPs peering की तुलना में transit costs पर बहुत ज़्यादा खर्च कर रहे हैं?

    • आम तौर पर यह guarantee करने का तरीका नहीं होता कि cache ने content में छेड़छाड़ नहीं की
      उदाहरण के लिए, non-HTTPS sites पर ISP proxy ads inject कर सकता है
      software downloads में आम तौर पर signatures और checksums होते हैं, लेकिन arbitrary content में ऐसा बहुत कम होता है