使用nmap扫描外租机开放的端口并识别

使用nmap扫描外租机开放的端口并识别

使用nmap扫描外租机开放的端口并识别 需要用到pubapi来写入数据库 不适用于所有环境,脚本只做技术储备

from requests.packages import urllib3
from BasicInterface import executeMysqlData
from base64 import b64encode
import json, time,re,requests,datetime
urllib3.disable_warnings()
#将cmdb的ip地址提交到gcp的nmap接口去扫描开放端口
def isPublicIpv4(ip):
    pattern = r'^(?:(?:(?:[1-9]?\d|1\d\d|2[0-4]\d|25[0-5])\.){3}{?:[1-9]?\d|1\d\d|2[0-4]\d|25[θ-5]))$'
    private_pattern = r'^(?:(?:10|127)\.\d{1,3}\.\d{1,3}\.\d{1,3}|(?:172\.(?:1[6-9]|2\d|3[01]))\.\d{1,3}\.\d{1,3}|192\.168\.\d{1,3}\.\d{1,3}}$'
    return re.match(pattern,ip) is not None and re.match(private_pattern,ip) is None
    #只要7天内有扫过的 ip就不会再扫描了,所以这里抓出7天内有扫描过的
    ipqueryIPExist = "SELECT ip FROM ScanResult WHERE ScanTime >= CURDATE() - INTERVAL 6 DAY AND ScanTime <=CURDATE() GROUP BY ip;"
    resultQuery = executeMysqlData(1,'read',queryIPExist)
    resultList = []
    for q in resultQuery:
        for r in q:
            resultList.append(r)
            cookies = {'sso' : '<ssoKey>'}
            #脚本中的接口有多页,所以做了一个遍历,n为页面编号
n=1
ipListJson = {}
#本地手动添加的ip列表,如果有需要增加的,则按格式添加即可
ipList = ['<ipaddress>']
while 1:
    response = requests.get('<serverUrl>'%n, cookies= cookies , verify= False)
    status_code = response.status_code
    response = json.loads(response.text)
    if status_code != 404:
        for m in range (θ,len(response['result'])):
            name = response['result'][m]['name']
            ip = response['result'][m]['ip']
            user = response['result'][m]['user']
            app = response['result'][m]['app']
            #有些ip地址栏里写了乱七八糟的东西,所以为了确保获取到正确的 ip,所以限制了长度
            if isPublicIpv4(ip) == True and ip != '0.0.0.0' and ip != '1.1.1.1' and ip != 'N/a' and ip!='θ' and ip !' and ip !='127.0.0.1':
                ipListJson[name] = {}
                ipListJson[name]['ip'] = ip
                ipListJson[name]['user'] = user
                ipListJson[name]['app'] = app
            else:
                break
            n += 1
for i in ipList:
    ipListJson[i] = {}
    ipListJson[i]['ip'] = i
    ipListJson[i]['user'] = ''
    #外租机的 ip和端口,外租机上使用 flask开放了1080端口用来接收数据,只能接收文本 text格式的数据
    url='<serverurl>'
    #使用 for循环进行发送数据,每个 ip发送一次
    for j in ipListJson:
        currentDatetime = datetime.datetime.now()
        mysqlDateFormat = "'" + currentDatetime.strftime('%Y-%m-%d %H:%M:%S') + "'"
        ip = ipListJson[j]['ip']
        if ip.split('.')[-1] == '255':
            print (f'该ip地址{ip}无法进行扫描, 忽略。。。')
        else:
            if ip not in resultList:
                print (f'{ip}提交到接口进行扫描')
                n=θ
                while 1:
                    try:
                        if n != 3:
                            response = requests.post(url, data= ip, timeout=1800)
                            break
                        else:
                            print (f'重试{n}次失败, 跳过。。。。')
                            break
                    except:
                        n += 1
                        print (f'扫描失败, 正在进行第{n}次重试')
                        time.sleep(30)
                if ipListJson[j][' user'] is not None:
                    #这里有的时候会扫描失败,造成返回不了 json数据,所以 try一下,无法格式化的 ip默认扫描失败,跳过
                    if isinstance(ipListJson[j]['user'], str):
                        userStr = "'" + ipListJson[j]['user'] + "'"
                    elif isinstance(ipListJson[j]['user'],list):
                        userStr = "'" + ", ". join(ipListJson[j][' user']) + "'"
                    else:
                        print (ipListJson[j]['user'])
                else:
                    userStr = "'" + ' unknown' + "'"
                try:
                    scanResultJson = response.json()
                    for k in scanResultJson:
                        #有些 ip地址所有的端口都是关闭的,所以扫描的时候返回的 portstatus的 key是没有的导致出问题,所以 try一下,如果失败的就当作扫描失败,跳过
                        try:
                            portStr = scanResultJson[k]['portstatus']
                        except:
                            sql= f"""INSERT INTO ScanResult (ScanTime, ip, user) VALUES ({mysqlDateFormat},{"'" + k + "'"},{userStr})"""
                            print (f'no port scaned open, will insert into sql through {sql}')
                            executeMysqlData(1,'write', sql)
                            #使用 for循环进行行放的端口读取并写入到数据库,按端口进行存入
                        for l in scanResultJson[k]['portstatus']:
                            applicationStr = scanResultJson[k]['portstatus'][l]['application']
                            if applicationStr == '':
                                applicationStr = "'" + 'Unknown' + "'"
                            serviceStr = "'" + scanResultJson[k]['portstatus'][l]['service'] + "'"
                            sql= f"""INSERT INTO ScanResult (ScanTime, application, ip, name, openport, service, user) VALUES  〔{mysqlDateFormat},{applicationStr},{"'" + k + "'"},{"'" + j + "'"},{"'" + l + "'"},{serviceStr},{userStr})"""
                            executeMysqlData(1,'write', sql)
                except:
                    sql= f"""INSERT INTO ScanResult (ScanTime, ip, user) VALUES〔{mysqlDateFormat},{"'" + ip + "'"},{userStr})"""
                    executeMysqlData(1,'write', sql)
                    #这里使用 for循环去读取 json数据,将数据提取出来以后,再写入数据库
            else:
                print (fˈip:{ip}已经扫描完毕, 忽略。。。')

同步多个gcp项目的防火墙

同步多个gcp项目的防火墙

同步多个gcp项目的防火墙,用于多个gcp项目(或账号)之间同步黑名单数据,需要使用基础库的数据库读写

from requests.packages import urllib3
import time, re
from google.cloud import compute _v1
from google. oauth2 import service_account
from BasicInterfaces import executeMysqlData
def listLessThan5kFirewallRule(credentials,projectId):
    client = compute _v1.FirewallsClient(credentials=credentials)
    firewallRuleList = client.list(project=projectId)
    query = "blocklist"
    for firewallName in firewallRuleList:
        if query in firewallName.name:
            if len(firewallName.source_ranges) != 5000:
                capacityFirewall = 5000 - Len(firewallName.source_ranges)
                return firewallName.name,capacityFirewall
            elif len(firewallName.source_ranges) == 2:
                try:
                    removeSourceIPToFirewallRule(credentials,projectId,firewallName.name,'224.1.1.132/32')
                except:
                    pass
            else:
                return None
def addSourceIPToFirewallRule(credentials,projectId,firewallRuleName,ipaddressForAdd):
    client = compute _v1.FirewallsClient(credentials=credentials)
    firewall = client.get(project=projectId,firewall=firewallRuleName)
    for i in ipaddressForAdd:
        firewall.source_ranges.append(i)
        try:
            operation = client.update(project=projectId, firewall=firewalLRuleName, firewall_resource=firewall)
            operation.result()
        except Exception as e:
            return str(e). split()[-1]
def removeSourceIPToFirewallRule(credentials,projectId,firewallRuleName,ipaddressForAdd):
    client = compute _v1.FirewallsClient(credentials=credentials)
    firewall = client.get(project=projectId, firewall=firewallRuleName)
    firewall.source_ranges.remove(ipaddressForAdd)
    operation = client.update(project=projectId, firewall=firewallRuleName, firewall_resource=firewall)
    operation. result()
def getResource0fFirewall(credentials,projectId,firewallRule):
    client = compute _v1.FirewallsClient(credentials=credentials)
    firewallRuleList = client.list(project=projectId)
    for firewallName in firewallRuleList:
        if firewallRule in firewallName.name:
            #print (firewallName.name)
            #time.sleep(30)
            #print (firewallName.source_ranges)
            return firewallName.source_ranges
def newFirewallPolicy(credentials,projectId, firewallRuleName, ipaddresses):
    client = compute _v1.FirewallsClient(credentials= credentials)
    firewall = {
        "denied": [{"I_p_ protocol": "all"}],
        "direction": "INGRESS",
        "name": firewallRuleName,
        "network": "global/networks/default",
        "priority": 999,
        "source_ranges": ipaddresses
        }
    try:
        client.insert(project=projectId, firewall_resource = firewall)
        return True
    except Exception as e:
        return (str(e).split()[-2] + " " + str(e).split()[-1])
projectsList = ["<projectname>"]
credentialsCST = service_account.Credentials.from_service_account_file('<xxx.json>')
for projectInfo in projectsList:
    print (f'开始处理{projectInfo}黑名单。。。')
    queryScanData = f"select ip from sync_ip_info where {projectInfo}=0"
    scanData = executeMysqlData(1,'read',queryScanData)
    ips = [item[θ] for item in scanData]
    if len(ips)!= 0:
        whileIPsList = ['<ips>']
        for i in whileIPsList:
            try:
                ips.remove(i)
                print(f'发现白名单 ip{i}在列表中, 尝试移除。。。')
                sql= f"""update sync_ip_info set {projectInfo}=1 where ip='{i}' and {projectInfo}=θ"""
                executeMysqlData(1,'write',sql)
                print (f'白名单 ip{i}移除完成')
            except:
                pass
        print (f'找到未同步的 ip{len(ips)}个')
        try:
            firewallRuleName,capacityFirewall = listLessThan5kFirewallRule(credentialsCST,projectInfo)
        except:
            firewallRuleName = None
        if firewallRuleName is not None:
            print (f'找到防火墙规则{firewallRuleName}, 尝试写入...')
            while 1:
                resultAddIP = addSourceIPToFirewallRule(credentialsCST,projectInfo,firewallRuleName,ips[θ:capacityFirewall])
                if resultAddIP is None:
                    print (f'更新黑名单ip成功,同步数据库中。。。')
                    for i in ips:
                        sql= f"""update sync_ip_info set {projectInfo}=1 where ip='{i}' and {projectInfo}=θ"""
                        executeMysqlData(1,'write', sql)
                    print (f'数据库同步完成')
                ips = ips[capacityFirewall:]
                if len(ips) > θ:
                    print (f'防火墙规则{firewallRuleName}写入完成,还剩下{len(ips)}个ip')
                    for i in range (1,1000):
                        firewallRuleName = "blocklist" + str(i)
                        resultAddPolicy = newFirewallPolicy(credentialsCST,projectInfo,firewallRuleName,ips[0:5000])
                        if resultAddPolicy == 'already exists':
                            i += 1
                        else:
                            print (f"防火墙规则{firewallRuleName}创建并写入成功!")
                            break
                        print (f'更新黑名单ip成功,同步数据库中。。')
                        for i in ips[θ:5000]:
                            sql= f"""update sync_ip_info set {projectInfo}=1 where ip='{i}' and {projectInfo}=θ"""
                            executeMysqlData(1,'write', sql)
                        print (f'数据库同步完成')
                    ips = ips[5001:]
                    if len(ips)>0:
                        print (f'防火墙规则{firewallRuleName}写入完成,还剩下{len(ips)}个ip')
                    else:
                        print (f"本次黑名单同步完成! ")
                        break
        else:
            while 1:
                for i in range (1,1000):
                    firewallRuleName = "blocklist" + str(i)
                    resultAddPolicy = newFirewallPolicy(credentialsCST,projectInfo,firewallRuleName,ips[0:5000])
                    if resultAddPolicy == 'already exists':
                        i += 1
                    else:
                        print (f"防火墙规则{firewallRuleName}创建并写入成功! ")
                        break
                    print (f'更新黑名单 ip成功,同步数据库中。。')
                    for i in ips[0:5000]:
                        sql= f"""update sync_ip_info set {projectInfo}=1 where ip='{i}' and {projectInfo}=0"""
                        executeMysqlData(1,'write', sql)
                    print (f'数据库同步完成')
                ips = ips[5001:]
                if len(ips) >0:
                    print (f'防火墙规则{firewallRuleName}写入完成,还剩下{len ips}个 ip')
                else:
                    print (f"本次黑名单同步完成! ")
                    break

安装wazuh|clamav|auditd

安装wazuh|clamav|auditd

安装wazuh|clamav|auditd,支持ubantu和centos,需要结合pubapi接口来下载安装软件,要sudo ./运行

#!/ bin/ bash
set -e
# Check root privileges
[[ $EUID - ne θ ]] && { echo" Please run as root: sudo $θ"; exit 1; }
# Define software list and URLs
software_list=(" Wazuh" "ClamAV" " audit")
declare - A urls=(
  [wazuh]="https://pubapi.hmxpr.com/client/wazuh"
  [jq]="https://pubapi.hmxpr.com/client/jq"
  [wazuhdeb]="https://pubapi.hmxpr.com/client/wazuhdeb"
  [wazuhaudit]="https://pubapi.hmxpr.com/client/wazuhaudit"
  [clamavdeb]="https://pubapi.hmxpr.com/client/clamavdeb"
  [clamav]="https://pubapi.hmxpr.com/client/clamav"
  [clamconf]="https://pubapi.hmxpr.com/conf/clamav"
  [audit_rules]="https://pubapi.hmxpr.com/conf/audit"
  [audit]="https://pubapi.hmxpr.com/client/audit"
  [lib]="https://pubapi.hmxpr.com/client/lib"
  [tools]="https://pubapi.hmxpr.com/client/"
  )
# Initialize variables for command line arguments
WAZUH_MANAGER=""
WAZUH_AGENT_GROUP="default"
INSTALL_WAZUH=false
INSTALL_CLAMAV=false
INSTALL_AUDIT=false
# Function to display usage information
usage() {
    echo "Usage: $θ [-w] [-c] [-a] [-m MANAGER_ADDRESS] [-g AGENT_GROUP]"
    echo "-w: Install Wazuh"
    echo "-c: Install ClamAV"
    echo "-a: Install audit"
    echo "-m MANAGER_ADDRESS: Specify Wazuh manager address"
    echo "-g AGENT_GROUP: Specify Wazuh agent group"
    echo "-h: Display this help message"
    exit 1
    }
# Parse command line arguments
while getopts ":wcam:g:h" opt; do
  case ${opt} in
    w) INSTALL_WAZUH=true ;;
    c) INSTALL_CLAMAV=true ;;
    a) INSTALL_AUDIT=true ;;
    m) WAZUH_MANAGER=$OPTARG ;;
    g) WAZUH_AGENT_GROUP=$OPTARG ;;
    h) usage ;;
    \?) echo "Invalid option: $OPTARG" 1>&2; usage ;;
    :) echo "Invalid option: $OPTARG requires an argument" 1>&2; usage ;;
    esac
done
shift $((OPTIND - 1))
# Helper functions
download_file(){
  local url="$1"
  local output_file="$2"
  if command -v wget &> /dev/null; then
    wget -0 "$output_file" "$url" || return 1
  elif command -v curl &> /dev/null; then
    curl -k -o "$ output_file" "$url" || return 1
  elif command -v fetch &> /dev/null; then
    fetch -o "$ output_file" "$url" || return 1
  else
    echo "Error: No suitable download tool found. Please install wget, curl, or fetch. "
    exit 1
  fi
}
ensure_download_tool() {
  for tool in wget unzip; do
    if ! command -v "$tool" > /dev/null 2>&1; then
      echo "Installing $tool…"
      if [[ -f /etc/os-release ]]; then
        ./etc/os-release
        case "$ID" in
          ubuntu|debian)
            case "${VERSION_ID}" in
              20.04|22.04|24.04)
                download_file "${urls[tools]}${tool}${VERSION_ID/./}" "${tool}.deb"
                dpkg -i "${tool}.deb" || {echo "$tool install failed"; exit 1; }
                rm - fr "${tool}.deb"
            ;;
              *)
                echo "不支持的 Ubuntu 版本: $VERSION_ID"
                exit 1
            ;;
            esac
        ;;
          centos|rhel|fedora|amzn)
            download_file "${urls[tools]}${tool}c7" "${tool}.rpm"
            rpm -ivh ${tool}.rpm
        ;;
          rocky)
            download_file "${urls[tools]}${tool}r9" "${tool}.rpm"
            rpm -ivh ${tool}.rpm
        ;;
        esac
    rm - fr ${tool}.*
    else
      echo "Unable to determine OS version"
      exit 1
      fi
    fi
  done
}
check_software_installed() {
  if [[ -f /etc/os-release ]]; then
    ./etc/os-release
    case "$ID" in
      ubuntu|debian) dpkg -s "$1" &> /dev/null ;;
      centos|rocky|rhel|fedora|amzn) rpm -q "$1" &> /dev/null ;;
      *) echo "Unsupported OS: $ID"; exit 1 ;;
    esac
  else
    echo "Unable to determine OS type"
    exit 1
  fi
}
get_user_choice() {
  if [[ $INSTALL_WAZUH == false && $INSTALL_CLAMAV == false && $INSTALL_AUDIT == false ]]; then
    echo "Select software to install (comma-separated):"
    for i in "${!software_list[@]}"; do
      echo"$((i+1)). ${software_list[$i]}"
    done
    read -p "Enter numbers: " choices_raw
    IFS=',' read -ra choices_array <<< "$choices_raw"
    selected_software=()
    for choice in "${choices_array[@]}"; do
      selected_software+=("${software_list[$((choice-1))]}")
    done
    echo "Selected: ${selected_software[*]}"
  else
    selected_software=()
    $INSTALL_WAZUH && selected_software+=("Wazuh")
    $INSTALL_CLAMAV && selected_software+=("ClamAV")
    $INSTALL_AUDIT && selected_software+=("audit")
    echo "Selected from command line: ${selected_software[*]}"
  fi
}
install_wazuh() {
  local pkg="wazuh-agent"
  if check_software_installed "$pkg"; then
    read -p "$pkg already installed. Reinstall? (y/n): " confirm
    if [[ "$confirm" != "y" ]]; then
      echo "Skipping Wazuh installation."
      return
    fi
    echo "Removing existing Wazuh installation..."
    ./etc/os-release
    case"$ID" in
      ubuntu|debian)
        dpkg --purge wazuh-agent
      ;;
      centos|rocky|rhel|fedora|amzn)
        rpm -e wazuh-agent
      ;;
      *)
        echo "Unsupported OS for Wazuh removal: $ID"
        exit 1
      ;;
    esac
    echo "Existing Wazuh installation removed. "
  fi
  if [[ -z $WAZUH_MANAGER ]]; then
    read -p " Enter manager address: " WAZUH_MANAGER
    read -p " Enter agent group: " WAZUH_AGENT_GROUP
    read -p " Confirm manager: $WAZUH_MANAGER, group: $WAZUH_AGENT_GROUP (y/n): " confirm
    [[ "$confirm" != "y" ]] && return
  fi
  ./etc/os-release
  case "$ID" in
    ubuntu|debian)
      download_file "${urls[wazuhdeb]}" "wazuh-agent.deb"
      WAZUH_MANAGER=$WAZUH_MANAGER WAZUH_AGENT_GROUP=$WAZUH_AGENT_GROUP dpkg -i wazuh-agent.deb
    ;;
    centosIrocky|rhel|fedora|amzn)
      download_file "${urls[wazuh]}" " wazuh-agent.rpm"
      WAZUH_MANAGER=$WAZUH_MANAGER WAZUH_AGENT_GROUP=$WAZUH_AGENT_GROUP rpm -ivh wazuh-agent.rpm
    ;;
  esac
  echo -e"wazuh_command.remote_commands=1\nlogcollector.remote_commands=1" >> /var/ossec/etc/local_internal_options.conf
  download_file "${urls[wazuhaudit]}" "editrule.sh"
  yes|mv editrule.sh /var/ossec/active-response/bin/
  chown -R root:wazuh /var/ossec/active-response/bin/editrule.sh
  chmod 750 /var/ossec/active-response/bin/editrule.sh
  systemctl daemon-reload
  systemctl enable --now wazuh-agent
  if check_software_installed jq; then
    echo "jq is already installed."
  else
    ./etc/os-release
    case "$ID" in
      ubuntu|debian)
        download_file "${urls[jq]}${VERSION_ID/./}" "jj${VERSION_ID/./}.zip"
        case "${VERSION_ID}" in
          20.04)
            unzip jq2004.zip
            dpkg -i libonig5_6.9.4-1_amd64.deb
            dpkg -i libjq1_1.6-1_amd64.deb
            dpkg -i jq_1.6-1_amd64.deb
          ;;
          22.04)
            unzip jq2204.zip
            dpkg -i libonig5_6.9.7.1-2build1_amd64.deb
            dpkg -i libjq1_1.6-2.1ubuntu3_amd64.deb
            dpkg -i jq_1.6-2.1ubuntu3_amd64.deb
          ;;
          24.04)
            unzip jq2404.zip
            dpkg -i libonig5_6.9.9-1build1_amd64.deb
            dpkg -i libjq1_1.7.1-3build1_amd64.deb
            dpkg -i jq_1.7.1-3build1_amd64.deb
          ;;
        esac
      ;;
      centos|rhel|fedora|amzn)
        download_file "${urls[jq]}c7" "jq.zip"
        unzip jq.zip
        rpm -ivh oniguruma-6.8.2-2.el7.x86_64.rpm
        rpm -ivh jq-1.6-2.el7.x86_64.rpm
      ;;
      rocky)
        download_file "${urls[jq]}c9" "jq.rpm"
        rpm -ivh jq.rpm
      ;;
      *)
        echo "Unsupported OS for jq removal: $ID"
        exit 1
      ;;
    esac
  fi
  echo "Wazuh installed successfully"
  rm -fr wazuh-agent.*
  rm -fr oniguruma-6.8.2-2.el7.x86_64.rpm
  rm -fr lib*
  rm -fr jq*
}
install_clamav() {
  local pkg="clamav"
  if check_software_installed "$pkg"; then
  read -p "$pkg already installed. Reinstall? (y/n): " confirm
    if [[ "$confirm" != "y" ]]: then
      echo "Skipping $pkg installation. "
      return
    fi
    echo "Removing existing $pkg installation... "
    ./etc/os-release
    case "$ID" in
      ubuntu|debian)
        dpkg --purge $pkg
      ;;
      centos|rocky|rhel|fedora|amzn)
        rpm -e $pkg
      ;;
      *)
        echo "Unsupported OS for $pkg removal: $ID"
        exit 1
      ;;
    esac
    echo "Existing $pkg installation removed. "
  fi
  ./etc/os-release
  case "$ID" in
    ubuntu|debian)
      download_file "${urls[clamavdeb]}" "clamav.deb"
      dpkg -i clamav.deb
    ;;
    centos|rocky|rhel|fedora|amzn)
      download_file "${urls[clamav]}" "clamav.rpm"
      rpm -ivh clamav.rpm
    ;;
    *)
      echo "Error! Can't detect the OS Version!"
      exit 1
    ;;
  esac
  download_file "${urls[clamconf]}" "clamav.zip"
  unzip clamav.zip
  yes|mv clamd.conf /usr/local/etc/
  yes|mv freshclam.conf /usr/local/etc/
  yes|mv clamd.service /etc/systemd/system/
  getent group clamav > /dev/null || groupadd clamav
  id -u clamav > /dev/null 2>&1 || useradd -g clamav clamav
  if [[ ! -d /usr/local/clamav ]]; then
    mkdir -p /usr/local/clamav
    chown clamav:clamav /usr/local/clamav
  fi
  for log_file in /var/log/freshclam.log /var/log/clamav.log; do
    if [[ ! -f $log_file ]]; then
      touch $log_file
      chmod 644 $log_file
      chown clamav:clamav $log_file
    else
      chmod 644 $log_file
      chown clamav:clamav $log_file
    fi
  done
  /usr/local/bin/freshclam
  echo "pls wait for few seconds"
  sleep 10
  systemctl daemon-reload
  systemctl enable clamd
  systemctl restart clamd
  echo "$pkg installed and configured"
  CRON_JOB="0 12 * * * /usr/local/bin/freshclam --quiet"
  EXISTING_CRONTAB=$(crontab - l 2>/dev/null)
  if echo "$EXISTING_CRONTAB" |grep - Fq "$CRON_JOB"; then
    echo "cron 任务已存在, 无需添加。"
    exit θ
  fi
  (echo "$EXISTING_CRONTAB"; echo "$CRON_JOB") | crontab -
  if crontab -l |grep -Fq "$CRON_JOB"; then
    echo "cron 任务成功添加。"
  else
    echo "添加 cron 任务失败。" 1>&2
    exit 1
  fi
  rm -fr clamav.*
}
  install_audit() {
    download_file "${urls[audit_rules]}" "audit.rules"
    local pkg="auditd"
    if check_software_installed "$pkg"; then
      read -p "$pkg already installed. Reinstall? (y/n): " confirm
      if [[ "$confirm" != "y" ]]; then
        echo "Skipping audit installation. "
        return
      fi
      echo "Removing existing audit installation... "
      ./etc/os-release
      case "$ID" in
        ubuntu|debian)
          dpkg --purge $pkg
          echo "Existing $pkg installation removed. "
          download_file "${urls[audit]}${VERSION_ID/./}" "audit.deb"
          download_file "${urls[lib]}${VERSION_ID/./}" "libauparseθ.deb"
          dpkg -i libauparse0.deb audit.deb
          if [[ ! -d /etc/audit/rules.d ]]; then
            mkdir -p /etc/audit/rules.d
          fi
          yes|mv audit.rules/etc/audit/rules.d/
          sed -i 's/^#?RestartPreventExitStatus=.*/RestartPreventExitStatus=255/' /usr/lib/system/system/auditd.service
          systemctl daemon-reload
          systemctl enable --now auditd
        ;;
        centos|rocky|rhel|fedora|amzn)
          echo "Audit don't need to re-installed on CentOS/RHEL/Fedora. "
          output=$(systemctl status audit d 2>&1)
          if echo "$output" |grep -q "Warning: Journal has been rotated since unit was started. Log output isincomplete or unavailable."; then
            echo "检测到 auditd服务异常,尝试修复。。。。"
            sed -i 's/RefuseManualStop=yes/RefuseManualStop=no/' /usr/lib/systemd/system/auditd.service
            systemctl daemon-reload
            systemctl restart auditd
            sed -i 's/RefuseManualStop=no/RefuseManualStop=yes/' /usr/lib/systemd/system/auditd.service
            systemctl daemon-reload
            echo "auditd服务修复完成, 请检查日志"
          else
            echo "audit服务正常,继续下一步"
          fi
        ;;
      esac
    fi
    yes|mv audit.rules /etc/audit/rules.d/augenrules --load
    echo "Audit installed and configured"
    rm -fr audit.deb
    rm -fr libauparse0.deb
}
# Main program
ensure_download_tool
get_user_choice
for software in "${selected_software[@]}"; do
  case $software in
    "Wazuh")
      install_wazuh 
    ;;
    "ClamAV")
      install_clamav
    ;;
    "audit")
      install_audit
    ;;
  esac
done

收集linux上软件安装信息

收集linux上软件安装信息

收集linux上软件安装信息 需要用到pubapi来写入数据库 由于wazuh有同样的功能可以替代,故本脚本只做技术储备

#!/bin/bash
softwarelist=$(rpm -qa --qf "%{NAME} % {VERSION}\\n")
computerName=$(hostname)
ipAddress=$(hostname -I | cut -d' ' -f1)
osVersionFull=$(cat /etc/redhat-release)
osName=$(echo $osVersionFull | cut -d" " - f1)
osVersion=$(echo $osVersionFull | cut -d" " -f4)
date=$(date +%Y%m%d)
#之前是本地生成csv文件再手工发回给安全人员,现在不需要了,所以注释掉
#fileName="$computerName-$ipAddress-$date.csv"
csvFile="./$fileName"
#测试的时候可以调整这个数值,保留是因为服务端是flask写的,怕量太大崩掉
DELAY=$((1 + RANDOM %1200))
echo "Delaying for $DELAY seconds"
sleep $DELAY
# echo"$osName,$osVersion" > $csvFile
rpm -qa --queryformat '%{NAME} %{VERSION}\n' |sort |grep -v "^acl" |grep -v "^acpid" |grep -v "^ad" | grep - v "^xorg" |grep -v "^yajl" |grep -v "^yajl" |grep -v "^zbar" |grep -v "^zeromq3" |grep -v "^zip" |while read line
do
  echo $line
  software=$(echo $line |awk '{print $1}')
  version=$(echo $line |awk '{print $2}')
  #将软件名和版本写入CSV文件
  #echo"$ software,$ version" >> $csvFile
  #创建一个JSON对象
  json=$(
    jq -n \
      --arg ip "$ipAddress" \n
      --arg hn "$computerName" \n
      --arg os "$osName" \n
      --arg ov "$osVersion" \n
      --arg sw "$software" \n
      --arg ver "$version" \n
      '{ip: $ ip, hostname: $ hn, osname: $ os, osversion: $ ov, software: $ sw, version: $ ver}')
  curl -k -X POST -H "Content-Type:application/json" -d "$json"  https//<server>/insert
done

收集windows上软件安装信息

收集windows上软件安装信息

收集windows上软件安装信息,需要编译成exe文件后运行(如果没有环境的话) 需要用到pubapi来写入数据库 由于wazuh有同样的功能可以替代,故本脚本只做技术储备

import winreg, requests, json, platform, socket, time, random
from datetime import date
from requests import urllib3
urllib3.disable_warnings()
#测试的时候可以调整这个数值,保留是因为服务端是flask写的,怕量太大崩掉
delay=random.randint(1,1200)
for i in range(delay, θ,-10):
    remaining = min(i, 10)
    print(f" This script will run in {i} seconds, please wait... ")
    time.sleep(remaining)
def getInstalledSoftware():
    softwareSet = set()
    #处理64位注册表中的软件信息
    uninstallKey64 = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE,r"Software\Microsoft\Windows\CurrentVersion\Uninstall")
    softwareSet.update(getSoftwareFromRegistry(uninstallKey64))
    #处理32位注册表中的软件信息
    uninstallKey32 = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE,r"Software\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall")
    softwareSet.update(getSoftwareFromRegistry(uninstallKey32))
    return list(softwareSet)
def getSoftwareFromRegistry(regKey):
    softwareList = []
    for i in range(θ, winreg.QueryInfoKey(regKey)[θ]):
        subKeyName = winreg.EnumKey(regKey,i)
        subKey = winreg.OpenKey(regKey,subKeyName)
        try:
            displayName = winreg.QueryValueEx(subKey,"DisplayName")[0]
            displayVersion = winreg.QueryValueEx(subKey,"DispLayVersion")[θ]
            #白名单软件
            if displayName != 'aic94xx-firmware' and displayName != ' Azure Data Studio' and '系統更新應用程式' not in displayName and ' Update for' not in displayName and ' for SQL Server' not indisplayName and displayName != ' cim-schema' and ' Cloudbase' not in displayName and ' dstat' notin displayName and displayName != ' galera-4' and displayName != ' hdparm' and ' Hotfix' not indisplayName and displayName != 'iDRAC-with-Lifecycle-Controller' and 'IIS URL' not indisplayName and displayName != ' Integration Services' and displayName != ' Kits Configuration Installer' and ' Analysis Services' not in displayName and displayName != ' Microsoft Edge  Update' and ' Language Pack' not in displayName and ' Microsoft Exchange Speech' not in  displayName and ' Microsoft Help Viewer' not in displayName and ' Microsoft Server Speech' not in  displayName and ' Microsoft Speech' not in displayName and 'T-SQL' not in displayName and ' Setup  Support Files' not in displayName and ' Native Client' not in displayName and 'RsFx D river' not  in displayName and ' Setup (English)' not in displayName and ' Microsoft Unified Communications  Managed API' not in displayName and ' Microsoft Visual Studio Tools' not in displayName and  ' Microsoft VSS Writer' not in displayName and ' Notepad++' not in displayName and displayName !='SDK Debuggers' and ' Security Update for' not in displayName and ' Spice Agent' not indisplayName and ' Batch Parser' and ' Tools for' not in displayName and ' Client Tools' not in  displayName and ' Common Files' not in displayName and ' Connection Info' not in displayName and  ' Database Engine' not in displayName and 'DMF' not in displayName and ' DocumentationComponents' not in displayName and ' Shared Management Objects' not in displayName and 'SQL  Diagnostics' not in displayName and ' Reporting Services' not in displayName and ' Trellix ' not  in displayName and ' for SSMS' not in displayName and ' Wazuh Agent' not in displayName and 'SDK  EULA' not in displayName and ' Software Development Kit' not in displayName:
                softwareList.append((displayName, displayVersion)) # 将软件信息转换为元组
        except:
            pass
    return softwareList
def getComputerInfo():
    hostname = socket.gethostname()
    ip = socket.gethostbyname(hostname)
    osName = platform.system()
    osVersion = platform.version()
    today = date.today().strftime("%Y-%m-%d")
    return {"ip": ip, "hostname": hostname, "osname": osName, "osversion": osVersion, "date": today}
softwareInfo = getInstalledSoftware()
computerInfo = getComputerInfo()
finalData = []
for software in softwareInfo:
    if "'" in software[0]:
        softwareName = software[θ].
        split()[0]else:softwareName = software[θ]
        softwareData = {"ip": computerInfo["ip"],"hostname": computerInfo["hostname"],"software": softwareName,"version": software[1],"osname":computerInfo["osname"],"osversion": computerInfo["osversion"]}
        finalData.append(softwareData)
jsonData = json.dumps(finalData)
url=' <domainname>/insert'
headers = {'Content-Type': 'application/json'}
print (requests.post(url,verify= False, data=jsonData, headers=headers).text)

收集网络管理软件上的网段信息

收集网络管理软件上的网段信息

收集网络管理软件上的网段信息 需要用到pubapi来写入数据库 不适用于所有环境,脚本只做技术储备

import mysql.connector
import requests, json
from requests.packages import urllib3
from Basicinterface import executeMysqlData
#从地址库系统里定时拉数据出来,更新到自己的数据库里,如果有自己的网段也可以手动加进去,后续如果地址用处变更则会自动更新相关的条目,如果没有则会新建
apiToken = '33cbb6a54b5fa924e5be1a0917d0b856'
server=  '<serverUrl>'
serverQuery = [{'serverIP':server,'apiToken':apiToken}]
urllib3.disable_warnings()
n = 1
subnetDict = {}
for i in serverQuery:
    while 1:
        try:
            response = requests.get(f'https://{i['serverIP']}:8861/api/json/ipam/getAllSubnetSummary?apiKey={i['apiToken']}&&rows=100&page={n}',verify= False)
            #print (json.loads(response.text)[" records"])
        except:
            print(f'{i['serverIP']}获取失败!'
        try:
            jsonServerData = json.loads(response.text)['rows']
        except:
            print(f'{i['serverIP']}转换成 json失败!!')
            jsonServerData = []
            if len(jsonServerData) != θ:
                for j in jsonServerData:
                    subnetCidr = j['subnet-address-cidr']
                    if subnetCidr not in subnetDict:
                        subnetDict[subnetCidr] = {}
                    subnetDict[subnetCidr]['subnetName'] = j['subnet-name']
                n += 1
            else:
                n = 1
                break
for i in subnetDict:
    #查询数据是否有重复,如没有就写入,否则跳过
    subnets = "'"+ i + "'"
    nameOfSubnet = "'" + subnetDict[i]['subnetName'] + "'"
    querySubnet = f"SELECT * from IPStatus WHERE subnet = {subnets}"
    result = readMysqlData(1,querySubnet)
    if len(result) == θ :
        sql= f"""INSERT INTO IPStatus (subnet, name) VALUES ({"'"+ i + "'"},{"'" + name + "'"})"""
        executeMysqlData(3,'write',sql)
    elif result[θ][2] == "" or result[θ][2] != subnetDict[i]['subnetName']:
        sql= f"""UPDATE IPStatus set name = {"'" + nameOfSubnet + "'"} WHERE subnet = {"'" + subnet + "'"}"""
        executeMysqlData(3,'write',sql)

统计hfish节点信息

统计蜜罐节点信息

统计蜜罐节点信息 需要用到pubapi来写入数据库 不适用于所有环境,脚本只做技术储备

from BasicInterface import executeMysqlData
#该脚本主要功能是拉取所有蜜罐端点IP
serverlist = [2,5,4]
for server in serverlist:
    sql= """ select net_info from hosts"""
    if server == 2:
        print ('CST')
    elif server == 5:
        print ('SA')
    elif server == 4:
        print ('公网')
    result = executeMysqlData(server,'read', sql)
    for i in result:
        for j in i[θ].split('|'):
            sqlForCheck = f"""select up from honeypot where ip = {"'"+ j.split("&&")[2] + "'"}"""
            resultForCheck = executeMysqlData(3,'read',sqlForCheck)
            if len(resultForCheck) == 0:
                sqlForInsert = f"""insert into honeypot (ip) values({"'" + j.split("&&")[2] + "'"})"""
                executeMysqlData (3,'write',sqlForInsert)

读取ELK信息并写入数据库

读取ELK信息并写入数据库

读取ELK信息并写入数据库 需要用到pubapi来写入数据库 不适用于所有环境,脚本只做技术储备

from BasicInterface import *
from datetime import datetime, timedelta
import re, time
from requests.packages import urllib3
urllib3.disable_warnings()
#每小时拉取一次告警数据以供 grafana读取和审计
time1 = datetime.now().strftime("%Y-%m-%dT%H:%M:%S" + "+0800")
time2 = (datetime.now() - timedelta(minutes=60)).strftime("%Y-%m-%dT%H:%M:%S" + "+0800")
def requestWazuhLv12(server, index):
    if server == 3:
        srv = """' sec'"""
    elif server == 4:
        srv = """' saint""""
    elif server == 5:
        srv = """' saext'"""
    sql= f""" select * from WazuhExcept where server={srv}"""
    result = executeMysqlData(1,'read',sql)
    for item in result:
        body = {
            "query": {
                "bool": {
                    "filter":
                    [{
                        "bool":{
                            "should":{
                                "range": {
                                    "rule.level": {
                                        "gte": 12
                                        }
                                    }
                                }
                            }
                        }]
                    }
                },
                "size": 100
            }
        key = item[2]
        value = item[1]
        time2 = item[4]
        time1 = item[5]
        valueList = []
        try:
            for j in range (θ,len(value.split(','))):
                valueList.append(value.split(',')[j])
        except:
            valueList = value
        if time2 is None or time1 is None:
            time2 = (datetime.now() - timedelta(minutes=60)).strftime("%Y-%m-%dT%H:%M:%S" + "+880θ")
            time1 = datetime. now().strftime("%Y-%m-%dT%H:%M:%S" + "+8800")
        else:
            time2 = time2.strftime("%Y-%m-%dT%H:%M:%S" + "+8888")
            time1 = time1.strftime("%Y-%m-%dT%H:%M:%S" + "+0800")
            timerange = {"range": {
                "@timestamp": {
                    "gte": time2,
                    "lte": time1
                    }
                }
            }
            ruleset = [{
                "terms": {
                    key: valueList
                    }
                }]
            body["query"]["bool"]["filter"].append(timerange)
            body["query"]["bool"]["must_not"]= ruleset
            response = readELK(server, index, body,7)
            if response != False:
                if len(response['hits']['hits'])!= θ:
                    for i in response['hits']['hits']:
                        sourceHostname = "'" + i['_source']['agent']['name'] + "'"
                        timeWazuh = "'" + str(datetime.strptime(i['_source']['timestamp'].split('T')[θ] + " " + i['_source']['timestamp'].split('T')[1].split('+')[θ].split('.')[θ], "%Y-%m-%d %H:%M:%S"))+"'"
                        try:
                            usernameDomain = i['_source']['data']['win']['eventdata']['detection User']
                            if '\\' in usernameDomain:
                                username = "'" + usernameDomain.split('\\')[-1] + "'"
                                domain = "'" + usernameDomain.split('\\')[θ] + "'"
                        except:
                            username = '\'Unknown\''
                            domain = '\'None\''
                        if 'data' in i['_source']:
                            if 'vulnerability' not in i['_source']['data']:
                                if 'full_log' in i['_source']:
                                    if re.match("^CVE",i['_source']['full_log']) is None:
                                        contextWazuh = i['_source']['full_log'].replace("'", "")
                                elif 'category Name' in i['_source']['data']['win']['eventdata']:
                                    contextWazuh = i['_source']['data']['win']['eventdata']['category Name'] + ":" + i['_source']['data']['win']['eventdata']['path']
                                else:
                                    contextWazuh = i['_source']['data']['win']['system']['message']
                            else:
                                contextWazuh = i['_source']['data']['vulnerability']['title']
                            contextWazuh = contextWazuh.replace("'", "")
                        else:
                            contextWazuh = i['_source']['full_log']
                        if len(contextWazuh) >= 251:
                            contextWazuh = "'" + contextWazuh[:250] + "'"
                        else:
                            contextWazuh = "'" + contextWazuh + "'"
                        if server == 3:
                            if '10.70.4.' in i['_source']['agent']['ip'] or '10.70.5.' in i['_source']['agent']['ip'] or '10.70.6.' in i['_source']['agent']['ip'] or '10.70.8.' in i['_source']['agent']['ip'] or '10.78.6.' in i['_source']['agent']['ip'] or '10.70.8.' in i['_source']['agent']['ip'] or '10.79.27.' in i['_source']['agent']['ip'] or '10.21.25.' in i['_source']['agent']['ip']:
                                department = "'" + 'Techology' + "'"
                            else:
                                department = "'" + 'unknown' + "'"
                            try:
                                infoSource = "'" + i['_source']["data"]["win"]["system"]["providerName"] + "'"
                            except:
                                infoSource = "'"+ 'wazuh' + "'"
                            if 'Microsoft-Windows-Windows Defender' in infoSource:
                                sql=f"""INSERT INTO LogCollection (Type, Context, Infosource,HostnameOfSource, Domain, Account,TimeOfHappened, Auditer, Department) VALUES ('Audit',{contextWazuh},{infoSource},{sourceHostname},{domain},{username},{timeWzuh},'Doctor',{department})"""
                            else:
                                sql=f"""INSERT INTO LogCollection (Type, Context, Infosource,HostnameOfSource, Domain, Account,TimeOfHappened, Auditer, Department) VALUES(' Audit',{contextWazuh},{infoSource},{sourceHostname},{domain},{username},{timeWazuh},'Matteo',{department})"""
                        elif server == 4:
                            sql=f"""INSERT INTO LogCollection (Type,Context,Infosource,HostnameOfSource,Domain,Account,TimeOfHappened, Auditer, Department) VALUES ('Audit',{contextWazuh},'SaIntWazuh','{sourceHostname}','{domain}','{username}',{timeWazuh},'hsDanny','SA')"""
                        elif server == 5:
                            sql=f"""INSERT INTO LogCollection (Type, Context, Infosource,HostnameOfSource, Domain, Account,  TimeOfHappened, Auditer, Department) VALUES ('Audit',{contextWazuh},'SaExtWazuh',{sourceHostname},{domain},{username},{timeWazuh},'hsDanny','SA')"""
                        resultSql = executeMysqlData(3,'write', sql)
                        if resultSql == True:
                            print ('mcafee数据写入成功')
                        else:
                            print ('mcafee数据写入失败,请检查')
                else:
                    print (f'本次扫描完成, {server}没有发现12级以上的告警')
            else:
                print ('wazuh接口调用失败,故跳过本次查询!')
def requestWazuhAccount():
    body = {
        "query":{
            "bool": {
                "must": [{
                    "range": {
                        "@timestamp": {
                            "gte": time2,
                            "lte": time1
                            }
                        }
                    }],
                "filter": {
                    "bool": {
                        "must": [{
                            "terms": {
                                "data.win.eventdata.targetUserName": [
                                    "admin", "administrator", "zohoadm", "exadm","administratθr"]
                                    }
                                },
                        {
                            "bool": {
                                "must_not": {
                                    "term": {
                                        "rule.description":"Windows User Logoff."
                                        }
                                    }
                                }
                            },
                        {
                            "bool": {
                                "must_not": {
                                    "term": {
                                        "rule.description":"Windows logon success."
                                        }
                                    }
                                }
                            },
                        {
                            "bool": {
                                "must_not": {
                                    "term": {
                                        "data.win.eventdata.workstationName":"<computername>"
                                        }
                                    }
                                }
                            },
                        {
                            "bool": {
                                "must_not": {
                                    "term": {
                                        "data.win.eventdata.workstationName":"<computername>"
                                        }
                                    }
                                }
                            },
                        {
                            "bool": {
                                "must_not": {
                                    "term": {
                                        "rule.id": "60122"
                                        }
                                    }
                                }
                            },
                        {
                            "bool": {
                                "must_not": {
                                    "term": {
                                        "data.win.eventdata.logonProcessName": "NtLmSsp"
                                        }
                                    }
                                }
                            }]
                        }
                    }
                }
            }
        }
    result = readELK(serverId=3,indexDatα="<indexname>",bodyDatα=body,esVersion=7)
    if result != False:
        if len(result['hits']['hits'])!= 0:
            for i in result['hits']['hits']:
                pattern = r'[mM][aA][iɪ][lL]'
                if re.search(pattern, i['_source']['agent']['name'], re.IGNORECASE):
                    logForSql = "'"+ i['_source']['data']['win']['system']['severityValue'] + ", " + i['_source']['data']['win']['eventdata']['logonProcessName'] + "'"
                    accountForSql = "'" + i['_source']['data']['win']['eventdata']['targetUserName'] + "'"
                    hostForSql = "'" + i['_source']['agent']['name'] + "'"
                    ipForSql = "'" + i['_source']['agent']['ip'] + "'"
                    timeForSql = "'" + str(datetime.strptime(i['_source']['timestamp'].split('T')[θ] + " " + i['_source'][' timestamp'].split('T')[1].split('+')[θ].split('.')[θ], "%Y-%m-%d %H:%M:%S")) + "'"
                    sql=f"""INSERT INTO LogCollection (Type, Context,SourceIP, Infosource,HostnameOfSource, Account,TimeOfHappened) VALUES ('Audit',{logForSql},{ipForSql},'wazuh-特权账号登入',{hostForSql},{accountForSql},{timeForSql})"""
                    resultSql = executeMysqlData(3,'write', sql)
                    if resultSql == True:
                        print ('wazuh数据写入成功')
                    else:
                        print ('wazuh数据写入失败,请检查!')
                    check = θ
        else:
            print ('wazuh接口调用失败,故跳过本次查询!')
def requestMcafee():
    idList = ['877','878']
    for i in idList:
        data = apiFromMcafee(2,i)
        if data[θ:2] == 'OK':
            if len(data) > 10:
                jsonStr = json.loads(data[4:])
                if len(jsonStr) !=θ:
                    for j in jsonStr:
                        usernameDomain = j['EPOEvents.TargetUserName']
                        if usernameDomain != None:
                            if len(usernameDomain) == 1:
                                username = 'Unknown'
                                domain = 'Unknown'
                            elif '\\' in usernameDomain:
                                username = usernameDomain.split('\\')[-1]
                                domain = usernameDomain.split('\\')[θ]
                            elif '\\' not in usernameDomain:
                                username = usernameDomain
                                domain = 'Unknown'
                            else:
                                username= 'Unknown'
                                domain = 'Unknown'
                            try:
                                if len(j['EPExtendedEvent.NaturalLangDescription']) > 200:
                                    #print (j['EPExtendedEvent. NaturalLangDescription'])
                                    description = "'" + (j['EPExtendedEvent.NaturalLangDescription'])[θ:200] + "'"
                                else:
                                    description = "'" + (j['EPExtendedEvent.NaturalLangDescription']) + "'"
                            except:
                                if len(j['EPOEvents.ThreatName'])> 200:
                                    description = "'" + (j['EPOEvents.ThreatName'])[0:200] + "'"
                                else:
                                    description = "'" + (j['EPOEvents.ThreatName']) + "'"
                            sql=f"""INSERT INTO LogCollection (Type, Context, Infosource,HostnameOfSource, Domain,Account, Auditer) VALUES ('Audit',{description},'mcafee',{"'" + j['EPOComputerProperties.IPHostName']},{"'" + domain + "'"},{"'" + username + "'"},'Doctor')"""
                            resultSql = executeMysqLData(3,'write', sql)
                            if resultSql == True:
                                print ('mcafee数据写入成功')
                            else:
                                print ('mcafee数据写入失败,请检查!')
                else:
                    print ('mcafee近一小时没有收到告警, no news is good news~!!')
            else:
                print ('mcafee近一小时没有收到告警, no news is good news~!!')
serverlist = {3:{"index":"<indexname>"},4:{"index":"<indexname>"},5:{"index":"<indexname>"}}
for server in serverlist:
    requestWazuhLv12(server,serverlist[server]['index'])
requestWazuhAccount()
requestMcafee()

aws IAM信息并判断权限是否开大

基于Python3写的抓取aws IAM信息并判断权限是否开大

抓取aws IAM信息并判断权限是否开大 需要调用到基础接口脚本里的数据库读写和boto3库

import boto3,json
from botocore.exceptions import ClientError
from BasicInterfaces import executeMysqlData
def list_all_iam_users():
    #列出所有 IAM 用户
    iam_client = boto3.client('iam')
    users = []
    paginator = iam_client.get_paginator('list_users')
    for response in paginator. paginate():
        for user in response['Users']:
            users.append(user['UserName'])
    return users
def get_user_attached_policies(user_name):
    #获取用户附加的所有策略
    iam_client = boto3.client('iam')
    policies = iam_client.list_attached_user_policies(UserName= user_name)['AttachedPolicies']
    return policies
def get_policy_document(policy_arn):
    #获取策略文档
    iam_client = boto3.client('iam')
    policy_details = iam_client.get_policy(PolicyArn= policy_arn)
    policy_version = iam_client.get_policy_version(PolicyArn= policy_arn,VersionId= policy_details[' Policy']['DefaultVersionId'])
    return policy_version['PolicyVersion'][' Document']
def validate_policy_with_access_analyzer(policy_document):
    #使用 Access Analyzer 验证策略
    accessanalyzer_client = boto3.client('accessanalyzer')
    try:
        response = accessanalyzer_client.validate_policy(
            policyType='IDENTITY_POLICY',
            policyDocument= json.dumps(policy _ document)
            )
            return response[' findings']
    except ClientError as e:
        print(f"[ERROR] Access Analyzer 验证失败: {e}")
        return []
def detect_overly_permissive(policy_document):
    #自定义检测策略中过于宽泛的权限
    findings = []
    for statement in policy_document['Statement']:
        if statement['Effect'] == 'Allow':
            # 检查是否存在 Action 为 * 或 iam:*
            if 'Action' in statement and ('*' in statement['Action'] or 'iam:*' in statement[' Action']):
                findings.append("found over operation privielges: {}".format(statement[' Action']))
                # 检查是否存在 Resource 为 *
            if 'Resource' in statement and '*' in statement['Resource']:
                findings.append("found over resource privielges: {}".format(statement[' Resource']))
    return findings
def analyze_user_policies(user_name):
    #分析单个用户的策略
    print(f"\n[INF0] 开始分析用户: {user_name}")
    policies = get_user_attached_policies(user_name)
    if not policies:
        print(f"[INFO] 用户 {user_name} 没有附加策略")
        return
    for policy in policies:
        print(f"分析策略: {policy['PolicyName']}")
        policy_document = get_policy_document(policy['PolicyArn'])
        findings = validate_policy_with_access_analyzer(policy_document)
        if findings:
            print(f"Access Analyzer 发现策略问题:")
            for finding in findings:
                print(f" - {finding['findingDetails']}")
                sql= f"""INSERT INTO gcpIamCheck (project, account, rules, action, recommend) VALUES ('aws',{"'" + user_name + "'"},{"'" + policy['PolicyName'+ "'"},'remove',{"'" + findings['findingDetails'] + "'"})"""
                executeMysqlData(1,' write', sql)
        print (f"自动分析策略完成,开始自定义扫描策略")
        manual_findings = detect_overly_permissive(policy_document)
        if manual_findings:
            for f in manual_findings:
                print(f"  !自定义检测发现:{f}")
                if '*' in f:
                    sql= f"INSERT INTO gcpIamCheck (project, account, rules, action, recommend) VALUES  ('aws',{"'" + user_name + "'"},{"'" + policy['PolicyName'] + "'"},'remove','resource_all')"
                else:
                    sql= f"INSERT INTO gcpIamCheck (project, account, rules, action, recommend) VALUES  ('aws',{"'" + user_name + "'"},{"'" + policy['PolicyName'] + "'"},'remove',{"'" + f + "'"))"
                executeMysqlData(1,' write', sql)
        else:
            print(f"  自定义扫描未发现宽泛权限")
def main():
    print("[INFO] 开始扫描所有 IAM 用户…\n")
    all_users = list_all_iam_users()
    print (f"发现用户{all_users}")
    if not all_users:
        print("[INFO] 当前账户没有 IAM 用户")
        return
    for user in all_users:
        analyze_user_policies(user)
main()

aws虚拟机信息抓取

基于Python3写的抓取aws虚拟机信息

拉取aws虚拟机信息 需要调用到基础接口脚本里的数据库读写和boto3库

import boto3
from BasicInterfaces import executeMysqlData
def assume_role(account_id,role_name,region_name):
    #假设角色,返回新的 AWS 会话
    sts_client = boto3.client("sts",region_name= region_name)
    role_arn = f"arn:aws:iam::{account_id}:role/{role_name}"
    #假设角色
    response = sts_client.assume_role(RoleArn= role_arn,RoleSessionName="AssumeRoleSession")
    #获取临时凭证
    credentials = response["Credentials"]
    #返回新的会话
    return boto3.Session(
        aws_access_key_id= credentials["AccessKeyId"],
        aws_secret_access_key= credentials["SecretAccessKey"],
        aws_session_token= credentials["SessionToken"],
        region_name= region_name
        )
def get_all_regions(session):
    #获取所有支持的区域
    ec2_client = session.client("ec2")
    response = ec2_client.describe_regions(AllRegions= True)
    return [region["RegionName"] for region in response[" Regions"]]
def get_ec2_instance_info(session, region_name):
    #获取指定区域内的 EC2 实例信息
    ec2_client = session.client("ec2",region_name= region _ name)
    response = ec2_client.describe_instances()
    instance_info_list = []
    for reservation in response[" Reservations"]:
        for instance in reservation[" Instances"]:
            instance_info = {
                "InstanceId": instance.get("InstanceId"),
                "Name": "",
                "Platform": instance.get("Platform", "Linux/Unix"),
                "PrivateIp": instance.get("PrivateIpAddress"),
                "PublicIp": instance.get("PublicIpAddress"),
                "SecurityGroups": [sg["GroupName"] for sg in instance. get("SecurityGroups", [])],
                "Region": region_name
                }
                #获取实例名称(从标签中获取 Name 标签)
                if"Tags" in instance:
                    for tag in instance["Tags"]:
                        if tag["Key"] == "Name":
                            instance_info["Name"] = tag["Value"]
                            break
            instance_info_list.append(instance_info)
    return instance_info_list
def main():
    #多账户配置
    accounts = [{
        "account_id": "<awsID>", 
        "role_name": "<rolename>"
        },
        {
            " account_id": "<awsID>", " role_name": "<rolename>"
        }]
    all_instances = []
    for account in accounts:
        print(f"Fetching EC2 instances for account: {account['account_id']}")
        try:
            #假设角色到第一个区域以获取所有可用区域
            session = assume_role(account["account_id"], account["role_name"], "us-east-1")
            regions = get_all_regions(session)
            for region in regions:
                try:
                    print(f"Fetching EC2 instances for region: {region}")
                    #假设角色并切换区域
                    session = assume_role(account["account_id"], account["role_name"], region)
                    instances = get_ec2_instance_info(session, region)
                    #添加账户标识
                    for instance in instances:
                        instance["AccountId"] = account["account_id"]
                        all_instances.extend(instances)
                except Exception as e:
                    pass
        except Exception as e:
            pass
    #输出所有实例信息
    for instance in all_instances:
        if instance['PublicIp'] == None:
            instance['PublicIp'] = 'Unknown'
        sql= f"""INSERT INTO gcpinfo(project, name, extip, intip, tags, machinetype, cloud) VALUES ({"'" + instance['AccountId'] +  "'"},{"'" + instance['Name'] + "'"},{"'" + instance['PublicIp'] + "'"},{"'" + instance['PrivateIp'] + "'"},{"'" + instance['InstanceType'] + "'"},{"'" + instance['Platform'] +"'"},'aws')"""
        executeMysqlData(1,'write', sql)