예제 #1
0
def migrate(revision):
    """Perform database migrations."""
    if not migrate_database(revision):
        print red(">>> Error migrating your database..")
        exit(1)

    print yellow(">>> Your database migration was successful!")
예제 #2
0
파일: main.py 프로젝트: swackhamer/cuckoo
def migrate(revision):
    """Perform database migrations."""
    if not migrate_database(revision):
        print red(">>> Error migrating your database..")
        exit(1)

    print yellow(">>> Your database migration was successful!")
예제 #3
0
def check_version():
    """Checks version of Cuckoo."""
    if not config("cuckoo:cuckoo:version_check"):
        return

    print(" Checking for updates...")

    try:
        r = requests.get("https://cuckoosandbox.org/updates.json",
                         params={"version": version},
                         timeout=6)
        r.raise_for_status()
        r = r.json()
    except (requests.RequestException, ValueError) as e:
        print(red(" Error checking for the latest Cuckoo version: %s!" % e))
        return

    try:
        old = StrictVersion(version) < StrictVersion(r["version"])
    except ValueError:
        old = True

    if old:
        msg = "Cuckoo Sandbox version %s is available now." % r["version"]
        print(red(" Outdated! ") + msg)
    else:
        print(green(" You're good to go!"))

    print("\n Our latest blogposts:")
    for blogpost in r["blogposts"]:
        print(" * %s, %s." % (yellow(blogpost["title"]), blogpost["date"]))
        print("   %s" % red(blogpost["oneline"]))
        print("   More at %s" % blogpost["url"])
        print("")
    return r
예제 #4
0
def main(ctx, debug, quiet, nolog, maxcount, user, cwd):
    """Invokes the Cuckoo daemon or one of its subcommands.

    To be able to use different Cuckoo configurations on the same machine with
    the same Cuckoo installation, we use the so-called Cuckoo Working
    Directory (aka "CWD"). A default CWD is available, but may be overridden
    through the following options - listed in order of precedence.

    \b
    * Command-line option (--cwd)
    * Environment option ("CUCKOO_CWD")
    * Environment option ("CUCKOO")
    * Current directory (if the ".cwd" file exists)
    * Default value ("~/.cuckoo")
    """
    decide_cwd(cwd)

    # Drop privileges.
    user and drop_privileges(user)
    ctx.user = user

    ctx.log = not nolog

    if quiet:
        level = logging.WARN
    elif debug:
        level = logging.DEBUG
    else:
        level = logging.INFO

    ctx.level = level

    # Update the Config.configuration object to have configuration info
    # from plugins.
    update_config()

    # A subcommand will be invoked, so don't run Cuckoo itself.
    if ctx.invoked_subcommand:
        return

    try:
        cuckoo_init(level, ctx)
        cuckoo_main(maxcount)
    except CuckooCriticalError as e:
        log.critical(red("{0}: {1}".format(e.__class__.__name__, e)))
        sys.exit(1)
    except SystemExit as e:
        if e.code:
            print e
    except Exception as e:
        # Deal with an unhandled exception.
        sys.stderr.write(exception_message())
        log.exception(red("{0}: {1}".format(e.__class__.__name__, e)))
        sys.exit(1)
예제 #5
0
파일: main.py 프로젝트: swackhamer/cuckoo
def dist_migrate():
    args = [
        "alembic", "-x", "cwd=%s" % cwd(), "upgrade", "head",
    ]
    try:
        subprocess.check_call(
            args, cwd=cwd("distributed", "migration", private=True)
        )
    except subprocess.CalledProcessError:
        print red(">>> Error migrating your database..")
        exit(1)

    print yellow(">>> Your database migration was successful!")
예제 #6
0
def dist_migrate():
    args = [
        "alembic", "-x", "cwd=%s" % cwd(), "upgrade", "head",
    ]
    try:
        subprocess.check_call(
            args, cwd=cwd("distributed", "migration", private=True)
        )
    except subprocess.CalledProcessError:
        print red(">>> Error migrating your database..")
        exit(1)

    print yellow(">>> Your database migration was successful!")
예제 #7
0
def process(ctx, instance, report, maxcount):
    """Process raw task data into reports."""
    init_console_logging(level=ctx.parent.level)

    if instance:
        pidfile = Pidfile(instance)
        if pidfile.exists():
            log.error(red(
                "Cuckoo process instance '%s' already exists. PID: %s\n"
            ), instance, pidfile.pid)
            sys.exit(1)

        pidfile.create()

        init_logfile("process-%s.json" % instance)

    Database().connect()

    # Load additional Signatures.
    load_signatures()

    try:
        # Initialize all modules & Yara rules.
        init_modules()
        init_yara()
    except CuckooCriticalError as e:
        message = red("{0}: {1}".format(e.__class__.__name__, e))
        if len(log.handlers):
            log.critical(message)
        else:
            sys.stderr.write("{0}\n".format(message))
        sys.exit(1)

    try:
        # Regenerate one or more reports.
        if report:
            process_task_range(report)
        elif not instance:
            print ctx.get_help(), "\n"
            sys.exit("In automated mode an instance name is required!")
        else:
            log.info(
                "Initialized instance=%s, ready to process some tasks",
                instance
            )
            process_tasks(instance, maxcount)
    except KeyboardInterrupt:
        print(red("Aborting (re-)processing of your analyses.."))

    if instance:
        Pidfile(instance).remove()
예제 #8
0
파일: main.py 프로젝트: consen/cuckoo
def process(ctx, instance, report, maxcount):
    """Process raw task data into reports."""
    init_console_logging(level=ctx.parent.level)

    if instance:
        pidfile = Pidfile(instance)
        if pidfile.exists():
            log.error(red(
                "Cuckoo process instance '%s' already exists. PID: %s\n"
            ), instance, pidfile.pid)
            sys.exit(1)

        pidfile.create()

        init_logfile("process-%s.json" % instance)

    Database().connect()

    # Load additional Signatures.
    load_signatures()

    try:
        # Initialize all modules & Yara rules.
        init_modules()
        init_yara()
    except CuckooCriticalError as e:
        message = red("{0}: {1}".format(e.__class__.__name__, e))
        if len(log.handlers):
            log.critical(message)
        else:
            sys.stderr.write("{0}\n".format(message))
        sys.exit(1)

    try:
        # Regenerate one or more reports.
        if report:
            process_task_range(report)
        elif not instance:
            print ctx.get_help(), "\n"
            sys.exit("In automated mode an instance name is required!")
        else:
            log.info(
                "Initialized instance=%s, ready to process some tasks",
                instance
            )
            process_tasks(instance, maxcount)
    except KeyboardInterrupt:
        print(red("Aborting (re-)processing of your analyses.."))

    if instance:
        Pidfile(instance).remove()
예제 #9
0
파일: main.py 프로젝트: consen/cuckoo
def main(ctx, debug, quiet, nolog, maxcount, user, cwd):
    """Invokes the Cuckoo daemon or one of its subcommands.

    To be able to use different Cuckoo configurations on the same machine with
    the same Cuckoo installation, we use the so-called Cuckoo Working
    Directory (aka "CWD"). A default CWD is available, but may be overridden
    through the following options - listed in order of precedence.

    \b
    * Command-line option (--cwd)
    * Environment option ("CUCKOO_CWD")
    * Environment option ("CUCKOO")
    * Current directory (if the ".cwd" file exists)
    * Default value ("~/.cuckoo")
    """
    decide_cwd(cwd)

    # Drop privileges.
    user and drop_privileges(user)
    ctx.user = user

    ctx.log = not nolog

    if quiet:
        level = logging.WARN
    elif debug:
        level = logging.DEBUG
    else:
        level = logging.INFO

    ctx.level = level

    # A subcommand will be invoked, so don't run Cuckoo itself.
    if ctx.invoked_subcommand:
        return

    try:
        cuckoo_init(level, ctx)
        cuckoo_main(maxcount)
    except CuckooCriticalError as e:
        log.critical(red("{0}: {1}".format(e.__class__.__name__, e)))
        sys.exit(1)
    except SystemExit as e:
        if e.code:
            print e
    except Exception as e:
        # Deal with an unhandled exception.
        sys.stderr.write(exception_message())
        log.exception(red("{0}: {1}".format(e.__class__.__name__, e)))
        sys.exit(1)
예제 #10
0
def cuckoo_create(username=None, cfg=None, quiet=False):
    """Create a new Cuckoo Working Directory."""
    if not quiet:
        print jinja2.Environment().from_string(
            open(cwd("cwd", "init-pre.jinja2", private=True), "rb").read()
        ).render(cwd=cwd, yellow=yellow, red=red)

    if not os.path.exists(cwd(".cwd", private=True)):
        print red(
            "The cuckoo/private/.cwd file is missing. Please run "
            "'python setup.py sdist' before 'pip install ...'!"
        )
        return

    if not os.path.isdir(cwd()):
        os.mkdir(cwd())

    def _ignore_pyc(src, names):
        """Don't copy .pyc files."""
        return [name for name in names if name.endswith(".pyc")]

    # The following effectively nops the first os.makedirs() call that
    # shutil.copytree() does as we've already created the destination
    # directory ourselves (assuming it didn't exist already).
    orig_makedirs = shutil.os.makedirs

    def _ignore_first_makedirs(dst):
        shutil.os.makedirs = orig_makedirs

    shutil.os.makedirs = _ignore_first_makedirs

    shutil.copytree(
        os.path.join(cuckoo.__path__[0], "data"),
        cwd(), symlinks=True, ignore=_ignore_pyc
    )

    # Drop our version of the CWD.
    our_version = open(cwd(".cwd", private=True), "rb").read()
    open(cwd(".cwd"), "wb").write(our_version)

    # Write the supervisord.conf configuration file.
    write_supervisor_conf(username or getuser())
    write_cuckoo_conf(cfg=cfg)

    if not quiet:
        print
        print jinja2.Environment().from_string(
            open(cwd("cwd", "init-post.jinja2", private=True), "rb").read()
        ).render()
예제 #11
0
파일: main.py 프로젝트: msr00t/cuckoo
def cuckoo_create(username=None, cfg=None, quiet=False):
    """Create a new Cuckoo Working Directory."""
    if not quiet:
        print jinja2.Environment().from_string(
            open(cwd("cwd", "init-pre.jinja2", private=True), "rb").read()
        ).render(cwd=cwd, yellow=yellow, red=red)

    if not os.path.exists(cwd(".cwd", private=True)):
        print red(
            "The cuckoo/private/.cwd file is missing. Please run "
            "'python setup.py sdist' before 'pip install ...'!"
        )
        return

    if not os.path.isdir(cwd()):
        os.mkdir(cwd())

    def _ignore_pyc(src, names):
        """Don't copy .pyc files."""
        return [name for name in names if name.endswith(".pyc")]

    # The following effectively nops the first os.makedirs() call that
    # shutil.copytree() does as we've already created the destination
    # directory ourselves (assuming it didn't exist already).
    orig_makedirs = shutil.os.makedirs

    def _ignore_first_makedirs(dst):
        shutil.os.makedirs = orig_makedirs

    shutil.os.makedirs = _ignore_first_makedirs

    shutil.copytree(
        os.path.join(cuckoo.__path__[0], "data"),
        cwd(), symlinks=True, ignore=_ignore_pyc
    )

    # Drop our version of the CWD.
    our_version = open(cwd(".cwd", private=True), "rb").read()
    open(cwd(".cwd"), "wb").write(our_version)

    # Write the supervisord.conf configuration file.
    write_supervisor_conf(username or getuser())
    write_cuckoo_conf(cfg=cfg)

    if not quiet:
        print
        print jinja2.Environment().from_string(
            open(cwd("cwd", "init-post.jinja2", private=True), "rb").read()
        ).render()
예제 #12
0
def dnsserve(ctx, host, port, nxdomain, hardcode):
    """Custom DNS server."""
    init_console_logging(ctx.parent.level)
    try:
        cuckoo_dnsserve(host, port, nxdomain, hardcode)
    except KeyboardInterrupt:
        print(red("Aborting Cuckoo DNS Serve.."))
예제 #13
0
파일: main.py 프로젝트: swackhamer/cuckoo
def process(ctx, instance, report, maxcount):
    """Process raw task data into reports."""
    init_console_logging(level=ctx.parent.level)

    if instance:
        init_logfile("process-%s.json" % instance)

    Database().connect()

    # Load additional Signatures.
    load_signatures()

    # Initialize all modules & Yara rules.
    init_modules()
    init_yara(False)

    try:
        # Regenerate one or more reports.
        if report:
            process_task_range(report)
        elif not instance:
            print ctx.get_help(), "\n"
            sys.exit("In automated mode an instance name is required!")
        else:
            log.info(
                "Initialized instance=%s, ready to process some tasks",
                instance
            )
            process_tasks(instance, maxcount)
    except KeyboardInterrupt:
        print(red("Aborting (re-)processing of your analyses.."))
예제 #14
0
파일: main.py 프로젝트: swackhamer/cuckoo
def rooter(ctx, socket, group, ifconfig, service, iptables, ip, sudo):
    """Instantiates the Cuckoo Rooter."""
    init_console_logging(level=ctx.parent.level)

    if sudo:
        args = [
            "sudo", sys.argv[0], "rooter", socket,
            "--group", group,
            "--ifconfig", ifconfig,
            "--service", service,
            "--iptables", iptables,
            "--ip", ip,
        ]

        if ctx.parent.level == logging.DEBUG:
            args.insert(2, "--debug")

        try:
            subprocess.call(args)
        except KeyboardInterrupt:
            pass
    else:
        try:
            cuckoo_rooter(socket, group, ifconfig, service, iptables, ip)
        except KeyboardInterrupt:
            print(red("Aborting the Cuckoo Rooter.."))
예제 #15
0
파일: main.py 프로젝트: swackhamer/cuckoo
def dnsserve(ctx, host, port, nxdomain, hardcode):
    """Custom DNS server."""
    init_console_logging(ctx.parent.level)
    try:
        cuckoo_dnsserve(host, port, nxdomain, hardcode)
    except KeyboardInterrupt:
        print(red("Aborting Cuckoo DNS Serve.."))
예제 #16
0
파일: main.py 프로젝트: consen/cuckoo
def dnsserve(ctx, host, port, nxdomain, hardcode, sudo):
    """Custom DNS server."""
    init_console_logging(ctx.parent.level)

    if sudo:
        args = [
            "sudo", sys.argv[0], "dnsserve",
            "--host", host, "--port", "%d" % port,
        ]

        if ctx.parent.level == logging.DEBUG:
            args.insert(2, "--debug")

        if nxdomain:
            args.extend(("--nxdomain", nxdomain))

        if hardcode:
            args.extend(("--hardcode", hardcode))

        try:
            subprocess.call(args)
        except KeyboardInterrupt:
            pass
    else:
        try:
            cuckoo_dnsserve(host, port, nxdomain, hardcode)
        except KeyboardInterrupt:
            print(red("Aborting Cuckoo DNS Serve.."))
예제 #17
0
def dnsserve(ctx, host, port, nxdomain, hardcode, sudo):
    """Custom DNS server."""
    init_console_logging(ctx.parent.level)

    if sudo:
        args = [
            "sudo", sys.argv[0], "dnsserve",
            "--host", host, "--port", "%d" % port,
        ]

        if ctx.parent.level == logging.DEBUG:
            args.insert(2, "--debug")

        if nxdomain:
            args.extend(("--nxdomain", nxdomain))

        if hardcode:
            args.extend(("--hardcode", hardcode))

        try:
            subprocess.call(args)
        except KeyboardInterrupt:
            pass
    else:
        try:
            cuckoo_dnsserve(host, port, nxdomain, hardcode)
        except KeyboardInterrupt:
            print(red("Aborting Cuckoo DNS Serve.."))
예제 #18
0
파일: main.py 프로젝트: swackhamer/cuckoo
def submit(ctx, target, url, options, package, custom, owner, timeout,
           priority, machine, platform, memory, enforce_timeout, clock, tags,
           baseline, remote, shuffle, pattern, max, unique):
    """Submit one or more files or URLs to Cuckoo."""
    init_console_logging(level=ctx.parent.level)
    Database().connect()

    try:
        l = submit_tasks(
            target, options, package, custom, owner, timeout, priority,
            machine, platform, memory, enforce_timeout, clock, tags, remote,
            pattern, max, unique, url, baseline, shuffle
        )

        for category, target, task_id in l:
            if task_id:
                print "%s: %s \"%s\" added as task with ID #%s" % (
                    bold(green("Success")), category, target, task_id
                )
            else:
                print "%s: %s \"%s\" as it has already been analyzed" % (
                    bold(yellow("Skipped")), category, target
                )
    except KeyboardInterrupt:
        print(red("Aborting submission of samples.."))
예제 #19
0
파일: main.py 프로젝트: songofhack/cuckoo
def process(ctx, instance, report, maxcount):
    """Process raw task data into reports."""
    init_console_logging(level=ctx.parent.level)

    if instance:
        init_logfile("process-%s.json" % instance)

    Database().connect()

    # Load additional Signatures.
    load_signatures()

    # Initialize all modules & Yara rules.
    init_modules()
    init_yara(False)

    try:
        # Regenerate one or more reports.
        if report:
            process_task_range(report)
        elif not instance:
            print ctx.get_help(), "\n"
            sys.exit("In automated mode an instance name is required!")
        else:
            log.info(
                "Initialized instance=%s, ready to process some tasks",
                instance
            )
            process_tasks(instance, maxcount)
    except KeyboardInterrupt:
        print(red("Aborting (re-)processing of your analyses.."))
예제 #20
0
def rooter(ctx, socket, group, service, iptables, ip, sudo):
    """Instantiates the Cuckoo Rooter."""
    init_console_logging(level=ctx.parent.level)

    if sudo:
        args = [
            "sudo", sys.argv[0], "rooter", socket,
            "--group", group,
            "--service", service,
            "--iptables", iptables,
            "--ip", ip,
        ]

        if ctx.parent.level == logging.DEBUG:
            args.insert(2, "--debug")

        try:
            subprocess.call(args)
        except KeyboardInterrupt:
            pass
    else:
        try:
            cuckoo_rooter(socket, group, service, iptables, ip)
        except KeyboardInterrupt:
            print(red("Aborting the Cuckoo Rooter.."))
예제 #21
0
def submit(ctx, target, url, options, package, custom, owner, timeout,
           priority, machine, platform, memory, enforce_timeout, clock, tags,
           baseline, remote, shuffle, pattern, max, unique):
    """Submit one or more files or URLs to Cuckoo."""
    init_console_logging(level=ctx.parent.level)
    Database().connect()

    try:
        l = submit_tasks(
            target, options, package, custom, owner, timeout, priority,
            machine, platform, memory, enforce_timeout, clock, tags, remote,
            pattern, max, unique, url, baseline, shuffle
        )

        for category, target, task_id in l:
            if task_id:
                print "%s: %s \"%s\" added as task with ID #%s" % (
                    bold(green("Success")), category, target, task_id
                )
            else:
                print "%s: %s \"%s\" as it has already been analyzed" % (
                    bold(yellow("Skipped")), category, target
                )
    except KeyboardInterrupt:
        print(red("Aborting submission of samples.."))
예제 #22
0
def ensure_tmpdir():
    """Verify if the current user can read and create files in the
    cuckoo temporary directory (and creates it, if needed)."""
    try:
        if not os.path.isdir(temppath()):
            mkdir(temppath())
    except OSError as e:
        # Currently we only handle EACCES.
        if e.errno != errno.EACCES:
            raise

    if os.path.isdir(temppath()) and os.access(temppath(), os.R_OK | os.W_OK):
        return True

    print red(
        "Cuckoo cannot read or write files into the temporary directory '%s',"
        " please make sure the user running Cuckoo has the ability to do so. "
        "If the directory does not yet exist and the parent directory is "
        "owned by root, then please create and chown the directory with root."
        % temppath())
    return False
예제 #23
0
파일: startup.py 프로젝트: ptcNOP/cuckoo
def check_version():
    """Checks version of Cuckoo."""
    if not config("cuckoo:cuckoo:version_check"):
        return

    print(" Checking for updates...")

    try:
        r = requests.post(
            "http://api.cuckoosandbox.org/checkversion.php",
            data={"version": version}
        )
        r.raise_for_status()
        r = r.json()
    except (requests.RequestException, ValueError) as e:
        print(red(" Error checking for the latest Cuckoo version: %s!" % e))
        return

    if not isinstance(r, dict) or r.get("error"):
        print(red(" Error checking for the latest Cuckoo version:"))
        print(yellow(" Response: %s" % r))
        return

    rc1_responses = "NEW_VERSION", "NO_UPDATES"

    # Deprecated response.
    if r.get("response") in rc1_responses and r.get("current") == "2.0-rc1":
        print(green(" You're good to go!"))
        return

    try:
        old = StrictVersion(version) < StrictVersion(r.get("current"))
    except ValueError:
        old = True

    if old:
        msg = "Cuckoo Sandbox version %s is available now." % r.get("current")
        print(red(" Outdated! ") + msg),
    else:
        print(green(" You're good to go!"))
예제 #24
0
def check_version():
    """Checks version of Cuckoo."""
    if not config("cuckoo:cuckoo:version_check"):
        return

    print(" Checking for updates...")

    try:
        r = requests.post(
            "http://api.cuckoosandbox.org/checkversion.php",
            data={"version": version}
        )
        r.raise_for_status()
        r = r.json()
    except (requests.RequestException, ValueError) as e:
        print(red(" Error checking for the latest Cuckoo version: %s!" % e))
        return

    if not isinstance(r, dict) or r.get("error"):
        print(red(" Error checking for the latest Cuckoo version:"))
        print(yellow(" Response: %s" % r))
        return

    rc1_responses = "NEW_VERSION", "NO_UPDATES"

    # Deprecated response.
    if r.get("response") in rc1_responses and r.get("current") == "2.0-rc1":
        print(green(" You're good to go!"))
        return

    try:
        old = StrictVersion(version) < StrictVersion(r.get("current"))
    except ValueError:
        old = True

    if old:
        msg = "Cuckoo Sandbox version %s is available now." % r.get("current")
        print(red(" Outdated! ") + msg),
    else:
        print(green(" You're good to go!"))
예제 #25
0
파일: startup.py 프로젝트: fbusta/cuckoo
def ensure_tmpdir():
    """Verifies if the current user can read and create files in the
    cuckoo temporary directory (and creates it, if needed)."""
    try:
        if not os.path.isdir(temppath()):
            mkdir(temppath())
    except OSError as e:
        # Currently we only handle EACCES.
        if e.errno != errno.EACCES:
            raise

    if os.path.isdir(temppath()) and os.access(temppath(), os.R_OK | os.W_OK):
        return True

    print red(
        "Cuckoo cannot read or write files into the temporary directory '%s',"
        " please make sure the user running Cuckoo has the ability to do so. "
        "If the directory does not yet exist and the parent directory is "
        "owned by root, then please create and chown the directory with root."
        % temppath()
    )
    return False
예제 #26
0
파일: log.py 프로젝트: CERT-Polska/cuckoo
    def emit(self, record):
        colored = copy.copy(record)

        if record.levelname == "WARNING":
            colored.msg = yellow(record.msg)
        elif record.levelname == "ERROR" or record.levelname == "CRITICAL":
            colored.msg = red(record.msg)
        else:
            if "analysis procedure completed" in record.msg:
                colored.msg = cyan(record.msg)
            else:
                colored.msg = record.msg

        logging.StreamHandler.emit(self, colored)
예제 #27
0
    def emit(self, record):
        colored = copy.copy(record)

        if record.levelname == "WARNING":
            colored.msg = yellow(record.msg)
        elif record.levelname == "ERROR" or record.levelname == "CRITICAL":
            colored.msg = red(record.msg)
        else:
            if "analysis procedure completed" in record.msg:
                colored.msg = cyan(record.msg)
            else:
                colored.msg = record.msg

        logging.StreamHandler.emit(self, colored)
예제 #28
0
파일: startup.py 프로젝트: fbusta/cuckoo
def check_version():
    """Checks version of Cuckoo."""
    if not config("cuckoo:cuckoo:version_check"):
        return

    print(" Checking for updates...")

    try:
        r = requests.get(
            "https://cuckoosandbox.org/updates.json",
            params={"version": version}, timeout=6
        )
        r.raise_for_status()
        r = r.json()
    except (requests.RequestException, ValueError) as e:
        print(red(" Error checking for the latest Cuckoo version: %s!" % e))
        return

    try:
        old = StrictVersion(version) < StrictVersion(r["version"])
    except ValueError:
        old = True

    if old:
        msg = "Cuckoo Sandbox version %s is available now." % r["version"]
        print(red(" Outdated! ") + msg)
    else:
        print(green(" You're good to go!"))

    print("\n Our latest blogposts:")
    for blogpost in r["blogposts"]:
        print(" * %s, %s." % (yellow(blogpost["title"]), blogpost["date"]))
        print("   %s" % red(blogpost["oneline"]))
        print("   More at %s" % blogpost["url"])
        print("")
    return r
예제 #29
0
파일: apps.py 프로젝트: jgajek/cuckoo
def submit_tasks(target, options, package, custom, owner, timeout, priority,
                 machine, platform, memory, enforce_timeout, clock, tags,
                 remote, pattern, maxcount, is_unique, is_url, is_baseline,
                 is_shuffle):
    db = Database()

    data = dict(
        package=package or "",
        timeout=timeout,
        options=options,
        priority=priority,
        machine=machine,
        platform=platform,
        custom=custom,
        owner=owner,
        tags=tags,
        memory="1" if memory else "0",
        enforce_timeout="1" if enforce_timeout else "0",
        clock=clock,
        unique="1" if is_unique else "0",
    )

    if is_baseline:
        if remote:
            print "Remote baseline support has not yet been implemented."
            return

        task_id = db.add_baseline(timeout, owner, machine, memory)
        yield "Baseline", machine, task_id
        return

    if is_url and is_unique:
        print "URL doesn't have --unique support yet."
        return

    if is_url:
        for url in target:
            if not remote:
                data.pop("unique", None)
                task_id = db.add_url(to_unicode(url), **data)
                yield "URL", url, task_id
                continue

            data["url"] = to_unicode(url)
            try:
                r = requests.post(
                    "http://%s/tasks/create/url" % remote, data=data
                )
                yield "URL", url, r.json()["task_id"]
            except Exception as e:
                print "%s: unable to submit URL: %s" % (
                    bold(red("Error")), e
                )
    else:
        files = []
        for path in target:
            files.extend(enumerate_files(os.path.abspath(path), pattern))

        if is_shuffle:
            random.shuffle(files)

        for filepath in files:
            if not os.path.getsize(filepath):
                print "%s: sample %s (skipping file)" % (
                    bold(yellow("Empty")), filepath
                )
                continue

            if maxcount is not None:
                if not maxcount:
                    break
                maxcount -= 1

            if not remote:
                if is_unique:
                    sha256 = File(filepath).get_sha256()
                    if db.find_sample(sha256=sha256):
                        yield "File", filepath, None
                        continue

                data.pop("unique", None)
                task_id = db.add_path(file_path=filepath, **data)
                yield "File", filepath, task_id
                continue

            files = {
                "file": (os.path.basename(filepath), open(filepath, "rb")),
            }

            try:
                r = requests.post(
                    "http://%s/tasks/create/file" % remote,
                    data=data, files=files
                )
                yield "File", filepath, r.json()["task_id"]
            except Exception as e:
                print "%s: unable to submit file: %s" % (
                    bold(red("Error")), e
                )
                continue
예제 #30
0
파일: settings.py 프로젝트: ionut97/cuckoo
from django.template.base import TemplateSyntaxError

from cuckoo.common.colors import red
from cuckoo.common.elastic import elastic
from cuckoo.common.mongo import mongo
from cuckoo.core.startup import init_rooter, init_routing
from cuckoo.misc import cwd, decide_cwd

if cwd(root=True) is None:
    decide_cwd(exists=True)

# Connect to MongoDB (mandatory).
if not mongo.init():
    sys.exit(
        red("In order to use the Cuckoo Web Interface it is required to have "
            "MongoDB up-and-running and enabled in Cuckoo. Please refer to our "
            "official documentation as well as the $CWD/conf/reporting.conf file."
            ))

mongo.connect()

# Connect to ElasticSearch (optional).
elastic.init()
elastic.connect()

# In case we have VPNs enabled we need to initialize through the following
# two methods as they verify the interaction with VPNs as well as gather
# which VPNs are available (for representation upon File/URL submission).
init_rooter()
init_routing()

DEBUG = False
예제 #31
0
def import_(ctx, mode, path):
    """Imports an older Cuckoo setup into a new CWD. The old setup should be
    identified by PATH and the new CWD may be specified with the --cwd
    parameter, e.g., "cuckoo --cwd /tmp/cwd import old-cuckoo"."""
    if mode == "symlink" and is_windows():
        sys.exit(red(
            "You can only use the 'symlink' mode on non-Windows platforms."
        ))

    print yellow("You are importing an existing Cuckoo setup. Please")
    print yellow("understand that, depending on the mode taken, if ")
    print yellow("you remove the old Cuckoo setup after this import ")
    print yellow("you may still"), red("lose ALL of your data!")
    print
    print yellow("Additionally, database migrations will be performed ")
    print yellow("in-place*. You won't be able to use your old Cuckoo ")
    print yellow("setup anymore afterwards! However, we'll provide ")
    print yellow("you with the option to create a SQL backup beforehand.")
    print
    print red("TL;DR Cleaning the old setup after the import may")
    print red("corrupt your new setup: its SQL, MongoDB, and ")
    print red("ElasticSearch database may be dropped and, in 'symlink'")
    print red("mode, the analyses removed.")
    print
    print yellow("*: Except for sqlite3 databases in combination with")
    print yellow("   the import 'copy' approach.")
    print

    value = click.confirm(
        "... I've read the above and understand the consequences", False
    )
    if not value:
        sys.exit(red("Aborting operation.. please try again!"))

    try:
        import_cuckoo(ctx.parent.user, mode, path)
    except KeyboardInterrupt:
        print(red("Aborting import of Cuckoo instance.."))
예제 #32
0
def web(ctx, args, host, port, uwsgi, nginx):
    """Operate the Cuckoo Web Interface.

    Use "--help" to get this help message and "help" to find Django's
    manage.py potential subcommands.
    """
    username = ctx.parent.user or getuser()
    if uwsgi:
        print "[uwsgi]"
        print "plugins = python"
        if os.environ.get("VIRTUAL_ENV"):
            print "virtualenv =", os.environ["VIRTUAL_ENV"]
        print "module = cuckoo.web.web.wsgi"
        print "uid =", username
        print "gid =", username
        dirpath = os.path.join(cuckoo.__path__[0], "web", "static")
        print "static-map = /static=%s" % dirpath
        print "# If you're getting errors about the PYTHON_EGG_CACHE, then"
        print "# uncomment the following line and add some path that is"
        print "# writable from the defined user."
        print "# env = PYTHON_EGG_CACHE="
        print "env = CUCKOO_APP=web"
        print "env = CUCKOO_CWD=%s" % cwd()
        return

    if nginx:
        print "upstream _uwsgi_cuckoo_web {"
        print "    server unix:/run/uwsgi/app/cuckoo-web/socket;"
        print "}"
        print
        print "server {"
        print "    listen %s:%d;" % (host, port)
        print
        print "    # Cuckoo Web Interface"
        print "    location / {"
        print "        client_max_body_size 1G;"
        print "        proxy_redirect off;"
        print "        proxy_set_header X-Forwarded-Proto $scheme;"
        print "        uwsgi_pass  _uwsgi_cuckoo_web;"
        print "        include     uwsgi_params;"
        print "    }"
        print "}"
        return

    # Switch to cuckoo/web and add the current path to sys.path as the Web
    # Interface is using local imports here and there.
    # TODO Rename local imports to either cuckoo.web.* or relative imports.
    sys.argv[0] = os.path.abspath(sys.argv[0])
    os.chdir(os.path.join(cuckoo.__path__[0], "web"))
    sys.path.insert(0, ".")

    os.environ.setdefault("DJANGO_SETTINGS_MODULE", "cuckoo.web.web.settings")

    # The Django HTTP server also imports the WSGI module for some reason, so
    # ensure that WSGI is able to load.
    os.environ["CUCKOO_APP"] = "web"
    os.environ["CUCKOO_CWD"] = cwd()

    from django.core.management import execute_from_command_line

    init_console_logging(level=ctx.parent.level)
    Database().connect()

    try:
        execute_from_command_line(
            ("cuckoo", "runserver", "%s:%d" % (host, port), "--noreload")
            if not args else
            ("cuckoo",) + args
        )
    except CuckooCriticalError as e:
        message = red("{0}: {1}".format(e.__class__.__name__, e))
        if len(log.handlers):
            log.critical(message)
        else:
            sys.stderr.write("{0}\n".format(message))
        sys.exit(1)
예제 #33
0
def import_cuckoo(username, mode, dirpath):
    version = identify(dirpath)
    if not version:
        raise CuckooOperationalError(
            "The path that you specified is not a proper Cuckoo setup. Please "
            "point the path to the root of your older Cuckoo setup, i.e., to "
            "the directory containing the cuckoo.py script!"
        )

    # TODO Copy over the configuration and ignore the database.
    if version in ("0.4", "0.4.1", "0.4.2"):
        raise CuckooOperationalError(
            "Importing from version 0.4, 0.4.1, or 0.4.2 is not supported as "
            "there are no database migrations for that version. Please start "
            "from scratch, your configuration would have been obsolete anyway!"
        )

    print "We've identified a Cuckoo Sandbox %s installation!" % version

    if os.path.isdir(cwd()) and os.listdir(cwd()):
        raise CuckooOperationalError(
            "This Cuckoo Working Directory already exists. Please import to "
            "a new/clean Cuckoo Working Directory."
        )

    # Following are various recursive imports.
    from cuckoo.apps import migrate_database
    from cuckoo.main import cuckoo_create

    print "Reading in the old configuration.."

    # Port the older configuration.
    cfg = Config.from_confdir(os.path.join(dirpath, "conf"), loose=True)
    cfg = migrate_conf(cfg, version)

    print "  configuration has been migrated to the latest version!"
    print

    # Create a fresh Cuckoo Working Directory.
    cuckoo_create(username, cfg, quiet=True)

    dburi = cfg["cuckoo"]["database"]["connection"]

    # Ask if the user would like to make a backup of the SQL database and in
    # the case of sqlite3, copy/move/symlink cuckoo.db to the CWD.
    sqldump(dburi, dirpath)
    movesql(dburi, mode, dirpath)

    # Run database migrations.
    if not migrate_database():
        raise CuckooOperationalError(
            "Error migrating your old Cuckoo database!"
        )

    # Link or copy all of the older results to the new CWD.
    import_legacy_analyses(mode, dirpath)

    # Urge the user to run the community command.
    print
    print "You have successfully imported your old version of Cuckoo!"
    print "However, in order to get up-to-date, you'll probably want to"
    print yellow("run the community command"),
    print "by running", red("'cuckoo community'"), "manually."
    print "The community command will fetch the latest monitoring updates"
    print "and Cuckoo Signatures."
예제 #34
0
파일: rooter.py 프로젝트: leixyou/cuckoo
def cuckoo_rooter(socket_path, group, service, iptables, ip):
    try:
        import grp
    except ImportError:
        sys.exit(red(
            "Could not find the `grp` module, the Cuckoo Rooter is only "
            "supported under Linux operating systems."
        ))

    if not service or not os.path.exists(service):
        sys.exit(red(
            "The service binary is not available, please configure it!\n"
            "Note that on CentOS you should provide --service /sbin/service, "
            "rather than using the Ubuntu/Debian default /usr/sbin/service."
        ))

    if not iptables or not os.path.exists(iptables):
        sys.exit(red("The `iptables` binary is not available, eh?!"))

    if not ip or not os.path.exists(ip):
        sys.exit(red("The `ip` binary is not available, eh?!"))

    if os.getuid():
        sys.exit(red(
            "This utility is supposed to be ran as root user. Please invoke "
            "it with the --sudo flag (e.g., 'cuckoo rooter --sudo') so it "
            "will automatically prompt for your password (this naturally only "
            "works for users with sudo capabilities)."
        ))

    if os.path.exists(socket_path):
        os.remove(socket_path)

    server = socket.socket(socket.AF_UNIX, socket.SOCK_DGRAM)
    server.bind(socket_path)

    # Provide the correct file ownership and permission so Cuckoo can use it
    # from an unprivileged process, based on Sean Whalen's routetor.
    try:
        gr = grp.getgrnam(group)
    except KeyError:
        sys.exit(red(
            "The group ('%s') does not exist. Please define the group / user "
            "through which Cuckoo will connect to the rooter, e.g., "
            "'cuckoo rooter -g myuser'." % group
        ))

    os.chown(socket_path, 0, gr.gr_gid)
    os.chmod(socket_path, stat.S_IRUSR | stat.S_IWUSR | stat.S_IWGRP)

    # Initialize global variables.
    s.service = service
    s.iptables = iptables
    s.ip = ip

    while True:
        try:
            command, addr = server.recvfrom(4096)
        except socket.error as e:
            if e.errno == errno.EINTR:
                continue
            raise e

        try:
            obj = json.loads(command)
        except:
            log.info("Received invalid request: %r", command)
            continue

        command = obj.get("command")
        args = obj.get("args", [])
        kwargs = obj.get("kwargs", {})

        if not isinstance(command, basestring) or command not in handlers:
            log.info("Received incorrect command: %r", command)
            continue

        if not isinstance(args, (tuple, list)):
            log.info("Invalid arguments type: %r", args)
            continue

        if not isinstance(kwargs, dict):
            log.info("Invalid keyword arguments: %r", kwargs)
            continue

        for arg in args + kwargs.keys() + kwargs.values():
            if not isinstance(arg, basestring):
                log.info("Invalid argument detected: %r", arg)
                break
        else:
            log.debug(
                "Processing command: %s %s %s", command,
                " ".join(args),
                " ".join("%s=%s" % (k, v) for k, v in kwargs.items())
            )

            output = e = None
            try:
                output = handlers[command](*args, **kwargs)
            except Exception as e:
                log.exception("Error executing command: %s", e)

            server.sendto(json.dumps({
                "output": output,
                "exception": str(e) if e else None,
            }), addr)
예제 #35
0
파일: settings.py 프로젝트: consen/cuckoo
from django.template.base import TemplateSyntaxError

from cuckoo.common.colors import red
from cuckoo.common.elastic import elastic
from cuckoo.common.mongo import mongo
from cuckoo.core.startup import init_rooter, init_routing
from cuckoo.misc import cwd, decide_cwd

if cwd(root=True) is None:
    decide_cwd(exists=True)

# Connect to MongoDB (mandatory).
if not mongo.init():
    sys.exit(red(
        "In order to use the Cuckoo Web Interface it is required to have "
        "MongoDB up-and-running and enabled in Cuckoo. Please refer to our "
        "official documentation as well as the $CWD/conf/reporting.conf file."
    ))

mongo.connect()

# Connect to ElasticSearch (optional).
elastic.init()
elastic.connect()

# In case we have VPNs enabled we need to initialize through the following
# two methods as they verify the interaction with VPNs as well as gather
# which VPNs are available (for representation upon File/URL submission).
init_rooter()
init_routing()
예제 #36
0
def cuckoo_init(level, ctx, cfg=None):
    """Initialize Cuckoo configuration.
    @param quiet: enable quiet mode.
    """
    logo()

    # It would appear this is the first time Cuckoo is being run (on this
    # Cuckoo Working Directory anyway).
    if not os.path.isdir(cwd()) or not os.listdir(cwd()):
        cuckoo_create(ctx.user, cfg)
        sys.exit(0)

    # Determine if this is a proper CWD.
    if not os.path.exists(cwd(".cwd")):
        sys.exit(
            "No proper Cuckoo Working Directory was identified, did you pass "
            "along the correct directory? For new installations please use a "
            "non-existant directory to build up the CWD! You can craft a CWD "
            "manually, but keep in mind that the CWD layout may change along "
            "with Cuckoo releases (and don't forget to fill out '$CWD/.cwd')!")

    init_console_logging(level)

    # Only one Cuckoo process should exist per CWD. Run this check before any
    # files are possibly modified. Note that we mkdir $CWD/pidfiles/ here as
    # its CWD migration rules only kick in after the pidfile check.
    mkdir(cwd("pidfiles"))
    pidfile = Pidfile("cuckoo")
    if pidfile.exists():
        log.error(red("Cuckoo is already running. PID: %s"), pidfile.pid)
        sys.exit(1)

    pidfile.create()

    check_configs()
    check_version()

    ctx.log and init_logging(level)

    # Determine if any CWD updates are required and if so, do them.
    current = open(cwd(".cwd"), "rb").read().strip()
    latest = open(cwd(".cwd", private=True), "rb").read().strip()
    if current != latest:
        migrate_cwd()
        open(cwd(".cwd"), "wb").write(latest)

    # Ensure the user is able to create and read temporary files.
    if not ensure_tmpdir():
        sys.exit(1)

    Database().connect()

    # Load additional Signatures.
    load_signatures()

    init_modules()
    init_tasks()
    init_yara()
    init_binaries()
    init_rooter()
    init_routing()

    signatures = 0
    for sig in cuckoo.signatures:
        if not sig.enabled:
            continue
        signatures += 1

    if not signatures:
        log.warning(
            "It appears that you haven't loaded any Cuckoo Signatures. "
            "Signatures are highly recommended and improve & enrich the "
            "information extracted during an analysis. They also make up "
            "for the analysis score that you see in the Web Interface - so, "
            "pretty important!")
        log.warning(
            "You'll be able to fetch all the latest Cuckoo Signaturs, Yara "
            "rules, and more goodies by running the following command:")
        log.info("$ %s", green(format_command("community")))
예제 #37
0
파일: main.py 프로젝트: swackhamer/cuckoo
def import_(ctx, mode, path):
    """Imports an older Cuckoo setup into a new CWD. The old setup should be
    identified by PATH and the new CWD may be specified with the --cwd
    parameter, e.g., "cuckoo --cwd /tmp/cwd import old-cuckoo"."""
    if mode == "symlink" and is_windows():
        sys.exit(red(
            "You can only use the 'symlink' mode on non-Windows platforms."
        ))

    print yellow("You are importing an existing Cuckoo setup. Please")
    print yellow("understand that, depending on the mode taken, if ")
    print yellow("you remove the old Cuckoo setup after this import ")
    print yellow("you may still"), red("lose ALL of your data!")
    print
    print yellow("Additionally, database migrations will be performed ")
    print yellow("in-place*. You won't be able to use your old Cuckoo ")
    print yellow("setup anymore afterwards! However, we'll provide ")
    print yellow("you with the option to create a SQL backup beforehand.")
    print
    print red("TL;DR Cleaning the old setup after the import may")
    print red("corrupt your new setup: its SQL, MongoDB, and ")
    print red("ElasticSearch database may be dropped and, in 'symlink'")
    print red("mode, the analyses removed.")
    print
    print yellow("*: Except for sqlite3 databases in combination with")
    print yellow("   the import 'copy' approach.")
    print

    value = click.confirm(
        "... I've read the above and understand the consequences", False
    )
    if not value:
        sys.exit(red("Aborting operation.. please try again!"))

    try:
        import_cuckoo(ctx.parent.user, mode, path)
    except KeyboardInterrupt:
        print(red("Aborting import of Cuckoo instance.."))
예제 #38
0
파일: main.py 프로젝트: consen/cuckoo
def web(ctx, args, host, port, uwsgi, nginx):
    """Operate the Cuckoo Web Interface.

    Use "--help" to get this help message and "help" to find Django's
    manage.py potential subcommands.
    """
    username = ctx.parent.user or getuser()
    if uwsgi:
        print "[uwsgi]"
        print "plugins = python"
        if os.environ.get("VIRTUAL_ENV"):
            print "virtualenv =", os.environ["VIRTUAL_ENV"]
        print "module = cuckoo.web.web.wsgi"
        print "uid =", username
        print "gid =", username
        dirpath = os.path.join(cuckoo.__path__[0], "web", "static")
        print "static-map = /static=%s" % dirpath
        print "# If you're getting errors about the PYTHON_EGG_CACHE, then"
        print "# uncomment the following line and add some path that is"
        print "# writable from the defined user."
        print "# env = PYTHON_EGG_CACHE="
        print "env = CUCKOO_APP=web"
        print "env = CUCKOO_CWD=%s" % cwd()
        return

    if nginx:
        print "upstream _uwsgi_cuckoo_web {"
        print "    server unix:/run/uwsgi/app/cuckoo-web/socket;"
        print "}"
        print
        print "server {"
        print "    listen %s:%d;" % (host, port)
        print
        print "    # Cuckoo Web Interface"
        print "    location / {"
        print "        client_max_body_size 1G;"
        print "        proxy_redirect off;"
        print "        proxy_set_header X-Forwarded-Proto $scheme;"
        print "        uwsgi_pass  _uwsgi_cuckoo_web;"
        print "        include     uwsgi_params;"
        print "    }"
        print "}"
        return

    # Switch to cuckoo/web and add the current path to sys.path as the Web
    # Interface is using local imports here and there.
    # TODO Rename local imports to either cuckoo.web.* or relative imports.
    sys.argv[0] = os.path.abspath(sys.argv[0])
    os.chdir(os.path.join(cuckoo.__path__[0], "web"))
    sys.path.insert(0, ".")

    os.environ.setdefault("DJANGO_SETTINGS_MODULE", "cuckoo.web.web.settings")

    # The Django HTTP server also imports the WSGI module for some reason, so
    # ensure that WSGI is able to load.
    os.environ["CUCKOO_APP"] = "web"
    os.environ["CUCKOO_CWD"] = cwd()

    from django.core.management import execute_from_command_line

    init_console_logging(level=ctx.parent.level)
    Database().connect()

    try:
        execute_from_command_line(
            ("cuckoo", "runserver", "%s:%d" % (host, port))
            if not args else
            ("cuckoo",) + args
        )
    except CuckooCriticalError as e:
        message = red("{0}: {1}".format(e.__class__.__name__, e))
        if len(log.handlers):
            log.critical(message)
        else:
            sys.stderr.write("{0}\n".format(message))
        sys.exit(1)
예제 #39
0
파일: main.py 프로젝트: consen/cuckoo
def cuckoo_init(level, ctx, cfg=None):
    """Initialize Cuckoo configuration.
    @param quiet: enable quiet mode.
    """
    logo()

    # It would appear this is the first time Cuckoo is being run (on this
    # Cuckoo Working Directory anyway).
    if not os.path.isdir(cwd()) or not os.listdir(cwd()):
        cuckoo_create(ctx.user, cfg)
        sys.exit(0)

    # Determine if this is a proper CWD.
    if not os.path.exists(cwd(".cwd")):
        sys.exit(
            "No proper Cuckoo Working Directory was identified, did you pass "
            "along the correct directory? For new installations please use a "
            "non-existant directory to build up the CWD! You can craft a CWD "
            "manually, but keep in mind that the CWD layout may change along "
            "with Cuckoo releases (and don't forget to fill out '$CWD/.cwd')!"
        )

    init_console_logging(level)

    # Only one Cuckoo process should exist per CWD. Run this check before any
    # files are possibly modified. Note that we mkdir $CWD/pidfiles/ here as
    # its CWD migration rules only kick in after the pidfile check.
    mkdir(cwd("pidfiles"))
    pidfile = Pidfile("cuckoo")
    if pidfile.exists():
        log.error(red("Cuckoo is already running. PID: %s"), pidfile.pid)
        sys.exit(1)

    pidfile.create()

    check_configs()
    check_version()

    ctx.log and init_logging(level)

    # Determine if any CWD updates are required and if so, do them.
    current = open(cwd(".cwd"), "rb").read().strip()
    latest = open(cwd(".cwd", private=True), "rb").read().strip()
    if current != latest:
        migrate_cwd()
        open(cwd(".cwd"), "wb").write(latest)

    Database().connect()

    # Load additional Signatures.
    load_signatures()

    init_modules()
    init_tasks()
    init_yara()
    init_binaries()
    init_rooter()
    init_routing()

    signatures = 0
    for sig in cuckoo.signatures:
        if not sig.enabled:
            continue
        signatures += 1

    if not signatures:
        log.warning(
            "It appears that you haven't loaded any Cuckoo Signatures. "
            "Signatures are highly recommended and improve & enrich the "
            "information extracted during an analysis. They also make up "
            "for the analysis score that you see in the Web Interface - so, "
            "pretty important!"
        )
        log.warning(
            "You'll be able to fetch all the latest Cuckoo Signaturs, Yara "
            "rules, and more goodies by running the following command:"
        )
        raw = cwd(raw=True)
        if raw == "." or raw == "~/.cuckoo":
            command = "cuckoo community"
        elif " " in raw or "'" in raw:
            command = 'cuckoo --cwd "%s" community' % raw
        else:
            command = "cuckoo --cwd %s community" % raw

        log.info("$ %s", green(command))
예제 #40
0
def submit_tasks(target, options, package, custom, owner, timeout, priority,
                 machine, platform, memory, enforce_timeout, clock, tags,
                 remote, pattern, maxcount, is_unique, is_url, is_baseline,
                 is_shuffle):
    db = Database()

    data = dict(
        package=package or "",
        timeout=timeout,
        options=options,
        priority=priority,
        machine=machine,
        platform=platform,
        custom=custom,
        owner=owner,
        tags=tags,
        memory="1" if memory else "0",
        enforce_timeout="1" if enforce_timeout else "0",
        clock=clock,
        unique="1" if is_unique else "0",
    )

    if is_baseline:
        if remote:
            print "Remote baseline support has not yet been implemented."
            return

        task_id = db.add_baseline(timeout, owner, machine, memory)
        yield "Baseline", machine, task_id
        return

    if is_url and is_unique:
        print "URL doesn't have --unique support yet."
        return

    if is_url:
        for url in target:
            if not remote:
                data.pop("unique", None)
                task_id = db.add_url(to_unicode(url), **data)
                yield "URL", url, task_id
                continue

            data["url"] = to_unicode(url)
            try:
                r = requests.post("http://%s/tasks/create/url" % remote,
                                  data=data)
                yield "URL", url, r.json()["task_id"]
            except Exception as e:
                print "%s: unable to submit URL: %s" % (bold(red("Error")), e)
    else:
        files = []
        for path in target:
            files.extend(enumerate_files(os.path.abspath(path), pattern))

        if is_shuffle:
            random.shuffle(files)

        for filepath in files:
            if not os.path.getsize(filepath):
                print "%s: sample %s (skipping file)" % (bold(
                    yellow("Empty")), filepath)
                continue

            if maxcount is not None:
                if not maxcount:
                    break
                maxcount -= 1

            if not remote:
                if is_unique:
                    sha256 = File(filepath).get_sha256()
                    if db.find_sample(sha256=sha256):
                        yield "File", filepath, None
                        continue

                data.pop("unique", None)
                task_id = db.add_path(file_path=filepath, **data)
                yield "File", filepath, task_id
                continue

            files = {
                "file": (os.path.basename(filepath), open(filepath, "rb")),
            }

            try:
                r = requests.post("http://%s/tasks/create/file" % remote,
                                  data=data,
                                  files=files)
                yield "File", filepath, r.json()["task_id"]
            except Exception as e:
                print "%s: unable to submit file: %s" % (bold(red("Error")), e)
                continue
예제 #41
0
def check_version(ignore_vuln=False):
    """Check version of Cuckoo."""
    if not config("cuckoo:cuckoo:version_check"):
        return

    ignore_vuln = ignore_vuln or config("cuckoo:cuckoo:ignore_vulnerabilities")

    import pkg_resources

    print(" Checking for updates...")

    try:
        r = requests.get("https://cuckoosandbox.org/updates.json",
                         params={"version": version},
                         timeout=6)
        r.raise_for_status()
        r = r.json()
    except (requests.RequestException, ValueError) as e:
        print(red(" Error checking for the latest Cuckoo version: %s!" % e))
        return

    try:
        old = StrictVersion(version) < StrictVersion(r["version"])
    except ValueError:
        old = True

    warnings = []
    for deptype, vulns in r.get("vulnerable", {}).iteritems():
        for dep in vulns:
            compare = dep.get("highest") or dep.get("lowest")

            # Check if any of the mentioned Python dependencies are installed
            if deptype == "pydep":
                try:
                    v = pkg_resources.get_distribution(
                        dep["name"]).parsed_version
                except (pkg_resources.DistributionNotFound, ValueError):
                    continue

            # See if the mentioned virtualization software is used
            elif deptype == "machinery":
                if config("cuckoo:cuckoo:machinery") != dep["name"]:
                    continue

                # If the version number cannot be determined, raise a warning
                # to be sure. Virtualization vulnerabilities can potentially
                # cause a lot of damage
                v = cuckoo.machinery.plugins[dep["name"]].version()
                if not v:
                    warnings.append(
                        bold(
                            red("Potentially vulnerable %s version installed. "
                                "Failed to retrieve its version. Update if version"
                                " is: %s" % (dep["name"], compare))))
                    continue

            else:
                continue

            warn = False
            # If a range is specified, check if the current version falls
            # within the range.
            if dep.get("highest") and dep.get("lowest"):
                lv = LooseVersion(str(v))
                if (lv >= LooseVersion(dep["lowest"])
                        and lv <= LooseVersion(dep["highest"])):
                    warn = True

            # If no range is specified, use the specified operator to see if
            # the installed version is
            # 'if <operator> highest/lowest specified'
            elif cmp_version(str(v), compare, dep["op"]):
                warn = True

            # Warn the user the dependency must be updated/
            if warn:
                info = dep.get("info")
                message = "Vulnerable version of %s installed (%s). It is " \
                          "highly recommended to update. Please update and " \
                          "restart Cuckoo." % (dep["name"], v)

                if deptype == "pydep":
                    message += " 'pip install %s%s'" % (dep["name"],
                                                        dep["recommended"])

                else:
                    message += " Recommended version: %s" % dep["recommended"]

                message = bold(red(message))

                if info:
                    message += yellow("\nAdditional information: %s" % info)

                warnings.append(message)

    if warnings:
        print(color(bold(red("Vulnerable dependencies found\n")), 5))
    for warning in warnings:
        print("--> %s\n" % color(warning, 4))

    if warnings and not ignore_vuln:
        print(
            "This check can be disabled by enabling "
            "'ignore_vulnerabilities' in cuckoo.conf under the "
            "[cuckoo] section")
        sys.exit(1)

    if old:
        msg = "Cuckoo Sandbox version %s is available now." % r["version"]
        print(red(" Outdated! ") + msg)
    else:
        print(green(" You're good to go!"))

    print("\n Our latest blogposts:")
    for blogpost in r["blogposts"]:
        print(" * %s, %s." % (yellow(blogpost["title"]), blogpost["date"]))
        print("   %s" % red(blogpost["oneline"]))
        print("   More at %s" % blogpost["url"])
        print("")
    return r
예제 #42
0
파일: config.py 프로젝트: songofhack/cuckoo
def log_error(message, *args):
    """Prints to stderr if no logging has been initialized yet."""
    if not logging.getLogger().handlers:
        print >> sys.stderr, red("Configuration error: " + message % args)
    else:
        log.error(message, *args)
예제 #43
0
def import_cuckoo(username, mode, dirpath):
    version = identify(dirpath)
    if not version:
        raise CuckooOperationalError(
            "The path that you specified is not a proper Cuckoo setup. Please "
            "point the path to the root of your older Cuckoo setup, i.e., to "
            "the directory containing the cuckoo.py script!")

    # TODO Copy over the configuration and ignore the database.
    if version in ("0.4", "0.4.1", "0.4.2"):
        raise CuckooOperationalError(
            "Importing from version 0.4, 0.4.1, or 0.4.2 is not supported as "
            "there are no database migrations for that version. Please start "
            "from scratch, your configuration would have been obsolete anyway!"
        )

    print "We've identified a Cuckoo Sandbox %s installation!" % version

    if os.path.isdir(cwd()) and os.listdir(cwd()):
        raise CuckooOperationalError(
            "This Cuckoo Working Directory already exists. Please import to "
            "a new/clean Cuckoo Working Directory.")

    # Following are various recursive imports.
    from cuckoo.apps import migrate_database
    from cuckoo.main import cuckoo_create

    print "Reading in the old configuration.."

    # Port the older configuration.
    cfg = Config.from_confdir(os.path.join(dirpath, "conf"), loose=True)
    cfg = migrate_conf(cfg, version)

    print "  configuration has been migrated to the latest version!"
    print

    # Create a fresh Cuckoo Working Directory.
    cuckoo_create(username, cfg, quiet=True)

    dburi = cfg["cuckoo"]["database"]["connection"]

    # Ask if the user would like to make a backup of the SQL database and in
    # the case of sqlite3, copy/move/symlink cuckoo.db to the CWD.
    sqldump(dburi, dirpath)
    movesql(dburi, mode, dirpath)

    # Run database migrations.
    if not migrate_database():
        raise CuckooOperationalError(
            "Error migrating your old Cuckoo database!")

    # Link or copy all of the older results to the new CWD.
    import_legacy_analyses(mode, dirpath)

    # Urge the user to run the community command.
    print
    print "You have successfully imported your old version of Cuckoo!"
    print "However, in order to get up-to-date, you'll probably want to"
    print yellow("run the community command"),
    print "by running", red("'cuckoo community'"), "manually."
    print "The community command will fetch the latest monitoring updates"
    print "and Cuckoo Signatures."
예제 #44
0
def cuckoo_rooter(socket_path, group, service, iptables, ip):
    try:
        import grp
    except ImportError:
        sys.exit(red(
            "Could not find the `grp` module, the Cuckoo Rooter is only "
            "supported under Linux operating systems."
        ))

    if not service or not os.path.exists(service):
        sys.exit(red(
            "The service binary is not available, please configure it!\n"
            "Note that on CentOS you should provide --service /sbin/service, "
            "rather than using the Ubuntu/Debian default /usr/sbin/service."
        ))

    if not iptables or not os.path.exists(iptables):
        sys.exit(red("The `iptables` binary is not available, eh?!"))

    if not ip or not os.path.exists(ip):
        sys.exit(red("The `ip` binary is not available, eh?!"))

    if os.getuid():
        sys.exit(red(
            "This utility is supposed to be ran as root user. Please invoke "
            "it with the --sudo flag (e.g., 'cuckoo rooter --sudo') so it "
            "will automatically prompt for your password (this naturally only "
            "works for users with sudo capabilities)."
        ))

    if os.path.exists(socket_path):
        os.remove(socket_path)

    server = socket.socket(socket.AF_UNIX, socket.SOCK_DGRAM)
    server.bind(socket_path)

    # Provide the correct file ownership and permission so Cuckoo can use it
    # from an unprivileged process, based on Sean Whalen's routetor.
    try:
        gr = grp.getgrnam(group)
    except KeyError:
        sys.exit(red(
            "The group ('%s') does not exist. Please define the group / user "
            "through which Cuckoo will connect to the rooter, e.g., "
            "'cuckoo rooter -g myuser'." % group
        ))

    os.chown(socket_path, 0, gr.gr_gid)
    os.chmod(socket_path, stat.S_IRUSR | stat.S_IWUSR | stat.S_IWGRP)

    # Initialize global variables.
    s.service = service
    s.iptables = iptables
    s.iptables_save = "/sbin/iptables-save"
    s.iptables_restore = "/sbin/iptables-restore"
    s.ip = ip

    # Simple object to allow a signal handler to stop the rooter loop
    class Run(object):
        def __init__(self):
            self.run = True
    do = Run()

    def handle_sigterm(sig, f):
        do.run = False
        server.shutdown(socket.SHUT_RDWR)
        server.close()
        cleanup_rooter()

    signal.signal(signal.SIGTERM, handle_sigterm)

    while do.run:
        try:
            command, addr = server.recvfrom(4096)
        except socket.error as e:
            if e.errno == errno.EINTR:
                continue
            elif e.errno == errno.EBADF and not do.run:
                continue

            raise e

        try:
            obj = json.loads(command)
        except:
            log.info("Received invalid request: %r", command)
            continue

        command = obj.get("command")
        args = obj.get("args", [])
        kwargs = obj.get("kwargs", {})

        if not isinstance(command, basestring) or command not in handlers:
            log.info("Received incorrect command: %r", command)
            continue

        if not isinstance(args, (tuple, list)):
            log.info("Invalid arguments type: %r", args)
            continue

        if not isinstance(kwargs, dict):
            log.info("Invalid keyword arguments: %r", kwargs)
            continue

        for arg in args + kwargs.keys() + kwargs.values():
            if not isinstance(arg, basestring):
                log.info("Invalid argument detected: %r", arg)
                break
        else:
            log.info(
                "Processing command: %s %s %s", command,
                " ".join(args),
                " ".join("%s=%s" % (k, v) for k, v in kwargs.items())
            )

            output = e = None
            try:
                output = handlers[command](*args, **kwargs)
            except Exception as e:
                log.exception("Error executing command: %s", e)

            server.sendto(json.dumps({
                "output": output,
                "exception": str(e) if e else None,
            }), addr)