वहां कई हैं विभिन्न प्रकार की कमजोरियां यह आपके वेब एप्लिकेशन के लिए CORS की स्थापना करते समय हो सकता है, और होममेड CORS कार्यान्वयन में CORS फ्रेमवर्क और लॉजिक त्रुटियों का असुरक्षित उपयोग गंभीर सुरक्षा कमजोरियों को जन्म दे सकता है जो हमलावरों को प्रमाणीकरण को बायपास करने की अनुमति देते हैं। क्या अधिक है, हमलावर इंट्रानेट पर सेवाओं तक पहुंचने के लिए वेब अनुप्रयोगों में अन्य मौजूदा कमजोरियों की गंभीरता को बढ़ाने के लिए CORS MisConfigurations का उपयोग कर सकते हैं।

ब्राउज़र में दो वेबसाइटों के बीच संचार दिखाने वाला एक CORS आरेख।

इस ब्लॉग पोस्ट में, मैं दिखाऊंगा कि कैसे डेवलपर्स और सुरक्षा शोधकर्ता अपने स्वयं के पुस्तकालयों को मॉडल करने के लिए Codeql का उपयोग कर सकते हैं, जो मैंने एक उदाहरण के रूप में CORS फ्रेमवर्क पर किए हैं। चूंकि मैंने जिन तकनीकों का उपयोग किया था, वे अन्य फ्रेमवर्क के मॉडलिंग के लिए उपयोगी हैं, यह ब्लॉग पोस्ट आपको मॉडल बनाने और आपकी अपनी परियोजनाओं में कमजोरियों को खोजने में मदद कर सकता है। क्योंकि CODEQL जैसे स्टेटिक एनालाइजर में संरचनाओं, कार्यों और आयातित पुस्तकालयों के बारे में विस्तृत जानकारी प्राप्त करने की क्षमता है, वे GREP जैसे सरल उपकरणों की तुलना में अधिक बहुमुखी हैं। इसके अलावा, चूंकि CORS फ्रेमवर्क अक्सर विशिष्ट संरचनाओं और कार्यों के माध्यम से सेट कॉन्फ़िगरेशन का उपयोग करते हैं, CodeQL का उपयोग करना आपके कोडबेस में गलतफहमी खोजने का सबसे आसान तरीका है।

CodeQL में कोड जोड़ते समय, यह हमेशा संबंधित प्रश्नों और फ्रेमवर्क की जांच करना सबसे अच्छा अभ्यास है जो पहले से ही उपलब्ध हैं ताकि हम पहिया को फिर से नहीं कर रहे हों। अधिकांश भाषाओं के लिए, CodeQL में पहले से ही एक CORS क्वेरी है जो कई डिफ़ॉल्ट मामलों को कवर करती है। CORS को लागू करने का सबसे आसान और सरल तरीका मैन्युअल रूप से सेट करके है Access-Control-Allow-Origin और Access-Control-Allow-Credentials प्रतिक्रिया शीर्षकों। किसी भाषा (जैसे, Django, Fastapi, और flask) के लिए फ्रेमवर्क को मॉडलिंग करके, CodeQL पहचान सकता है कि कोड में उन हेडर को कहां सेट किया गया है। विशिष्ट हेडर मूल्यों की तलाश में उन मॉडलों पर निर्माण, CodeQL CORS के सरल उदाहरण पा सकता है और देखें कि क्या वे कमजोर मूल्यों से मेल खाते हैं।

निम्नलिखित GO उदाहरण में, सर्वरों पर अनौपचारिक संसाधनों को मनमानी वेबसाइटों द्वारा एक्सेस किया जा सकता है।

func saveHandler(w http.ResponseWriter, r *http.Request) { 
    w.Header().Set("Access-Control-Allow-Origin", "*") 
}

यह उन वेब अनुप्रयोगों के लिए परेशानी भरा हो सकता है जिनमें प्रमाणीकरण नहीं होता है, जैसे कि स्थानीय स्तर पर होस्ट किए जाने वाले उपकरण, क्योंकि किसी भी खतरनाक समापन बिंदु को एक हमलावर द्वारा एक्सेस और शोषण किया जा सकता है।

यह GO HTTP फ्रेमवर्क का एक स्निपेट है जहां Codeql मॉडल Set इस ढांचे के लिए सुरक्षा से संबंधित हेडर खोजने की विधि। हेडर राइट्स द्वारा मॉडलिंग की जाती है HeaderWrite में क्लास करना HTTP.qllजो सभी हेडर राइट्स को खोजने के लिए अन्य मॉड्यूल और कक्षाओं द्वारा बढ़ाया जाता है।

 /** Provides a class for modeling new HTTP header-write APIs. */
  module HeaderWrite {
    /**
     * A data-flow node that represents a write to an HTTP header.
     *
     * Extend this class to model new APIs. If you want to refine existing API models,
     * extend `HTTP::HeaderWrite` instead.
     */
    abstract class Range extends DataFlow::ExprNode {
      /** Gets the (lower-case) name of a header set by this definition. */
      string getHeaderName() { result = this.getName().getStringValue().toLowerCase() }

कुछ उपयोगी तरीके जैसे getHeaderName और getHeaderValue हेडर से संबंधित सुरक्षा प्रश्नों को विकसित करने में भी मदद कर सकते हैं, जैसे कि CORS MISCONFIGURATION। पिछले कोड उदाहरण के विपरीत, नीचे का पैटर्न एक कोर्स मिसकॉन्फ़िगरेशन का एक उदाहरण है जिसका प्रभाव बहुत अधिक प्रभावशाली है।

func saveHandler(w http.ResponseWriter, r *http.Request) { 
    w.Header().Set("Access-Control-Allow-Origin", 
    r.Header.Get("Origin"))
    w.Header().Set("Access-Control-Allow-Credentials", 
    "true") 
}

अनुरोध मूल हेडर को दर्शाते हुए और क्रेडेंशियल्स को अनुमति देने से उपयोगकर्ता में वर्तमान लॉग इन के रूप में अनुरोध करने के लिए एक हमलावर वेबसाइट की अनुमति मिलती है, जो पूरे वेब एप्लिकेशन से समझौता कर सकता है।

CodeQL का उपयोग करते हुए, हम हेडर को मॉडल कर सकते हैं, विशिष्ट हेडर और तरीकों की तलाश कर सकते हैं ताकि CODQL को CORS कमजोरियों को खोजने के लिए प्रासंगिक सुरक्षा कोड संरचनाओं की पहचान करने में मदद मिल सके।

/**
 * An `Access-Control-Allow-Credentials` header write.
 */
class AllowCredentialsHeaderWrite extends Http::HeaderWrite {
    AllowCredentialsHeaderWrite() {
        this.getHeaderName() = headerAllowCredentials()
    }
}

/**
 * predicate for CORS query.
 */
predicate allowCredentialsIsSetToTrue(DataFlow::ExprNode allowOriginHW) {
        exists(AllowCredentialsHeaderWrite allowCredentialsHW |
                allowCredentialsHW.getHeaderValue().toLowerCase() = "true"

यहाँ, HTTP::HeaderWrite क्लास, जैसा कि पहले चर्चा की गई थी, के लिए एक सुपरक्लास के रूप में उपयोग किया जाता है AllowCredentialsHeaderWriteजो सभी हेडर को मूल्य का लिखता है Access-Control-Allow-Credentials। फिर, जब हमारे CORS MISCONFIGURATION क्वेरी की जाँच करता है जब क्रेडेंशियल्स सक्षम होते हैं, तो हम AllowCredentialSheaderWrite का उपयोग करने के लिए संभावित स्रोतों में से एक के रूप में उपयोग करते हैं।

डेवलपर्स के लिए CORS नीति सेट करने का सबसे सरल तरीका उनके सर्वर में HTTP प्रतिक्रियाओं पर हेडर सेट करना है। सभी उदाहरणों को मॉडलिंग करके जहां एक हेडर सेट किया गया है, हम अपने CORS क्वेरी में इन CORS मामलों की जांच कर सकते हैं।

जब वेबक्यूएल का उपयोग करके वेब फ्रेमवर्क मॉडलिंग करते हैं, तो ऐसी कक्षाएं बनाती हैं जो अधिक जेनेरिक सुपरक्लास का विस्तार करती हैं HTTP::HeaderWrite मॉडल के प्रभाव को सभी CODEQL सुरक्षा प्रश्नों में उपयोग करने की अनुमति देता है जो उनकी आवश्यकता है। चूंकि वेब एप्लिकेशन में हेडर इतने महत्वपूर्ण हो सकते हैं, इसलिए उन सभी तरीकों को मॉडल करना जो उन्हें एक फ्रेमवर्क में लिखा जा सकता है, उस वेब फ्रेमवर्क को CodeQL में जोड़ने के लिए एक शानदार पहला कदम हो सकता है।

Codeql में मॉडलिंग फ्रेमवर्क

दो विंडो के साथ एक कंप्यूटर ओपन ओपन दिखा रहा है सुरक्षित कोड।

CORS हेडर को मैन्युअल रूप से सेट करने के बजाय, कई डेवलपर्स इसके बजाय CORS फ्रेमवर्क का उपयोग करते हैं। आम तौर पर, CORS फ्रेमवर्क हर प्रतिक्रिया के लिए हेडर जोड़ने के लिए एक वेब फ्रेमवर्क के राउटर में मिडिलवेयर का उपयोग करता है। कुछ वेब फ्रेमवर्क में अपने स्वयं के CORS मिडिलवेयर होंगे, या आपको एक तृतीय-पक्ष पैकेज शामिल करना होगा। CodeQL में CORS फ्रेमवर्क को मॉडलिंग करते समय, आप आमतौर पर प्रासंगिक संरचनाओं और तरीकों को मॉडलिंग कर रहे हैं जो CORS नीति को दर्शाते हैं। एक बार जब मॉडल की संरचना या तरीकों में सही मूल्य होते हैं, तो क्वेरी को यह जांचना चाहिए कि संरचना वास्तव में कोडबेस में उपयोग की जाती है।

फ्रेमवर्क के लिए, हम अपनी पसंद की भाषा के रूप में जा रहे हैं क्योंकि यह CORS के लिए बहुत समर्थन है। GO CORS फ्रेमवर्क के एक जोड़े को प्रदान करता है, लेकिन अधिकांश जिन कोर्स की संरचना का अनुसरण करते हैं, जो कि GIN वेब फ्रेमवर्क के लिए एक CORS मिडिलवेयर फ्रेमवर्क है। यहाँ CORS के लिए एक GIN कॉन्फ़िगरेशन का एक उदाहरण है:

package main

import (
  "time"

  "github.com/gin-contrib/cors"
  "github.com/gin-gonic/gin"
)

func main() {
  router := gin.Default()
  router.Use(cors.New(cors.Config{
    AllowOrigins:     []string{"https://foo.com"},
    AllowMethods:     []string{"PUT", "PATCH"},
    AllowHeaders:     []string{"Origin"},
    ExposeHeaders:    []string{"Content-Length"},
    AllowCredentials: true,
    AllowOriginFunc: func(origin string) bool {
      return origin == "https://github.com"
    }
  }))
  router.Run()
}

अब जब हमने मॉडलिंग की है router.Use विधि और cors.New – यह सुनिश्चित करना cors.Config संरचना कुछ बिंदु पर है router.Use वास्तविक उपयोग के लिए कार्य – हमें फिर सभी की जांच करनी चाहिए cors.Config उपयुक्त हेडर के लिए संरचनाएं।

अगला, हम उन उपयुक्त हेडर फ़ील्ड को पाते हैं जिन्हें हम मॉडल करना चाहते हैं। एक बुनियादी cors misconfiguration क्वेरी के लिए, हम मॉडल करेंगे AllowOrigins, AllowCredentials, AllowOriginFunc। यदि आप सब कुछ देखने में रुचि रखते हैं, जो कोडक्यूएल में एक फ्रेमवर्क जोड़ने में रुचि रखते हैं, तो Codeql में ginkors और rscors को जोड़ने के लिए मेरे पुल अनुरोधों का उपयोग संदर्भ के रूप में किया जा सकता है। नीचे मैं कुछ सबसे महत्वपूर्ण विवरणों पर चर्चा करूंगा।

 /**
   * A variable of type Config that holds the headers to be set.
   */
  class GinConfig extends Variable {
    SsaWithFields v;

    GinConfig() {
      this = v.getBaseVariable().getSourceVariable() and
      v.getType().hasQualifiedName(packagePath(), "Config")
    }

    /**
     * Get variable declaration of GinConfig
     */
    SsaWithFields getV() { result = v }
  }

मैंने Ssawithfields का उपयोग करके कॉन्फ़िगर प्रकार को मॉडल किया, जो एक है एकल स्थैतिक असाइनमेंट खेतों के साथ। का उपयोग करके getSourceVariable()हम उस चर को प्राप्त कर सकते हैं जिसे संरचना को सौंपा गया था, जो हमें यह देखने में मदद कर सकता है कि कॉन्फ़िगरेशन का उपयोग कहां किया गया है। यह हमें ट्रैक चर खोजने की अनुमति देता है जिसमें कोडबेस में CORS कॉन्फ़िगर संरचना होती है, जिसमें अक्सर इस तरह से आरंभ किया जाता है:

func main() {
...
// We can now track the corsConfig variable for further updates,such as when one of the fields is updated.
corsConfig:= cors.New(cors.Config{
...
})}

अब जब हमारे पास प्रासंगिक संरचना वाला चर है, तो हम उन सभी उदाहरणों को ढूंढना चाहते हैं जहां चर लिखे गए हैं। ऐसा करने से, हम उन प्रासंगिक संपत्ति मूल्यों की समझ प्राप्त कर सकते हैं जिन्हें इसे सौंपा गया है, और इस प्रकार यह तय करें कि CORS कॉन्फ़िगरेशन गलत है या नहीं।

 /**
   * A write to the value of Access-Control-Allow-Origins header
   */
  class AllowOriginsWrite extends UniversalOriginWrite {
    DataFlow::Node base;
	
	// This models all writes to the AllowOrigins field of the Config type
    AllowOriginsWrite() {

      exists(Field f, Write w |
        f.hasQualifiedName(packagePath(), "Config", "AllowOrigins") and
        w.writesField(base, f, this) and

		// To ensure we are finding the correct field, we look for a write of type string (SliceLit)
        this.asExpr() instanceof SliceLit
      )

    }

    /**
     * Get config variable holding header values
     */
    override GinConfig getConfig() {
      exists(GinConfig gc |
        (
          gc.getV().getBaseVariable().getDefinition().(SsaExplicitDefinition).getRhs() =
            base.asInstruction() or
          gc.getV().getAUse() = base
        ) and
        result = gc
      )
    }
  }

जोड़कर getConfig फ़ंक्शन, हम पहले बनाए गए को वापस करते हैं GinConfigजो हमें यह सत्यापित करने की अनुमति देता है कि कोई भी प्रासंगिक हेडर को लिखता है समान कॉन्फ़िगरेशन संरचना को प्रभावित करता है। उदाहरण के लिए, एक डेवलपर एक कॉन्फ़िगरेशन बना सकता है जिसमें एक कमजोर मूल और एक अन्य कॉन्फ़िगरेशन होता है जो क्रेडेंशियल्स की अनुमति देता है। क्रेडेंशियल्स की अनुमति देने वाला कॉन्फ़िगर हाइलाइट नहीं किया जाएगा क्योंकि केवल कमजोर मूल के साथ कॉन्फ़िगर करता है एक सुरक्षा समस्या पैदा करेगा। CORS प्रासंगिक हेडर की अनुमति देकर विभिन्न रूपरेखाओं से सभी विस्तार के लिए लिखते हैं UniversalOriginWrite और UniversalCredentialsWriteहम अपने cors misconfiguration क्वेरी में उन लोगों का उपयोग कर सकते हैं।

Codeql में cors misconfiguration प्रश्न लिखना

CORS के मुद्दों को दो प्रकारों में अलग किया जाता है: बिना क्रेडेंशियल्स (जहां हम * या अशक्त की तलाश में हैं) और CORS के साथ क्रेडेंशियल्स (जहां हम मूल प्रतिबिंब या अशक्त की तलाश में हैं) के साथ हैं। यदि आप CodeQL क्वेरी को सरल रखना चाहते हैं, तो आप प्रत्येक प्रकार की CORS भेद्यता के लिए एक क्वेरी बना सकते हैं और तदनुसार उनकी गंभीरता को असाइन कर सकते हैं। गो लैंग्वेज के लिए, CodeQL में केवल “क्रेडेंशियल के साथ CORS” प्रकार की क्वेरी होती है क्योंकि यह सभी अनुप्रयोगों पर लागू होता है।

आइए हम उन मॉडलों में टाई करते हैं जो हमने अभी ऊपर बनाए थे कि कैसे वे गो कोर्स मिसकॉनफिगरेशन क्वेरी में इस्तेमाल किए गए थे।

from DataFlow::ExprNode allowOriginHW, string message
where
  allowCredentialsIsSetToTrue(allowOriginHW) and
  (
    flowsFromUntrustedToAllowOrigin(allowOriginHW, message)
    or
    allowOriginIsNull(allowOriginHW, message)
  ) and
  not flowsToGuardedByCheckOnUntrusted(allowOriginHW)
...
select allowOriginHW, message

यह क्वेरी केवल महत्वपूर्ण कमजोरियों में रुचि रखता है, इसलिए यह जांचता है कि क्या क्रेडेंशियल्स की अनुमति है, और क्या अनुमत उत्पत्ति या तो एक दूरस्थ स्रोत से आती है या शून्य के रूप में हार्डकोड किया जाता है। झूठी सकारात्मकता को रोकने के लिए, यह जांचता है कि क्या कुछ गार्ड हैं – जैसे कि स्ट्रिंग तुलना – दूरस्थ स्रोत से पहले मूल तक पहुंचें। चलो विधेय पर करीब से नज़र डालते हैं allowCredentialsIsSetToTrue

/**
 * Holds if the provided `allowOriginHW` HeaderWrite's parent ResponseWriter
 * also has another HeaderWrite that sets a `Access-Control-Allow-Credentials`
 * header to `true`.
 */
predicate allowCredentialsIsSetToTrue(DataFlow::ExprNode allowOriginHW) {
  exists(AllowCredentialsHeaderWrite allowCredentialsHW |
    allowCredentialsHW.getHeaderValue().toLowerCase() = "true"
  |
    allowOriginHW.(AllowOriginHeaderWrite).getResponseWriter() =
      allowCredentialsHW.getResponseWriter()
  )
  or
...

विधेय के पहले भाग के लिए, हम उन हेडर में से एक का उपयोग करेंगे, जिन्हें हमने पहले मॉडल किया था, हेडर की तुलना करने के लिए, अनुमति दी। यह हमें सभी हेडर लिखते हुए फ़िल्टर करने में मदद करेगा, जिसमें क्रेडेंशियल सेट नहीं है।

  exists(UniversalAllowCredentialsWrite allowCredentialsGin |
    allowCredentialsGin.getExpr().getBoolValue() = true
  |
    allowCredentialsGin.getConfig() = allowOriginHW.(UniversalOriginWrite).getConfig() and
    not exists(UniversalAllowAllOriginsWrite allowAllOrigins |
      allowAllOrigins.getExpr().getBoolValue() = true and
      allowCredentialsGin.getConfig() = allowAllOrigins.getConfig()
    )
    or
    allowCredentialsGin.getBase() = allowOriginHW.(UniversalOriginWrite).getBase() and
    not exists(UniversalAllowAllOriginsWrite allowAllOrigins |
      allowAllOrigins.getExpr().getBoolValue() = true and
      allowCredentialsGin.getBase() = allowAllOrigins.getBase()
    )
  )
}

यदि CORS को हेडर के माध्यम से सेट नहीं किया जाता है, तो हम CORS फ्रेमवर्क का उपयोग करके जांच करते हैं UniversalAllowCredentialsWriteसभी उदाहरणों को फ़िल्टर करें, जिनके संबंधित मूल मान “*” पर सेट है, हम उपयोग करते हैं not Codeql कीवर्ड UniversalAllowAllOriginsWriteचूंकि ये इस भेद्यता पर लागू नहीं हैं। flowsFromUntrustedToAllowOrigin और allowOriginIsNull यह सुनिश्चित करने के लिए समान तर्क का पालन करें कि परिणामी हेडर अधिकार कमजोर हैं।

जब आप CORS से संबंधित कमजोरियों का पता लगाने के लिए CodeQL क्वेरी को मॉडल करते हैं, तो आप एक-आकार-फिट-सभी दृष्टिकोण का उपयोग नहीं कर सकते हैं। इसके बजाय, आपको दो कारणों से प्रत्येक वेब फ्रेमवर्क के लिए अपने प्रश्नों को दर्जी करना होगा:

  • प्रत्येक ढांचा अपने तरीके से cors नीतियों को लागू करता है
  • भेद्यता पैटर्न एक रूपरेखा के व्यवहार पर निर्भर करते हैं

उदाहरण के लिए, हमने पहले जिन कोर्स में देखा था कि वहाँ है AllowOriginFunc। प्रलेखन को देखने या कोड के साथ प्रयोग करने के बाद, हम देख सकते हैं कि यह ओवरराइड हो सकता है AllowOrigins। अपनी क्वेरी को बेहतर बनाने के लिए, हम एक CodeQL क्वेरी लिख सकते हैं जो दिखता है AllowOriginFuncएस जो हमेशा सच लौटता है, जिसके परिणामस्वरूप क्रेडेंशियल्स के साथ जोड़ा जाता है।

इसे अपने साथ ले लो

एक बार जब आप CodeQL के साथ वेब फ्रेमवर्क और हेडर के व्यवहार को समझते हैं, तो अपने कोड में सुरक्षा मुद्दों को ढूंढना और अपने काम में अपनी जगह बनाने की संभावना को कम करना सरल है। CODEQL भाषाओं की संख्या जो cors misconfiguration प्रश्नों का समर्थन करती है, अभी भी बढ़ रही हैं, और समुदाय से सुधार के लिए हमेशा जगह होती है।

यदि यह ब्लॉग आपको CodeQL प्रश्न लिखने में मदद करने में मददगार रहा है, तो कृपया हमारे साथ समुदाय के साथ साझा करना चाहते हैं, कृपया कुछ भी खोलने के लिए स्वतंत्र महसूस करें Codeql सामुदायिक पैक

अंत में, Github कोड सुरक्षा जैसे कि कीड़े के लिए एक फिक्स का पता लगाकर और सुझाव देकर अपनी परियोजना को सुरक्षित करने में आपकी सहायता कर सकते हैं Cors misconfigurationतू

और ज्यादा खोजें गीथब सिक्योरिटी लैब ब्लॉग पोस्ट>

द्वारा लिखित

केविन स्टबिंग्स



स्रोत लिंक