Repository: kpcyrd/sn0int (language: rust)

Issue:
Quickstart for users
We do not ship any modules by default and a user currently needs to copy or symlink the content of the `modules/` folder to `~/.local/share/sn0int/modules/` or manually pick all relevant modules. If we detect an empty modules folder we should suggest running the `quickstart` command which would query the api for featured modules and install them.

```

                   ___/           .
     ____ , __   .'  /\ ` , __   _/_
    (     |'  `. |  / | | |'  `.  |
    `--.  |    | |,'  | | |    |  |
   \___.' /    | /`---' / /    |  \__/

        osint | recon | security

[+] Connecting to database
[+] Loaded 0 modules
[*] No modules found, run quickstart to install default modules
[sn0int][default] > quickstart
[installing module]
[installing module]
[installing module]
[...]
[sn0int][default] > 
```

This command should be exposed as `sn0int quickstart` as well.


Discussion / hints:
Resolved in 2887750

Fix patch:
diff --git a/Cargo.lock b/Cargo.lock
index 98ec9c0c..3d8f8f59 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -2461,7 +2461,7 @@ dependencies = [
  "sloppy-rfc4880 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "sn0int-common 0.4.0",
  "structopt 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)",
- "syscallz 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "syscallz 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "tar 0.4.20 (registry+https://github.com/rust-lang/crates.io-index)",
  "threadpool 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "tokio 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -2647,7 +2647,7 @@ dependencies = [
 
 [[package]]
 name = "syscallz"
-version = "0.9.0"
+version = "0.10.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -3582,7 +3582,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)" = "f92e629aa1d9c827b2bb8297046c1ccffc57c99b947a680d3ccff1f136a3bee9"
 "checksum synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a393066ed9010ebaed60b9eafa373d4b1baac186dd7e008555b0f702b51945b6"
 "checksum synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "73687139bf99285483c96ac0add482c3776528beac1d97d444f6e91f203a2015"
-"checksum syscallz 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b88b878ffd1e8499e7d4f8ab3e2aa28f9cfdf78e782be23d4dfba23440f05489"
+"checksum syscallz 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bcbb1ce2c374d32565800b2559f9d24729dece03cd49966b9a43480436136ddb"
 "checksum tar 0.4.20 (registry+https://github.com/rust-lang/crates.io-index)" = "a303ba60a099fcd2aaa646b14d2724591a96a75283e4b7ed3d1a1658909d9ae2"
 "checksum tempfile 3.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "7e91405c14320e5c79b3d148e1c86f40749a36e490642202a31689cb1a3452b2"
 "checksum tendril 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "707feda9f2582d5d680d733e38755547a3e8fb471e7ba11452ecfd9ce93a5d3b"
diff --git a/Cargo.toml b/Cargo.toml
index b3623310..ab1706a1 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -64,7 +64,7 @@ tokio = "0.1.14"
 [target.'cfg(target_os="linux")'.dependencies]
 caps = "0.3"
 #syscallz = { path="../syscallz-rs" }
-syscallz = "0.9"
+syscallz = "0.10"
 nix = "0.13"
 
 [target.'cfg(target_os="openbsd")'.dependencies]
diff --git a/ci/boxxy_stage1.txt b/ci/boxxy_stage1.txt
index fb2d106a..5b5165d8 100644
--- a/ci/boxxy_stage1.txt
+++ b/ci/boxxy_stage1.txt
@@ -1,3 +1,5 @@
 stage1
 ls
+echo checkpoint1
+id
 echo sandbox fail
diff --git a/ci/integration.py b/ci/integration.py
new file mode 100755
index 00000000..76a7d489
--- /dev/null
+++ b/ci/integration.py
@@ -0,0 +1,123 @@
+#!/usr/bin/env python3
+import subprocess
+from subprocess import DEVNULL, PIPE
+import tempfile
+import json
+import sys
+
+
+def _sn0int(tempdir, binary, args, piped_stdout=False):
+    return subprocess.Popen(
+        ['/usr/bin/env', 'HOME='+tempdir, binary] + args,
+        stdin=PIPE,
+        stdout=PIPE if piped_stdout else None,
+    )
+
+
+def sn0int(tempdir, binary, cmds):
+    p = _sn0int(tempdir, binary, [])
+    for cmd in cmds:
+        p.stdin.write((cmd + '\n').encode('utf-8'))
+    p.communicate()
+    if p.returncode != 0:
+        raise Exception('process failed')
+
+
+def sn0int_select(tempdir, binary, query):
+    p = _sn0int(tempdir, binary, ['select', '--json'] + query, piped_stdout=True)
+    stdout, _ = p.communicate()
+    lines = filter(None, stdout.decode('utf-8').split('\n'))
+    return [json.loads(x) for x in lines]
+
+
+def main(tempdir, binary):
+    print('[*] setting up workspace')
+    sn0int(tempdir, binary, [])
+
+    print('[*] adding domain')
+    sn0int(tempdir, binary, [
+        'add domain',
+        'example.com',
+        'select domains',
+    ])
+
+    print('[*] testing db for domain')
+    domains = sn0int_select(tempdir, binary, ['domains'])
+    assert domains == [{'id': 1, 'value': 'example.com', 'unscoped': False}]
+
+    print('[*] installing modules')
+    sn0int(tempdir, binary, [
+        'mod install kpcyrd/ctlogs',
+        'mod install kpcyrd/dns-resolve',
+        'mod install kpcyrd/url-scan',
+        'mod install kpcyrd/geoip',
+    ])
+
+    print('[*] running ctlogs')
+    sn0int(tempdir, binary, [
+        'use ctlogs',
+        'run',
+        'select subdomains',
+    ])
+
+    print('[*] testing db for subdomains')
+    subdomains = sn0int_select(tempdir, binary, ['subdomains'])
+    assert {x['value'] for x in subdomains} == {
+        'www.example.com',
+        'm.example.com',
+        'dev.example.com',
+        'products.example.com',
+        'support.example.com',
+    }
+
+    print('[*] running dns-resolve')
+    sn0int(tempdir, binary, [
+        'use dns-resolve',
+        'run',
+        'select ipaddrs',
+    ])
+
+    print('[*] testing db for ipaddrs')
+    ipaddrs = sn0int_select(tempdir, binary, ['ipaddrs'])
+    assert len(ipaddrs) >= 1
+
+    print('[*] running url-scan')
+    sn0int(tempdir, binary, [
+        'use url-scan',
+        'run',
+        'select urls',
+    ])
+
+    print('[*] testing db for urls')
+    urls = sn0int_select(tempdir, binary, ['urls'])
+    assert {(x['value'], x['status']) for x in urls} == {
+        ('http://www.example.com/', 200),
+        ('https://www.example.com/', 200),
+    }
+
+    print('[*] running geoip')
+    sn0int(tempdir, binary, [
+        'use geoip',
+        'run',
+        'select ipaddrs',
+    ])
+
+    print('[*] testing db for ipaddrs again')
+    ipaddrs2 = sn0int_select(tempdir, binary, ['ipaddrs'])
+    assert ipaddrs != ipaddrs2
+
+    print('')
+    print('\t###########')
+    print('\t# SUCCESS #')
+    print('\t###########')
+    print('')
+
+
+if __name__ == '__main__':
+    try:
+        binary = sys.argv[1]
+    except IndexError:
+        print('Usage: %s target/release/sn0int' % sys.argv[0])
+    else:
+        with tempfile.TemporaryDirectory(prefix='sn0int-') as tempdir:
+            main(tempdir, binary)
diff --git a/docs/install.rst b/docs/install.rst
index 950eab58..c338c5df 100644
--- a/docs/install.rst
+++ b/docs/install.rst
@@ -22,7 +22,7 @@ Debian testing/Debian sid/Kali
 
 .. code-block:: bash
 
-    $ apt install cargo libsqlite3-dev libseccomp-dev
+    $ apt install build-essential cargo libsqlite3-dev libseccomp-dev
     $ git clone https://github.com/kpcyrd/sn0int.git
     $ cd sn0int
     $ cargo install -f --path .
@@ -37,7 +37,7 @@ instructions instead.
 
 .. code-block:: bash
 
-    $ apt install libsqlite3-dev libseccomp-dev
+    $ apt install build-essential libsqlite3-dev libseccomp-dev
     $ git clone https://github.com/kpcyrd/sn0int.git
     $ cd sn0int
     $ cargo install -f --path .
diff --git a/src/sandbox/seccomp.rs b/src/sandbox/seccomp.rs
index 56547c7f..e1411d73 100644
--- a/src/sandbox/seccomp.rs
+++ b/src/sandbox/seccomp.rs
@@ -1,5 +1,5 @@
 use crate::errors::*;
-use syscallz::{Context, Syscall};
+use syscallz::{Context, Syscall, Action};
 
 
 pub fn init() -> Result<()> {
@@ -12,11 +12,8 @@ pub fn init() -> Result<()> {
     ctx.allow_syscall(Syscall::futex)?;
     ctx.allow_syscall(Syscall::sigaltstack)?;
     ctx.allow_syscall(Syscall::munmap)?;
-    //ctx.allow_syscall(Syscall::openat)?;
-    //#[cfg(not(target_arch = "aarch64"))]
-    //ctx.allow_syscall(Syscall::open)?;
     ctx.allow_syscall(Syscall::fcntl)?;
-    #[cfg(target_arch = "arm")]
+    #[cfg(not(any(target_arch = "x86_64", target_arch = "aarch64")))]
     ctx.allow_syscall(Syscall::fcntl64)?;
     ctx.allow_syscall(Syscall::uname)?;
     ctx.allow_syscall(Syscall::close)?;
@@ -26,6 +23,8 @@ pub fn init() -> Result<()> {
     ctx.allow_syscall(Syscall::sched_getaffinity)?;
     ctx.allow_syscall(Syscall::socket)?;
     ctx.allow_syscall(Syscall::connect)?;
+    #[cfg(target_arch = "x86")]
+    ctx.allow_syscall(Syscall::socketcall)?;
     #[cfg(not(target_arch = "aarch64"))]
     ctx.allow_syscall(Syscall::epoll_wait)?;
     ctx.allow_syscall(Syscall::epoll_pwait)?;
@@ -41,7 +40,7 @@ pub fn init() -> Result<()> {
     ctx.allow_syscall(Syscall::getsockopt)?;
     #[cfg(not(target_arch = "arm"))]
     ctx.allow_syscall(Syscall::mmap)?;
-    #[cfg(target_arch = "arm")]
+    #[cfg(not(any(target_arch = "x86_64", target_arch = "aarch64")))]
     ctx.allow_syscall(Syscall::mmap2)?;
     ctx.allow_syscall(Syscall::mprotect)?;
     ctx.allow_syscall(Syscall::clone)?;
@@ -50,6 +49,9 @@ pub fn init() -> Result<()> {
     ctx.allow_syscall(Syscall::sched_yield)?;
     ctx.allow_syscall(Syscall::setsockopt)?;
     ctx.allow_syscall(Syscall::madvise)?;
+    #[cfg(target_arch = "x86")]
+    ctx.allow_syscall(Syscall::time)?;
+    ctx.allow_syscall(Syscall::clock_gettime)?;
     ctx.allow_syscall(Syscall::nanosleep)?;
     ctx.allow_syscall(Syscall::exit)?;
     ctx.allow_syscall(Syscall::exit_group)?;
@@ -57,6 +59,10 @@ pub fn init() -> Result<()> {
     ctx.allow_syscall(Syscall::rt_sigprocmask)?;
     ctx.allow_syscall(Syscall::getpeername)?;
 
+    ctx.set_action_for_syscall(Action::Errno(1), Syscall::openat)?;
+    #[cfg(not(any(target_arch = "x86_64", target_arch = "aarch64")))]
+    ctx.set_action_for_syscall(Action::Errno(1), Syscall::open)?;
+
     ctx.load()?;
 
     Ok(())
diff --git a/src/shell.rs b/src/shell.rs
index 0872eb06..29de554e 100644
--- a/src/shell.rs
+++ b/src/shell.rs
@@ -400,7 +400,7 @@ pub fn init(args: &Args, config: Config, verbose_init: bool) -> Result<Readline>
     let engine = Engine::new(verbose_init)?;
     let keyring = KeyRing::init()?;
 
-    if engine.list().is_empty() {
+    if verbose_init && engine.list().is_empty() {
         term::success("No modules found, run quickstart to install default modules");
     }
 


Test patch: