diff --git a/docker/tanner/docker-compose.yml b/docker/tanner/docker-compose.yml index e50649f9..31a2ae00 100644 --- a/docker/tanner/docker-compose.yml +++ b/docker/tanner/docker-compose.yml @@ -49,23 +49,25 @@ services: - tanner_redis # Tanner WEB Service -# tanner_web: -# build: ./tanner -# container_name: tanner_web -# restart: always -# stop_signal: SIGKILL -# tmpfs: -# - /tmp/tanner:uid=2000,gid=2000 -# tty: true -# networks: -# - tanner_local -# image: "dtagdevsec/tanner:2006" -# command: tannerweb -# read_only: true -# volumes: -# - /data/tanner/log:/var/log/tanner -# depends_on: -# - tanner_redis + tanner_web: + build: ./tanner + container_name: tanner_web + restart: always + stop_signal: SIGKILL + tmpfs: + - /tmp/tanner:uid=2000,gid=2000 + tty: true + networks: + - tanner_local +# ports: +# - "127.0.0.1:8091:8091" + image: "dtagdevsec/tanner:2006" + command: tannerweb + read_only: true + volumes: + - /data/tanner/log:/var/log/tanner + depends_on: + - tanner_redis # Tanner Service tanner: @@ -86,7 +88,7 @@ services: - /data/tanner/files:/opt/tanner/files depends_on: - tanner_api -# - tanner_web + - tanner_web - tanner_phpox # Snare Service diff --git a/docker/tanner/phpox/dist/sandbox.py b/docker/tanner/phpox/dist/sandbox.py index 8b5d363e..9be76b75 100644 --- a/docker/tanner/phpox/dist/sandbox.py +++ b/docker/tanner/phpox/dist/sandbox.py @@ -23,12 +23,16 @@ import json import asyncio import hashlib import argparse +import functools from aiohttp import web from asyncio.subprocess import PIPE from pprint import pprint +_pretty_dumps = functools.partial(json.dumps, sort_keys=True, indent=4) + + class PHPSandbox(object): @classmethod def php_tag_check(cls, script): @@ -51,7 +55,7 @@ class PHPSandbox(object): self.stdout_value += line + b'\n' @asyncio.coroutine - def sandbox(self, script, phpbin="php7.0"): + def sandbox(self, script, phpbin="php7"): if not os.path.isfile(script): raise Exception("Sample not found: {0}".format(script)) @@ -96,12 +100,12 @@ def api(request): except KeyboardInterrupt: pass ret['file_md5'] = file_md5 - return web.Response(body=json.dumps(ret, sort_keys=True, indent=4).encode('utf-8')) + return web.json_response(ret, dumps=_pretty_dumps) if __name__ == '__main__': parser = argparse.ArgumentParser() - parser.add_argument("--phpbin", help="PHP binary, ex: php7.0", default="php7.0") + parser.add_argument("--phpbin", help="PHP binary, ex: php7", default="php7") args = parser.parse_args() phpbin = args.phpbin diff --git a/docker/tanner/phpox/dist/sandbox.py.old b/docker/tanner/phpox/dist/sandbox.py.old new file mode 100644 index 00000000..8b5d363e --- /dev/null +++ b/docker/tanner/phpox/dist/sandbox.py.old @@ -0,0 +1,125 @@ +#!/usr/bin/env python3 + +# Copyright (C) 2016 Lukas Rist +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +import os +import tempfile +import json +import asyncio +import hashlib +import argparse + +from aiohttp import web +from asyncio.subprocess import PIPE + +from pprint import pprint + +class PHPSandbox(object): + @classmethod + def php_tag_check(cls, script): + with open(script, "r+") as check_file: + file_content = check_file.read() + if "" not in file_content: + file_content += "?>" + check_file.write(file_content) + return script + + @asyncio.coroutine + def read_process(self): + while True: + line = yield from self.proc.stdout.readline() + if not line: + break + else: + self.stdout_value += line + b'\n' + + @asyncio.coroutine + def sandbox(self, script, phpbin="php7.0"): + if not os.path.isfile(script): + raise Exception("Sample not found: {0}".format(script)) + + try: + cmd = [phpbin, "sandbox.php", script] + self.proc = yield from asyncio.create_subprocess_exec(*cmd, stdout=PIPE) + self.stdout_value = b'' + yield from asyncio.wait_for(self.read_process(), timeout=3) + except Exception as e: + try: + self.proc.kill() + except Exception: + pass + print("Error executing the sandbox: {}".format(e)) + # raise e + return {'stdout': self.stdout_value.decode('utf-8')} + + +class EchoServer(asyncio.Protocol): + def connection_made(self, transport): + # peername = transport.get_extra_info('peername') + # print('connection from {}'.format(peername)) + self.transport = transport + + def data_received(self, data): + # print('data received: {}'.format(data.decode())) + self.transport.write(data) + + +@asyncio.coroutine +def api(request): + data = yield from request.read() + file_md5 = hashlib.md5(data).hexdigest() + with tempfile.NamedTemporaryFile(suffix='.php') as f: + f.write(data) + f.seek(0) + sb = PHPSandbox() + try: + server = yield from loop.create_server(EchoServer, '127.0.0.1', 1234) + ret = yield from asyncio.wait_for(sb.sandbox(f.name, phpbin), timeout=10) + server.close() + except KeyboardInterrupt: + pass + ret['file_md5'] = file_md5 + return web.Response(body=json.dumps(ret, sort_keys=True, indent=4).encode('utf-8')) + + +if __name__ == '__main__': + parser = argparse.ArgumentParser() + parser.add_argument("--phpbin", help="PHP binary, ex: php7.0", default="php7.0") + args = parser.parse_args() + phpbin = args.phpbin + + app = web.Application() + app.router.add_route('POST', '/', api) + + loop = asyncio.get_event_loop() + handler = app.make_handler() + f = loop.create_server(handler, '0.0.0.0', 8088) + srv = loop.run_until_complete(f) + print('serving on', srv.sockets[0].getsockname()) + try: + loop.run_forever() + except KeyboardInterrupt: + pass + finally: + loop.run_until_complete(handler.finish_connections(1.0)) + srv.close() + loop.run_until_complete(srv.wait_closed()) + loop.run_until_complete(app.finish()) + loop.close()