Esempio n. 1
0
def test_ls(policy_parser: PolicyParser, setup_testdir):
    ls = which('ls')

    text = """
    #![profile '%s']

    fs('%s', read|exec)
    fs('/etc/ld.so.cache', read|exec|getattr)
    fs('/usr/lib/ld-2.31.so', read|exec|getattr)
    fs('/lib64/ld-linux-x86-64.so.2', read)
    fs('/usr/lib/libcap.so.2', read|exec|getattr)
    fs('/usr/lib/libc.so.6', read|exec|getattr)
    fs('/usr/lib/locale/locale-archive', read|getattr)
    fs('/usr/share', exec)
    fs('/proc', exec)
    fs('/tmp/bpfbox', read|exec|getattr)
    fs('/tmp/bpfbox/a', getattr)
    fs('/tmp/bpfbox/b', getattr)
    fs('/tmp/bpfbox/c', getattr)
    fs('/tmp/bpfbox/d', getattr)
    proc('/usr/bin/ls', getattr)
    """ % (ls, ls)

    policy_parser.process_policy_text(text)

    out = subprocess.check_output([ls, '/tmp/bpfbox']).decode('utf-8')
    assert out.strip() == '\n'.join(sorted(os.listdir('/tmp/bpfbox')))
Esempio n. 2
0
def test_open_implicit_taint(policy_parser: PolicyParser, setup_testdir):
    text = """
    #![profile '%s']
    """ % (OPEN_PATH)

    policy_parser.process_policy_text(text)

    with pytest.raises(subprocess.CalledProcessError):
        subprocess.check_output([OPEN_PATH])
Esempio n. 3
0
def test_fs_policy_missing_file(policy_parser: PolicyParser, setup_testdir):

    text = """
    #![profile '%s']

    fs('/sdfoihsdfo/asdihsdfoui/asdpisdhf', read|write|exec)
    proc('/sdfoihsdfo/asdihsdfoui/asdpisdhf', getattr)
    """ % (OPEN_PATH)

    policy_parser.process_policy_text(text)
Esempio n. 4
0
 def generate_policy(self):
     logger.info('Generating policy...')
     policy_files = []
     for (dirpath, dirnames, filenames) in os.walk(defs.policy_directory):
         policy_files.extend([os.path.join(dirpath, f) for f in filenames])
     for f in policy_files:
         logger.info(f'Generating policy for {f}...')
         try:
             from bpfbox.dsl import PolicyParser
             PolicyParser.process_policy_file(f)
         except Exception as e:
             logger.error(f'Unable to generate policy for {f}!', exc_info=e)
             return
     logger.info('Generated policy successfully!')
Esempio n. 5
0
def test_open_link_policy(policy_parser: PolicyParser, setup_testdir):
    text = """
    #![profile '%s']

    #[taint]
    fs('/tmp/bpfbox/a', read)

    fs('/tmp/bpfbox', write)
    fs('/tmp/bpfbox/a', link)

    """ % (OPEN_PATH)

    policy_parser.process_policy_text(text)

    subprocess.check_call([OPEN_PATH, 'link'])
Esempio n. 6
0
def test_ipc_policy(policy_parser: PolicyParser, setup_testdir):
    sleep_path = which('sleep')
    text = """
    #![profile '%s']

    #[taint]
    signal(self, sigcheck)

    signal('%s', sigkill)
    """ % (IPC_PATH, sleep_path)

    policy_parser.process_policy_text(text)

    target_pid = subprocess.Popen([sleep_path, '10']).pid

    rc = subprocess.Popen([IPC_PATH, 'kill-target', str(target_pid)]).wait()
    assert rc == 0
Esempio n. 7
0
def test_net_policy(policy_parser: PolicyParser, setup_testdir):
    text = """
    #![profile '%s']

    #[taint]
    net(inet,  create)

    #[allow] {
        net(inet6, create|connect)
    }
    """ % (NET_PATH)

    policy_parser.process_policy_text(text)

    subprocess.check_call([NET_PATH, 'inet-create-and-connect'])

    with pytest.raises(subprocess.CalledProcessError):
        subprocess.check_call([NET_PATH, 'create-unix'])
Esempio n. 8
0
def test_open_complex_policy_implicit_allow(policy_parser: PolicyParser,
                                            setup_testdir):
    text = """
    #![profile '%s']

    #[taint]
    fs('/tmp/bpfbox/a', read)

    fs('/tmp/bpfbox/a', read|write)
    fs('/tmp/bpfbox/b', append)
    fs('/tmp/bpfbox/c', read)
    fs('/tmp/bpfbox/d', exec)

    """ % (OPEN_PATH)

    policy_parser.process_policy_text(text)

    subprocess.check_call([OPEN_PATH, 'complex'])
Esempio n. 9
0
def test_open_complex_policy_no_execute_permission(policy_parser: PolicyParser,
                                                   setup_testdir):
    text = """
    #![profile '%s']

    #[taint]
    fs('/tmp/bpfbox/a', read)

    #[allow] {
        fs('/tmp/bpfbox/a', read|write)
        fs('/tmp/bpfbox/b', append)
        fs('/tmp/bpfbox/c', read)
    }

    """ % (OPEN_PATH)

    policy_parser.process_policy_text(text)

    with pytest.raises(subprocess.CalledProcessError):
        subprocess.check_call([OPEN_PATH, 'complex'])
Esempio n. 10
0
def test_open_procfs_rules(policy_parser: PolicyParser, setup_testdir):
    sleep_path = which('sleep')

    text = """
    #![profile '%s']

    #[taint]
    fs('/tmp/bpfbox/a', read)

    fs('/proc', exec)
    proc('%s', read|exec)
    """ % (OPEN_PATH, sleep_path)

    policy_parser.process_policy_text(text)

    # /proc/self should always work
    subprocess.check_call([OPEN_PATH, 'proc-self'])

    sleep_pid = subprocess.Popen([sleep_path, '10']).pid
    subprocess.check_call([OPEN_PATH, 'proc-other', str(sleep_pid)])
Esempio n. 11
0
def test_net_policy_smoke(policy_parser: PolicyParser, setup_testdir):
    text = """
    #![profile '%s']

    #[taint] {
        net(inet,  bind|connect)
        net(inet6, bind|connect)
    }

    #[allow] {
        net(inet,  accept|listen|send|recv)
        net(inet6, accept|listen|send|recv)
    }

    #[audit] {
        net(inet,  create|shutdown)
        net(inet6, create|shutdown)
    }
    """ % (NET_PATH)

    policy_parser.process_policy_text(text)
Esempio n. 12
0
def test_open_proc_other_not_allowed(policy_parser: PolicyParser,
                                     setup_testdir):
    sleep_path = which('sleep')

    text = """
    #![profile '%s']

    #[taint]
    fs('/tmp/bpfbox/a', read)

    fs('/proc', exec)
    """ % (OPEN_PATH)

    policy_parser.process_policy_text(text)

    # /proc/self should always work
    subprocess.check_call([OPEN_PATH, 'proc-self'])

    sleep_pid = subprocess.Popen([sleep_path, '10']).pid
    with pytest.raises(subprocess.CalledProcessError):
        subprocess.check_call([OPEN_PATH, 'proc-other', str(sleep_pid)])
Esempio n. 13
0
def test_dsl_smoke(policy_parser: PolicyParser):
    text = """
    #![profile "/usr/bin/ls"]

    #[allow] {
        #[audit]
        fs("/tmp/bpfbox/a", read|write|exec)
        #[taint]
        fs("/tmp/bpfbox/b", getattr|setattr|ioctl|rm)
    }

    fs("/tmp/bpfbox/c", read)

    #[taint]
    fs("/tmp/bpfbox/d", write)

    #[allow]
    #[audit] {
        #[taint]
        net(inet, bind|connect|accept)
        proc("/foo/bar/qux", read)
    }

    #[audit]
    signal('/usr/bin/grep', sigkill|sigchld)

    #[allow]
    ptrace(self)
    """

    policy = policy_parser.parse_policy_text(text)

    pprint(policy)

    assert policy.profile == '/usr/bin/ls'

    assert len(policy.rules) == 8

    assert policy.rules[0].action == BPFBOX_ACTION.ALLOW
    assert policy.rules[0].access == FS_ACCESS.READ
    assert policy.rules[0].pathname == '/tmp/bpfbox/c'

    assert policy.rules[1].action == BPFBOX_ACTION.TAINT
    assert policy.rules[1].access == FS_ACCESS.WRITE
    assert policy.rules[1].pathname == '/tmp/bpfbox/d'

    assert policy.rules[2].action == BPFBOX_ACTION.AUDIT
    assert policy.rules[2].access == IPC_ACCESS.SIGKILL | IPC_ACCESS.SIGCHLD
    assert policy.rules[2].other_exe == '/usr/bin/grep'

    assert policy.rules[3].action == BPFBOX_ACTION.ALLOW
    assert policy.rules[3].access == IPC_ACCESS.PTRACE
    assert policy.rules[3].other_exe == 'self'

    assert policy.rules[4].action == BPFBOX_ACTION.ALLOW | BPFBOX_ACTION.AUDIT
    assert policy.rules[
        4].access == FS_ACCESS.READ | FS_ACCESS.WRITE | FS_ACCESS.EXEC
    assert policy.rules[4].pathname == '/tmp/bpfbox/a'

    assert policy.rules[5].action == BPFBOX_ACTION.ALLOW | BPFBOX_ACTION.TAINT
    assert policy.rules[
        5].access == FS_ACCESS.GETATTR | FS_ACCESS.SETATTR | FS_ACCESS.IOCTL | FS_ACCESS.RM
    assert policy.rules[5].pathname == '/tmp/bpfbox/b'

    assert policy.rules[
        6].action == BPFBOX_ACTION.ALLOW | BPFBOX_ACTION.TAINT | BPFBOX_ACTION.AUDIT
    assert policy.rules[
        6].access == NET_ACCESS.BIND | NET_ACCESS.CONNECT | NET_ACCESS.ACCEPT
    assert policy.rules[6].family == NET_FAMILY.INET

    assert policy.rules[7].action == BPFBOX_ACTION.ALLOW | BPFBOX_ACTION.AUDIT
    assert policy.rules[7].access == FS_ACCESS.READ
    assert policy.rules[7].other_exe == '/foo/bar/qux'
Esempio n. 14
0
def policy_parser(bpf_program: BPFProgram):
    yield PolicyParser()