Initial public release
Full BigBrother network implant - passive SOC + active exploitation. Personal identifiers removed; all capabilities intact. See README.md for setup and docs/deployment.md for detailed deployment.
This commit is contained in:
@@ -0,0 +1,190 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Root/capability checks, privilege dropping, directory permission enforcement."""
|
||||
|
||||
import ctypes
|
||||
import ctypes.util
|
||||
import grp
|
||||
import os
|
||||
import pwd
|
||||
import stat
|
||||
from pathlib import Path
|
||||
from typing import Optional
|
||||
|
||||
# Linux capability constants
|
||||
CAP_NET_RAW = 13
|
||||
CAP_NET_ADMIN = 15
|
||||
CAP_SYS_ADMIN = 21
|
||||
CAP_DAC_OVERRIDE = 1
|
||||
|
||||
# capget/capset structures
|
||||
_LINUX_CAPABILITY_VERSION_3 = 0x20080522
|
||||
_VFS_CAP_REVISION_2 = 0x02000000
|
||||
|
||||
_libc = ctypes.CDLL(ctypes.util.find_library("c"), use_errno=True)
|
||||
|
||||
|
||||
class _cap_header(ctypes.Structure):
|
||||
_fields_ = [
|
||||
("version", ctypes.c_uint32),
|
||||
("pid", ctypes.c_int),
|
||||
]
|
||||
|
||||
|
||||
class _cap_data(ctypes.Structure):
|
||||
_fields_ = [
|
||||
("effective", ctypes.c_uint32),
|
||||
("permitted", ctypes.c_uint32),
|
||||
("inheritable", ctypes.c_uint32),
|
||||
]
|
||||
|
||||
|
||||
def check_root() -> bool:
|
||||
return os.geteuid() == 0
|
||||
|
||||
|
||||
def check_capability(cap: int) -> bool:
|
||||
if check_root():
|
||||
return True
|
||||
|
||||
try:
|
||||
header = _cap_header(version=_LINUX_CAPABILITY_VERSION_3, pid=0)
|
||||
# Version 3 uses 2 data structs for 64-bit capability sets
|
||||
data = (_cap_data * 2)()
|
||||
ret = _libc.capget(ctypes.byref(header), data)
|
||||
if ret != 0:
|
||||
return False
|
||||
|
||||
idx = cap // 32
|
||||
bit = 1 << (cap % 32)
|
||||
return bool(data[idx].effective & bit)
|
||||
except Exception:
|
||||
return False
|
||||
|
||||
|
||||
def has_net_raw() -> bool:
|
||||
return check_capability(CAP_NET_RAW)
|
||||
|
||||
|
||||
def has_net_admin() -> bool:
|
||||
return check_capability(CAP_NET_ADMIN)
|
||||
|
||||
|
||||
def check_required_capabilities() -> dict:
|
||||
return {
|
||||
"root": check_root(),
|
||||
"CAP_NET_RAW": check_capability(CAP_NET_RAW),
|
||||
"CAP_NET_ADMIN": check_capability(CAP_NET_ADMIN),
|
||||
"CAP_SYS_ADMIN": check_capability(CAP_SYS_ADMIN),
|
||||
}
|
||||
|
||||
|
||||
def drop_privileges(
|
||||
username: str = "nobody",
|
||||
groupname: Optional[str] = None,
|
||||
keep_caps: Optional[list] = None,
|
||||
) -> bool:
|
||||
if not check_root():
|
||||
return False
|
||||
|
||||
try:
|
||||
pw = pwd.getpwnam(username)
|
||||
uid = pw.pw_uid
|
||||
gid = pw.pw_gid
|
||||
|
||||
if groupname:
|
||||
gr = grp.getgrnam(groupname)
|
||||
gid = gr.gr_gid
|
||||
|
||||
# Set supplementary groups
|
||||
os.setgroups([])
|
||||
|
||||
# Set GID first (can't change after dropping root)
|
||||
os.setregid(gid, gid)
|
||||
os.setreuid(uid, uid)
|
||||
|
||||
# Verify drop
|
||||
if os.geteuid() == 0:
|
||||
return False
|
||||
|
||||
# Re-apply specific capabilities if requested
|
||||
if keep_caps:
|
||||
_set_keepcaps()
|
||||
_apply_caps(keep_caps)
|
||||
|
||||
return True
|
||||
except (KeyError, PermissionError, OSError):
|
||||
return False
|
||||
|
||||
|
||||
def _set_keepcaps():
|
||||
PR_SET_KEEPCAPS = 8
|
||||
_libc.prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0)
|
||||
|
||||
|
||||
def _apply_caps(caps: list):
|
||||
header = _cap_header(version=_LINUX_CAPABILITY_VERSION_3, pid=0)
|
||||
data = (_cap_data * 2)()
|
||||
|
||||
for cap in caps:
|
||||
idx = cap // 32
|
||||
bit = 1 << (cap % 32)
|
||||
data[idx].effective |= bit
|
||||
data[idx].permitted |= bit
|
||||
|
||||
_libc.capset(ctypes.byref(header), data)
|
||||
|
||||
|
||||
def enforce_directory_permissions(
|
||||
path: str,
|
||||
mode: int = 0o700,
|
||||
recursive: bool = True,
|
||||
) -> int:
|
||||
count = 0
|
||||
target = Path(path)
|
||||
|
||||
if not target.exists():
|
||||
target.mkdir(parents=True, mode=mode)
|
||||
count += 1
|
||||
return count
|
||||
|
||||
current = target.stat().st_mode & 0o777
|
||||
if current != mode:
|
||||
target.chmod(mode)
|
||||
count += 1
|
||||
|
||||
if recursive:
|
||||
for item in target.rglob("*"):
|
||||
if item.is_dir():
|
||||
item_mode = item.stat().st_mode & 0o777
|
||||
if item_mode != mode:
|
||||
item.chmod(mode)
|
||||
count += 1
|
||||
elif item.is_file():
|
||||
file_mode = mode & 0o700 # Files get owner-only based on dir mode
|
||||
item_mode = item.stat().st_mode & 0o777
|
||||
if item_mode != file_mode:
|
||||
item.chmod(file_mode)
|
||||
count += 1
|
||||
|
||||
return count
|
||||
|
||||
|
||||
def secure_path(path: str, owner_uid: Optional[int] = None) -> bool:
|
||||
try:
|
||||
p = Path(path)
|
||||
if not p.exists():
|
||||
return False
|
||||
|
||||
# Set ownership if specified
|
||||
if owner_uid is not None:
|
||||
os.chown(path, owner_uid, owner_uid)
|
||||
|
||||
# Restrict permissions
|
||||
if p.is_dir():
|
||||
p.chmod(0o700)
|
||||
else:
|
||||
p.chmod(0o600)
|
||||
|
||||
return True
|
||||
except (OSError, PermissionError):
|
||||
return False
|
||||
Reference in New Issue
Block a user