v2.3
This commit is contained in:
@@ -0,0 +1,253 @@
|
||||
import argparse
|
||||
import base64
|
||||
import os
|
||||
import socket
|
||||
import subprocess
|
||||
import re
|
||||
import sys
|
||||
|
||||
from Crypto.Cipher import PKCS1_OAEP
|
||||
from Crypto.PublicKey import RSA
|
||||
from colorama import Fore
|
||||
from cryptography.hazmat.primitives import padding
|
||||
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
|
||||
|
||||
hostname = socket.gethostname()
|
||||
IPAddr = socket.gethostbyname(hostname)
|
||||
cwd = os.getcwd()
|
||||
BUNDLED_SCRIPT = "audit_cis_centos_v202.sh"
|
||||
|
||||
|
||||
def resource_path(relative_path):
|
||||
if getattr(sys, "frozen", False):
|
||||
return os.path.join(sys._MEIPASS, relative_path)
|
||||
return os.path.join(os.path.dirname(os.path.abspath(__file__)), relative_path)
|
||||
|
||||
|
||||
def resolve_script_path(user_path=None):
|
||||
if user_path and os.path.isfile(user_path):
|
||||
return os.path.abspath(user_path)
|
||||
bundled = resource_path(BUNDLED_SCRIPT)
|
||||
if os.path.isfile(bundled):
|
||||
return bundled
|
||||
same_dir = os.path.join(os.getcwd(), BUNDLED_SCRIPT)
|
||||
if os.path.isfile(same_dir):
|
||||
return same_dir
|
||||
return None
|
||||
|
||||
def print_progress(current, total):
|
||||
if total == 0:
|
||||
return
|
||||
|
||||
bar_len = 40 # độ dài thanh
|
||||
filled = int(bar_len * current / total)
|
||||
bar = '█' * filled + '-' * (bar_len - filled)
|
||||
percent = int(current * 100 / total)
|
||||
|
||||
sys.stdout.write(f'\rĐang xử lý... [{bar}] {percent}%')
|
||||
sys.stdout.flush()
|
||||
|
||||
# Khi xong hết thì xuống dòng mới cho đẹp
|
||||
if current == total:
|
||||
sys.stdout.write('\n')
|
||||
sys.stdout.flush()
|
||||
|
||||
|
||||
def get_os_tag():
|
||||
"""Trả về nhãn OS dạng 'ubuntu_22_04' hoặc 'centos_7', ..."""
|
||||
try:
|
||||
if os.path.isfile("/etc/os-release"):
|
||||
name = ""
|
||||
version = ""
|
||||
with open("/etc/os-release") as f:
|
||||
for line in f:
|
||||
if line.startswith("NAME=") and not name:
|
||||
name = line.split("=", 1)[1].strip().strip('"').lower()
|
||||
elif line.startswith("VERSION_ID=") and not version:
|
||||
version = line.split("=", 1)[1].strip().strip('"').lower()
|
||||
tag = f"{name}_{version}" if version else name
|
||||
# chuẩn hoá: thay khoảng trắng và ký tự lạ
|
||||
tag = re.sub(r"[^a-z0-9]+", "_", tag).strip("_")
|
||||
if tag:
|
||||
return tag
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
try:
|
||||
if os.path.isfile("/etc/redhat-release"):
|
||||
txt = open("/etc/redhat-release").read().strip().lower()
|
||||
# ví dụ: "centos linux release 7.9.2009 (core)"
|
||||
# lấy vendor + major.minor
|
||||
m = re.search(r"(centos|red hat|rhel|rocky|almalinux).*?release\s+([0-9]+(?:\.[0-9]+)?)", txt)
|
||||
if m:
|
||||
vendor = m.group(1).replace(" ", "")
|
||||
ver = m.group(2).replace(".", "_")
|
||||
return f"{vendor}_{ver}"
|
||||
# fallback rút gọn
|
||||
tag = re.sub(r"[^a-z0-9]+", "_", txt).strip("_")
|
||||
if tag:
|
||||
return tag
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
try:
|
||||
import platform
|
||||
sysname = platform.system().lower()
|
||||
release = platform.release().lower()
|
||||
tag = f"{sysname}_{release}"
|
||||
tag = re.sub(r"[^a-z0-9]+", "_", tag).strip("_")
|
||||
return tag or "unknown_os"
|
||||
except Exception:
|
||||
return "unknown_os"
|
||||
|
||||
def write_content(content):
|
||||
message = content.encode('utf-8')
|
||||
|
||||
aes_key = os.urandom(32)
|
||||
iv = os.urandom(16)
|
||||
|
||||
padder = padding.PKCS7(128).padder()
|
||||
padded_data = padder.update(message) + padder.finalize()
|
||||
|
||||
cipher_aes = Cipher(algorithms.AES(aes_key), modes.CBC(iv))
|
||||
encryptor = cipher_aes.encryptor()
|
||||
ciphertext = encryptor.update(padded_data) + encryptor.finalize()
|
||||
|
||||
public_key = RSA.import_key(open('public_key.pem').read())
|
||||
cipher_rsa = PKCS1_OAEP.new(public_key)
|
||||
enc_key = cipher_rsa.encrypt(aes_key)
|
||||
|
||||
b64_enc_key = base64.b64encode(enc_key).decode('utf-8')
|
||||
b64_iv = base64.b64encode(iv).decode('utf-8')
|
||||
b64_ct = base64.b64encode(ciphertext).decode('utf-8')
|
||||
|
||||
return f"HYBRID_V1:{b64_enc_key}:{b64_iv}:{b64_ct}"
|
||||
|
||||
|
||||
def is_file_exist(path):
|
||||
isFile = os.path.isfile(path)
|
||||
if isFile:
|
||||
return True
|
||||
|
||||
else:
|
||||
return False
|
||||
|
||||
|
||||
def run_bash(command):
|
||||
process = subprocess.Popen(
|
||||
['/bin/bash', '-c', command],
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.PIPE
|
||||
)
|
||||
stdout, stderr = process.communicate()
|
||||
|
||||
rc = process.returncode
|
||||
out = stdout.decode(errors="ignore")
|
||||
err = stderr.decode(errors="ignore")
|
||||
|
||||
# Luôn luôn ghép stderr (nếu có) vào log để không mất thông tin
|
||||
if err.strip():
|
||||
out += "\n########## STDERR BEGIN ##########\n"
|
||||
out += err
|
||||
out += "\n########## STDERR END ##########\n"
|
||||
|
||||
# Trả về tuple: (output, stderr, return_code)
|
||||
return out, err, rc
|
||||
|
||||
|
||||
|
||||
def run_audit(file_path):
|
||||
print(Fore.BLUE + """
|
||||
_ _ _____ _____ _______ _ _ _____ _____ ______ _ _ _____ _ _ _____
|
||||
/\ | | | | __ \_ _|__ __| | | | | /\ | __ \| __ \| ____| \ | |_ _| \ | |/ ____|
|
||||
/ \ | | | | | | || | | | ______ | |__| | / \ | |__) | | | | |__ | \| | | | | \| | | __
|
||||
/ /\ \| | | | | | || | | | |______| | __ | / /\ \ | _ /| | | | __| | . ` | | | | . ` | | |_ |
|
||||
/ ____ \ |__| | |__| || |_ | | | | | |/ ____ \| | \ \| |__| | |____| |\ |_| |_| |\ | |__| |
|
||||
/_/ \_\____/|_____/_____| |_| |_| |_/_/ \_\_| \_\_____/|______|_| \_|_____|_| \_|\_____|
|
||||
|
||||
|
||||
""" + Fore.RESET)
|
||||
print(Fore.RED + "Running Audit Hardening..." + Fore.RESET)
|
||||
|
||||
script_path = resolve_script_path(file_path)
|
||||
if script_path is None:
|
||||
print(Fore.RED + "ERROR: No audit script found. Use -p <script.sh> or bundle the script." + Fore.RESET)
|
||||
return
|
||||
|
||||
print(f" Script: {script_path}")
|
||||
print(" [1/3] Reading script...")
|
||||
with open(script_path, 'r', encoding='utf-8') as f:
|
||||
script_content = f.read()
|
||||
|
||||
script = script_content.split(
|
||||
"##################################################################################################################")
|
||||
|
||||
# Lọc bỏ các block rỗng trước
|
||||
script_blocks = [block.strip() for block in script if block.strip()]
|
||||
total_blocks = len(script_blocks)
|
||||
|
||||
output = ""
|
||||
errors = [] # Lưu lỗi để hiển thị sau khi loading xong
|
||||
|
||||
for idx, i in enumerate(script_blocks, 1):
|
||||
# Hiển thị progress bar
|
||||
print_progress(idx, total_blocks)
|
||||
|
||||
if "#!/bin/bash" not in i:
|
||||
result, err, rc = run_bash("#!/bin/bash\n{0}".format(i))
|
||||
else:
|
||||
result, err, rc = run_bash(i)
|
||||
|
||||
# Lưu lỗi nếu có (exit code != 0)
|
||||
if rc != 0 and err.strip():
|
||||
errors.append(f"[Block {idx}] {err.strip().split(chr(10))[0]}")
|
||||
|
||||
# Nếu lệnh lỗi và run_bash trả về None thì bỏ qua
|
||||
if result is None:
|
||||
continue
|
||||
|
||||
output += result
|
||||
|
||||
# Hiển thị các lỗi sau khi loading xong
|
||||
if errors:
|
||||
print(Fore.YELLOW + f"\n⚠ Có {len(errors)} cảnh báo:" + Fore.RESET)
|
||||
for e in errors:
|
||||
print(Fore.YELLOW + f" • {e}" + Fore.RESET)
|
||||
# Dùng regex để tìm Hostname và Audit Time trong output
|
||||
hostname_match = re.search(r"Hostname:\s*(\S+)", output)
|
||||
time_match = re.search(r"Audit Time:\s*(.+)", output)
|
||||
|
||||
hostname = hostname_match.group(1) if hostname_match else "unknown_host"
|
||||
time_generate = time_match.group(1).strip().replace("-", "_").replace(":", "_").replace(" ", "-") if time_match else "unknown_time"
|
||||
os_tag = get_os_tag()
|
||||
file_encrypt_name = f"{hostname}_{os_tag}_{time_generate}.txt.enc"
|
||||
# file_encrypt_name = '{}_{}.txt.enc'.format(hostname, time_generate)
|
||||
encrypt_result = write_content(output)
|
||||
with open(file_encrypt_name, 'w') as f:
|
||||
f.write(encrypt_result)
|
||||
|
||||
if is_file_exist(file_encrypt_name):
|
||||
print(Fore.GREEN + "THÀNH CÔNG - FILE ENCRYPT {}".format(file_encrypt_name) + Fore.RESET)
|
||||
else:
|
||||
print(Fore.RED + "THẤT BẠI RỒI THỬ LẠI NHÁ !!!" + Fore.RESET)
|
||||
|
||||
|
||||
def run_ubuntu_audit(file_path=None):
|
||||
old_file_path = '{}.txt'.format(hostname)
|
||||
old_file = is_file_exist(old_file_path)
|
||||
if old_file:
|
||||
os.remove(old_file_path)
|
||||
run_audit(file_path)
|
||||
|
||||
|
||||
def main():
|
||||
# Parse Arguments
|
||||
parser = argparse.ArgumentParser(description='Audit Hardening')
|
||||
parser.add_argument('-p', '--path', help='Path to audit script (optional if bundled)', default=None)
|
||||
args = parser.parse_args()
|
||||
return args
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
args = main()
|
||||
run_ubuntu_audit(args.path)
|
||||
Reference in New Issue
Block a user