Linux与Windows服务器操作系统安全防御实践指南
作者:快盘下载 人气:[TOC]
0x00 前言简述
最近单位在做等保测评,由本人从事安全运维方面的工作(PS:曾经做过等保等方面的安全服务),所以自然而然的与信安的测评人员一起对接相关业务系统的检查,在做主机系统测评检查时发现了系统中某些配置不符合等保要求,需要对不满足要求的主机做进一步整改,好在我们众多的系统基本都是运行在虚拟机上搭建的kubernetes集群中,这样一来就可以尽可能减少加固系统给应用带来的影响,我们可以一台一台加固更新。
在这样环境的驱动下不得不将通宵熬夜,我准备好了枸杞和保温杯,当然也把测试环境也准备了一套,并将以前写的安全加固脚本进行重新整理,根据当前业务服务器系统版本进行更新和测试。(我还年轻,我还可加班!)
我们企业内部主要有WindowsServer2019、CentOS7、以及Ubuntu20.04三类操作系统,可以看出操作系统版本都还是比较新的,所以在下面的安全配置核查脚本以及安全加固脚本主要针对上述的三个版本的操作系统。
Linux 系统中采用Shell脚本、WiindowsServer系统中采用的是PowerShell脚本进行编写, 注意脚本会有一定更新建议通过下面的项目地址获取最新的脚本。
Github 项目地址: https://github.com/WeiyiGeek/SecOpsDev/blob/master/OS-%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F
,欢迎大家 Star 与 Fork 。
原文链接: 完整的Windows与Linux服务器系统安全加固实践和基线检测脚本(等保2.0)( https://mp.weixin.QQ.com/s/CDGzTzrAk9vJtbH4BisSlw )
WindowsSever 2019 安全配置策略基线配置核查效果图
系统基础信息
等保主机测评项
系统补丁信息
系统补丁信息
WindowsSever2019 主机测评项安全加固效果图
等保主机测评项
等保主机测评项
主机测评加固
温馨提示: 下面脚本有点长,需要有一定的耐心哟。
0x01 WindowServer2019 配置核查与安全加固
Windows 加固项目地址: https://github.com/WeiyiGeek/SecOpsDev/tree/master/OS-%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F/Windows
Windows Server 安全配置策略基线加固项
系统账号策略 系统事件审核策略系统组策略安全选项策略注册表相关安全策略防火墙服务相关安全策略针对于系统暂无办法通过注册表以及组策略配置的安全加固项从微软安全中心拉取服务器安全补丁列表信息与本地已打补丁做比较废话不多,上才艺(脚本 )
Windows Server 安全配置策略基线检测脚本 Link: https://github.com/WeiyiGeek/SecOpsDev/blob/master/OS-%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F/Windows/WindowsSecurityBaseLine.ps1
####################################################### # @Author: WeiyiGeek # @Description: Windows Server 安全配置策略基线检测脚本 # @Create Time: 2019年5月6日 11:04:42 # @Last Modified time: 2021-11-15 11:06:31 # @E-mail: master@weiyigeek.top # @Blog: https://www.weiyigeek.top # @wechat: WeiyiGeeker # @Github: https://github.com/WeiyiGeek/SecOpsDev/tree/master/OS-操作系统/Windows/ # @Version: 1.8 # @Runtime: Server 2019 / Windows 10 ####################################################### <# .SYNOPSIS Windows Server 安全配置策略基线检测脚本 (脚本将会在Github上持续更新) .DESCRIPTION Windows Server 操作系统配置策略核查 (符合等保3级的关键检查项) .EXAMPLE WindowsSecurityBaseLine.ps1 -Executor WeiyiGeek -MsrcUpdate False - Executor : 脚本执行者 - MsrcUpdate : 是否在线拉取微软安全中心的服务器安全补丁列表信息(建议一台主机拉取好之后将WSUSList.json和WSUSListId.json拷贝到当前脚本同级目录下) .NOTES 注意:不同的版本操作系统以下某些关键项可能会不存在会有一些警告(需要大家提交issue,共同完成)。 #> [Cmdletbinding()] param( [Parameter(Mandatory=$true)][String]$Executor, [Boolean]$MsrcUpdate ) # * 文件输出默认为UTF-8格式 $PSDefaultParameterValues['Out-File:Encoding'] = 'utf8' ################################################################################################################################ # **********************# # * 全局公用工具依赖函数 * # **********************# Function F_IsCurrentUserAdmin { <# .SYNOPSIS F_IsCurrentUserAdmin 函数:全局公用工具依赖。 .DESCRIPTION 判断当前运行的powershell终端是否管理员执行,返回值 true 或者 false .EXAMPLE F_IsCurrentUserAdmin #> $user = [Security.Principal.WindowsIdentity]::GetCurrent(); (New-Object Security.Principal.WindowsPrincipal $user).IsInRole([Security.Principal.WindowsBuiltinRole]::Administrator) } function F_Logging { <# .SYNOPSIS F_Logging 日志输出函数 .DESCRIPTION 用于输出脚本执行结果并按照不同的日志等级输出显示到客户终端上。 .EXAMPLE F_Logging -Level [Info|Warning|Error] -Msg "测试输出字符串" #> param ( [Parameter(Mandatory=$true)]$Msg, [ValidateSet("Info","Warning","Error")]$Level ) switch ($Level) { Info { Write-Host "[INFO] ${Msg}" -ForegroundColor Green; } Warning { Write-Host "[WARN] ${Msg}" -ForegroundColor Yellow; } Error { Write-Host "[ERROR] ${Msg}" -ForegroundColor Red; } Default { Write-Host "[*] F_Logging 日志 Level 等级错误`n Useage: F_Logging -Level [Info|Warning|Error] -Msg '测试输出字符串'" -ForegroundColor Red; } } } function F_Tools { <# .SYNOPSIS F_Tools 检测对比函数 .DESCRIPTION 验证判断传入的字段是否与安全加固字段一致 .EXAMPLE F_Tools -Key "ItemDemo" -Value "2" -Operator "eq" -DefaultValue "1" -Msg "对比ItemDemo字段值与预设值" #> param ( [Parameter(Mandatory=$true)][String]$Key, [Parameter(Mandatory=$true)]$Value, [Parameter(Mandatory=$true)]$DefaultValue, [String]$Msg, [String]$Operator ) if ( $Operator -eq "eq" ) { if ( $Value -eq $DefaultValue ) { $Result = @{"$($Key)"="[合格项]|$($Value)|$($DefaultValue)|$($Msg)-【符合】等级保护标准."} Write-Host "$($Key)"=" [合格项]|$($Value)|$($DefaultValue)|$($Msg)-【符合】等级保护标准." -ForegroundColor White return $Result } else { $Result = @{"$($Key)"="[异常项]|$($Value)|$($DefaultValue)|$($Msg)-【不符合】等级保护标准."} Write-Host "$($Key)"=" [异常项]|$($Value)|$($DefaultValue)|$($Msg)-【不符合】等级保护标准." -ForegroundColor red return $Result } } elseif ($Operator -eq "ne" ) { if ( $Value -ne $DefaultValue ) { $Result = @{"$($Key)"="[合格项]|$($Value)|$($DefaultValue)|$($Msg)-【符合】等级保护标准."} Write-Host "$($Key)"=" [合格项]|$($Value)|$($DefaultValue)|$($Msg)-【符合】等级保护标准." -ForegroundColor White return $Result } else { $Result = @{"$($Key)"="[异常项]|$($Value)|$($DefaultValue)|$($Msg)-【不符合】等级保护标准."} Write-Host "$($Key)"=" [异常项]|$($Value)|$($DefaultValue)|$($Msg)-【不符合】等级保护标准." -ForegroundColor red return $Result } } elseif ($Operator -eq "le") { if ( $Value -le $DefaultValue ) { $Result = @{"$($Key)"="[合格项]|$($Value)|$($DefaultValue)|$($Msg)-【符合】等级保护标准."} Write-Host "$($Key)"=" [合格项]|$($Value)|$($DefaultValue)|$($Msg)-【符合】等级保护标准." -ForegroundColor White return $Result } else { $Result = @{"$($Key)"="[异常项]|$($Value)|$($DefaultValue)|$($Msg)-【不符合】等级保护标准."} Write-Host "$($Key)"=" [异常项]|$($Value)|$($DefaultValue)|$($Msg)-【不符合】等级保护标准." -ForegroundColor red return $Result } } elseif ($Operator -eq "ge") { if ( $Value -ge $DefaultValue ) { $Result = @{"$($Key)"="[合格项]|$($Value)|$($DefaultValue)|$($Msg)-【符合】等级保护标准."} Write-Host "$($Key)"=" [合格项]|$($Value)|$($DefaultValue)|$($Msg)-【符合】等级保护标准." -ForegroundColor White return $Result } else { $Result = @{"$($Key)"="[异常项]|$($Value)|$($DefaultValue)|$($Msg)-【不符合】等级保护标准."} Write-Host "$($Key)"=" [异常项]|$($Value)|$($DefaultValue)|$($Msg)-【不符合】等级保护标准." -ForegroundColor red return $Result } } } function F_GetRegPropertyValue { param ( [Parameter(Mandatory=$true)][String]$Key, [Parameter(Mandatory=$true)][String]$Name, [Parameter(Mandatory=$true)][String]$Operator, [Parameter(Mandatory=$true)]$DefaultValue, [Parameter(Mandatory=$true)][String]$Msg ) try { $Value = Get-ItemPropertyValue -Path "Registry::$Key" -ErrorAction Ignore -WarningAction Ignore -Name $Name $Result = F_Tools -Key "Registry::$($Name)" -Value $Value -Operator $Operator -DefaultValue $DefaultValue -Msg $Msg return $Result } catch { $Result = @{"Registry::$($Name)"="[异常项]|$($Key)中$($Name)不存在该项|$($DefaultValue)|$($Msg)"} Write-Host $Result.Values -ForegroundColor Red return $Result } } Function F_UrlRequest { param ( [Parameter(Mandatory=$true)][String]$Msrc_api ) Write-Host "[-] $($Msrc_api)" -ForegroundColor Gray $Response=Invoke-WebRequest -Uri "$($Msrc_api)" Return ConvertFrom-Json -InputObject $Response } ################################################################################################################################ # # * 操作系统基础信息记录函数 * # # # - 系统信息记录函数 - # $SysInfo = @{} # - Get-Computer 命令使用 # Tips :在 Server 2019 以及 Windows 10 以下系统无该命令 # $Item = 'WindowsProductName','WindowsEditionId','WindowsInstallationType','WindowsCurrentVersion','WindowsVersion','WindowsProductId','BiosManufacturer','BiosFirmwareType','BiosName','BiosVersion','BiosBIOSVersion','BiosSeralNumber','CsBootupState','OsBootDevice','BiosReleaseDate','CsName','CsAdminPasswordStatus','CsManufacturer','CsModel','OsName','OsType','OsProductType','OsServerLevel','OsArchitecture','CsSystemType','OsOperatingSystemSKU','OsVersion','OsBuildNumber','OsSerialNumber','OsInstallDate','OsSystemDevice','OsSystemDirectory','OsCountryCode','OsCodeSet','OsLocaleID','OsCurrentTimeZone','TimeZone','OsLanguage','OsLocalDateTime','OsLastBootUpTime','CsProcessors','OsBuildType','CsNumberOfProcessors','CsNumberOfLogicalProcessors','OsMaxNumberOfProcesses','OsTotalVisibleMemorySize','OsFreePhysicalMemory','OsTotalVirtualMemorySize','OsFreeVirtualMemory','OsInUseVirtualMemory','OsMaxProcessMemorySize','CsNetworkAdapters','OsHotFixes' # - Systeminfo 命令使用(通用-推荐) $Item = 'Hostname','OSName','OSVersion','OSManufacturer','OSConfiguration','OS Build Type','RegisteredOwner','RegisteredOrganization','Product ID','Original Install Date','System Boot Time','System Manufacturer','System Model','System Type','Processor(s)','BIOS Version','Windows Directory','System Directory','Boot Device','System Locale','Input Locale','Time Zone','Total Physical Memory','Available Physical Memory','Virtual Memory: Max Size','Virtual Memory: Available','Virtual Memory: In Use','Page File Location(s)','Domain','Logon Server','Hotfix(s)','Network Card(s)' Function F_SysInfo { # - 当前系统及计算机相关信息 (Primary) # Server 2019 以及 Windows 10 适用 # $Computer = Get-ComputerInfo $Computer = systeminfo.exe /FO CSV /S $env:COMPUTERNAME |Select-Object -Skip 1 | ConvertFrom-CSV -Header $Item foreach( $key in $Item) { $SysInfo += @{"$($key)"=$Computer.$key} } # - 通用设置针对采用`systeminfo.exe`命令方式 $SysInfo += @{"WindowsProductName"="$($SysInfo.OSName)"} $SysInfo.OsVersion=($Sysinfo.OSVersion -split " ")[0] $SysInfo += @{"CsSystemType"=($Sysinfo."System Type" -split " ")[0]} # - 当前系统 PowerShell 版本信息以及是否为虚拟机 $SysInfo += @{"PSVersion"=$PSVersionTable.PSEdition+"-"+$PSVersionTable.PSVersion} # - 验证当前计算机产品及其版本 (Primary) $Flag = $SysInfo.WindowsProductName -match "Windows 8.1|Windows 10|Server 2008|Server 2012|Server 2016|Server 2019" $ProductName = "$($Matches.Values)" if ( $ProductName.Contains("Windows")) { $SysInfo += @{"ProductType"="Client"} $SysInfo += @{"ProductName"=$ProductName} $SysInfo += @{"WindowsVersion"=Get-ItemPropertyValue -Path 'Registry::HKEY_LOCAL_MACHINESOFTWAREMicrosoftWindows NTCurrentVersion' -Name ReleaseId} } else { $SysInfo += @{"ProductType"="Server"} $SysInfo += @{"ProductName"=$ProductName} } # - 验证当前计算机产品是是物理机还是虚拟机 (Primary) $ComputerType = get-wmiobject win32_computersystem if ($ComputerType.Manufacturer -match "vmware"){ $SysInfo += @{"ComputerType"="虚拟机 - $($ComputerType.Model)"} } else { $SysInfo += @{"ComputerType"="物理机 - $($ComputerType.Model)"} } # # - 当前计算机温度值信息记录 (WINDOWSERVER2019支持) # Get-CimInstance -Namespace ROOT/WMI -Class MSAcpi_ThermalZoneTemperature | % { # $currentTempKelvin = $_.CurrentTemperature / 10 # $currentTempCelsius = $currentTempKelvin - 273.15 # $currentTempFahrenheit = (9/5) * $currentTempCelsius + 32 # $Temperature += "InstanceName: " + $_.InstanceName+ " ==>> " + $currentTempCelsius.ToString() + " 摄氏度(C); " + $currentTempFahrenheit.ToString() + " 华氏度(F) ; " + $currentTempKelvin + "开氏度(K) `n" # } # $SysInfo += @{"Temperature"=$Temperature} return $SysInfo } # # * - 计算机Mac及IP地址信息函数 * # # # * 系统网络及适配器信息变量 * # $SysNetAdapter = @{} function F_SysNetAdapter { # - 计算机Mac及IP地址信息 $Adapter = Get-NetAdapter | Sort-Object -Property LinkSpeed foreach ( $Item in $Adapter) { $IPAddress = (Get-NetIPAddress -AddressFamily IPv4 -InterfaceIndex $Item.ifIndex).IPAddress $SysNetAdapter += @{"$($Item.MacAddress)"="$($Item.Status) | $($Item.Name) | $($IPAddress) | $($Item.LinkSpeed) | $($Item.InterfaceDescription)"} } return $SysNetAdapter } # # * - 计算机系统磁盘与空间剩余查询函数 * # # # - 系统磁盘与空间剩余信息 - # $SysDisk = @{} function F_SysDisk { # - 计算机磁盘信息 $Disk = Get-Disk foreach ( $Item in $Disk) { $SysDisk += @{"$($Item.SerialNumber)"="$($Item.Number) | $($Item.FriendlyName) | $($Item.HealthStatus)| $($Item.Size / [math]::Pow(1024,3)) GB | $($Item.PartitionStyle) |$($Item.OperationalStatus)"} } $Drive = Get-PSDrive -PSProvider FileSystem | Sort-Object -Property Name $Drive | % { $Free = [Math]::Round( $_.Free / [math]::pow(1024,3),2 ) $Used = [Math]::Round( $_.Used / [math]::pow(1024,3),2 ) $Total = [Math]::Ceiling($Free + $Used) $SysDisk += @{"FileSystem::$($_.Name)"="$($_.Name) | Free: $($Free) GB | Used: $($Used) GB | Total: $($Total) GB"} } return $SysDisk } # # * 系统账号检查函数 * # # # - 系统账户信息变量 - # $SysAccount = @{} Function F_SysAccount { # - 账户检查 $Account = Get-WmiObject -Class Win32_UserAccount | Select-Object Name,AccountType,Caption,SID Write-Host "* 当前系统存在的 $($Account.Length) 名账户 : $($Account.Name)" -ForegroundColor Green if($Acount.Length -ge 4 -and ($Account.sid | Select-String -Pattern "^((?!(-500|-501|-503|-504)).)*$")) { $Result = @{"SysAccount"="[异常项]-系统中存在其他账号请检查: $($Account.Name)"} $SysAccount += $Result }else{ $Result = @{"SysAccount"="[合格项]-系统中无多余其他账号";} $SysAccount += $Result } return $SysAccount } # # * 系统账号策略配置核查函数 * # # # - 系统账号策略 - # $SysAccountPolicy = @{ # + 密码最短留存期 "MinimumPasswordAge" = @{operator="le";value=1;msg="密码最短留存期"} # + 密码最长留存期 "MaximumPasswordAge" = @{operator="le";value=90;msg="密码最长留存期"} # + 密码长度最小值 "MinimumPasswordLength" = @{operator="ge";value=14;msg="密码长度最小值"} # + 密码必须符合复杂性要求 "PasswordComplexity" = @{operator="eq";value=1;msg="密码必须符合复杂性要求策略"} # + 强制密码历史 N个记住的密码 "PasswordHistorySize" = @{operator="ge";value=3;msg="强制密码历史个记住的密码"} # + 账户登录失败锁定阈值N次数 "LockoutBadCount" = @{operator="le";value=6;msg="账户登录失败锁定阈值次数"} # + 账户锁定时间(分钟) "ResetLockoutCount" = @{operator="ge";value=15;msg="账户锁定时间(分钟)"} # + 复位账户锁定计数器时间(分钟) "LockoutDuration" = @{operator="ge";value=15;msg="复位账户锁定计数器时间(分钟)"} # + 下次登录必须更改密码 "RequireLogonToChangePassword" = @{operator="eq";value=0;msg="下次登录必须更改密码"} # + 强制过期 "ForceLogoffWhenHourExpire" = @{operator="eq";value=0;msg="强制过期"} # + 当前管理账号登陆名称 "NewAdministratorName" = @{operator="ne";value='"Administrator"';msg="当前系统默认管理账号登陆名称策略"} # + 当前来宾用户登陆名称 "NewGuestName" = @{operator="ne";value='"Guest"';msg="当前系统默认来宾用户登陆名称策略"} # + 管理员是否被启用 "EnableAdminAccount" = @{operator="eq";value=1;msg="管理员账户停用与启用策略"} # + 来宾用户是否启用 "EnableGuestAccount" = @{operator="eq";value=0;msg="来宾账户停用与启用策略"} # + 指示是否使用可逆加密来存储密码一般禁用(除非应用程序要求超过保护密码信息的需要) "ClearTextPassword" = @{operator="eq";value=0;msg="指示是否使用可逆加密来存储密码 (除非应用程序要求超过保护密码信息的需要)"} # + 启用时此设置允许匿名用户查询本地LSA策略(0关闭) "LSAAnonymousNameLookup" = @{operator="eq";value=0;msg="启用时此设置允许匿名用户查询本地LSA策略 (0关闭)"} # + 检查结果存放的空数组 "CheckResults" = @() } Function F_SysAccountPolicy { $Count = $Config.Count for ($i=0;$i -lt $Count; $i++){ $Line = $Config[$i] -split " = " if ($SysAccountPolicy.ContainsKey("$($Line[0])")) { $Result = F_Tools -Key "SysAccountPolicy::$($Line[0])" -Value $Line[1] -Operator $SysAccountPolicy["$($Line[0])"].Operator -DefaultValue $SysAccountPolicy["$($Line[0])"].Value -Msg "系统账号策略配置-$($SysAccountPolicy["$($Line[0])"].Msg)" $SysAccountPolicy['CheckResults'] += $Result } if ( $Line[0] -eq "[Event Audit]" ) { break;} } return $SysAccountPolicy['CheckResults'] } # # * 系统事件审核策略配置核查函数 * # # # - 系统事件审核策略 - # $SysEventAuditPolicy = @{ # + 审核系统事件(0) [成功(1)、失败(2)] (3) AuditSystemEvents = @{operator="eq";value=3;msg="审核系统事件"} # + 审核登录事件 成功、失败 AuditLogonEvents = @{operator="eq";value=3;msg="审核登录事件"} # + 审核对象访问 成功、失败 AuditObjectAccess = @{operator="eq";value=3;msg="审核对象访问"} # + 审核特权使用 失败 AuditPrivilegeUse = @{operator="ge";value=2;msg="审核特权使用"} # + 审核策略更改 成功、失败 AuditPolicyChange = @{operator="eq";value=3;msg="审核策略更改"} # + 审核账户管理 成功、失败 AuditAccountManage = @{operator="eq";value=3;msg="审核账户管理"} # + 审核过程追踪 失败 AuditProcessTracking = @{operator="ge";value=2;msg="审核过程追踪"} # + 审核目录服务访问 失败 AuditDSAccess = @{operator="ge";value=2;msg="审核目录服务访问"} # + 审核账户登录事件 成功、失败 AuditAccountLogon = @{operator="eq";value=3;msg="审核账户登录事件"} # + 检查结果存放的空数组 CheckResults = @() } function F_SysEventAuditPolicy { $Count = $Config.Count for ($i=0;$i -lt $Count; $i++){ $Line = $Config[$i] -split " = " if ( $Line[0] -eq "[Registry Values]" ) { break;} if ($SysEventAuditPolicy.ContainsKey("$($Line[0])")) { $Result = F_Tools -Key "SysEventAuditPolicy::$($Line[0])" -Value $Line[1] -Operator $SysEventAuditPolicy["$($Line[0])"].Operator -DefaultValue $SysEventAuditPolicy["$($Line[0])"].Value -Msg "系统账号策略配置-$($SysEventAuditPolicy["$($Line[0])"].Msg)" $SysEventAuditPolicy['CheckResults'] += $Result } } return $SysEventAuditPolicy['CheckResults'] } # # * 操作系统用户权限管理策略检查 * # # # - 组策略用户权限管理策略 - # $SysUserPrivilegePolicy = @{ # + 操作系统本地关机策略安全 SeShutdownPrivilege = @{operator="eq";value='*S-1-5-32-544';msg="操作系统本地关机策略"} # + 操作系统远程关机策略安全 SeRemoteShutdownPrivilege = @{operator="eq";value='*S-1-5-32-544';msg="操作系统远程关机策略"} # + 取得文件或其他对象的所有权限策略 SeProfileSingleProcessPrivilege = @{operator="eq";value='*S-1-5-32-544';msg="取得文件或其他对象的所有权限策略"} # + 从网络访问此计算机策略 SeNetworkLogonRight = @{operator="eq";value='*S-1-5-32-544,*S-1-5-32-545,*S-1-5-32-551';msg="从网络访问此计算机策略"} CheckResults = @() } Function F_SysUserPrivilegePolicy { # - 策略组用户权限配置 $Hash = $SysUserPrivilegePolicy.Clone() # 巨坑之处 foreach ( $Name in $Hash.keys) { if ( $Name.Equals("CheckResults")){ continue; } $Line = ($Config | Select-String $Name.toString()) -split " = " $Result = F_Tools -Key "SysUserPrivilegePolicy::$($Line[0])" -Value $Line[1] -Operator $SysUserPrivilegePolicy["$($Line[0])"].Operator -DefaultValue $SysUserPrivilegePolicy["$($Line[0])"].Value -Msg "策略组用户权限配置-$($SysUserPrivilegePolicy["$($Line[0])"].Msg)" $SysUserPrivilegePolicy['CheckResults'] += $Result } return $SysUserPrivilegePolicy['CheckResults'] } # # * 操作系统策略组安全选项权限配置检查 * # # # - 组策略安全选项策略 - # $SysSecurityOptionPolicy = @{ # - 帐户:使用空密码的本地帐户只允许进行控制台登录(启用),注意此设置不影响使用域帐户的登录。(0禁用|1启用) LimitBlankPasswordUse = @{operator="eq";value="MACHINESystemCurrentControlSetControlLsaLimitBlankPasswordUse=4,1";msg="帐户-使用空密码的本地帐户只允许进行控制台登录(启用)"} # - 交互式登录: 不显示上次登录用户名值(启用) DontDisplayLastUserName = @{operator="eq";value="MACHINESoftwareMicrosoftWindowsCurrentVersionPoliciesSystemDontDisplayLastUserName=4,1";msg="交互式登录-不显示上次登录用户名值(启用)"} # - 交互式登录: 登录时不显示用户名 DontDisplayUserName = @{operator="eq";value="MACHINESoftwareMicrosoftWindowsCurrentVersionPoliciesSystemDontDisplayUserName=4,1";msg="交互式登录: 登录时不显示用户名"} # - 交互式登录: 锁定会话时显示用户信息(不显示任何信息) DontDisplayLockedUserId = @{operator="eq";value="MACHINESoftwareMicrosoftWindowsCurrentVersionPoliciesSystemDontDisplayLockedUserId=4,3";msg="交互式登录: 锁定会话时显示用户信息(不显示任何信息)"} # - 交互式登录: 无需按 CTRL+ALT+DEL(禁用) DisableCAD = @{operator="eq";value="MACHINESoftwareMicrosoftWindowsCurrentVersionPoliciesSystemDisableCAD=4,0";msg="交互式登录-无需按CTRL+ALT+DEL值(禁用)"} # - 交互式登录:计算机不活动限制值为600秒或更少 InactivityTimeoutSecs = @{operator="le";value="MACHINESoftwareMicrosoftWindowsCurrentVersionPoliciesSystemInactivityTimeoutSecs=4,600";msg="交互式登录-计算机不活动限制值为600秒或更少"} # - 交互式登录: 计算机帐户阈值此策略设置确定可导致计算机重启的失败登录尝试次数 MaxDevicePasswordFailedAttempts = @{operator="le";value="MACHINESoftwareMicrosoftWindowsCurrentVersionPoliciesSystemMaxDevicePasswordFailedAttempts=4,10";msg="交互式登录: 此策略设置确定可导致计算机重启的失败登录尝试次数"} # - 交互式登录: 试图登录的用户的消息标题 LegalNoticeCaption = @{operator="eq";value='MACHINESoftwareMicrosoftWindowsCurrentVersionPoliciesSystemLegalNoticeCaption=1,"安全登陆"';msg="交互式登录: 试图登录的用户的消息标题"} # - 交互式登录: 试图登录的用户的消息文本 LegalNoticeText = @{operator="eq";value='MACHINESoftwareMicrosoftWindowsCurrentVersionPoliciesSystemLegalNoticeText=7,请谨慎的操作服务器中数据,您所有操作将被记录审计';msg="交互式登录: 试图登录的用户的消息文本"} # - Microsoft网络客户端: 将未加密的密码发送到第三方 SMB 服务器(禁用) EnablePlainTextPassword = @{operator="eq";value="MACHINESystemCurrentControlSetServicesLanmanWorkstationParametersEnablePlainTextPassword=4,0";msg="Microsoft网络客户端-将未加密的密码发送到第三方 SMB 服务器(禁用)"} # - Microsoft网络服务器:暂停会话前所需的空闲时间数量值为15分钟或更少但不为0 AutoDisconnect = @{operator="eq";value="MACHINESystemCurrentControlSetServicesLanManServerParametersAutoDisconnect=4,15";msg="Microsoft网络服务器-暂停会话前所需的空闲时间数量值为15分钟"} # - 网络安全: 再下一次改变密码时不存储LAN管理器哈希值(启用) NoLMHash = @{operator="eq";value="MACHINESystemCurrentControlSetControlLsaNoLMHash=4,1";msg="网络安全-在下一次改变密码时不存储LAN管理器哈希值(启用)"} # - 网络访问: 不允许SAM账户的匿名枚举值为(启用) RestrictAnonymousSAM = @{operator="eq";value="MACHINESystemCurrentControlSetControlLsaRestrictAnonymousSAM=4,1";msg="网络访问-不允许SAM账户的匿名枚举值为(启用)"} # - 网络访问:不允许SAM账户和共享的匿名枚举值为(启用) RestrictAnonymous = @{operator="eq";value="MACHINESystemCurrentControlSetControlLsaRestrictAnonymous=4,1";msg="网络访问-不允许SAM账户和共享的匿名枚举值为(启用)"} # - 关机:设置确定是否可以在无需登录 Windows 的情况下关闭计算机(禁用) ClearPageFileAtShutdown = @{operator="eq";value="MACHINESystemCurrentControlSetControlSession ManagerMemory ManagementClearPageFileAtShutdown=4,0";msg="关机-设置确定是否可以在无需登录 Windows 的情况下关闭计算机(禁用)"} "CheckResults" = @() } Function F_SysSecurityOptionPolicy { $Hash = $SysSecurityOptionPolicy.Clone() # 巨坑之处 foreach ( $Name in $Hash.keys) { if ( $Name.Equals("CheckResults")){ continue; } $Flag = $Config | Select-String $Name.toString() $Value = $SysSecurityOptionPolicy["$($Name)"].Value -split "," if ( $Flag ) { $Line = $Flag -split "," $Result = F_Tools -Key "SysSecurityOptionPolicy::$($Name)" -Value $Line[1] -Operator $SysSecurityOptionPolicy["$($Name)"].Operator -DefaultValue $Value[1] -Msg "策略组安全选项配置-$($SysSecurityOptionPolicy["$($Name)"].Msg)" $SysSecurityOptionPolicy['CheckResults'] += $Result } else { $Result = @{"SysSecurityOptionPolicy::$($Name)"="[异常项]|未配置|$($Value[1])|策略组安全选项配置-$($SysSecurityOptionPolicy["$($Name)"].Msg)-【不符合】等级保护标准."} $SysSecurityOptionPolicy['CheckResults'] += $Result } } return $SysSecurityOptionPolicy['CheckResults'] } # # * 操作系统注册表相关配置检查函数 * # # # - 注册表相关安全策略 - $SysRegistryPolicy = @{ # + 屏幕自动保护程序 ScreenSaveActive = @{regname="HKEY_CURRENT_USERControl PanelDesktop";name="ScreenSaveActive";operator="eq";value=1;msg="系统基配核查-屏幕自动保护程序策略"} # + 屏幕恢复时使用密码保护 ScreenSaverIsSecure = @{regname="HKEY_CURRENT_USERControl PanelDesktop";name="ScreenSaverIsSecure";operator="eq";value=1;msg="系统基配核查-屏幕恢复时使用密码保护策略"} # + 屏幕保护程序启动时间 ScreenSaveTimeOut = @{regname="HKEY_CURRENT_USERControl PanelDesktop";name="ScreenSaveTimeOut";operator="le";value=600;msg="系统基配核查-屏幕保护程序启动时间策略"} # + 禁止全部驱动器自动播放 DisableAutoplay = @{regname="HKEY_CURRENT_USERSoftwareMicrosoftWindowsCurrentVersionPoliciesExplorer";name="DisableAutoplay";regtype="DWord";operator="eq";value=1;msg="禁止全部驱动器自动播放"} NoDriveTypeAutoRun = @{regname="HKEY_CURRENT_USERSoftwareMicrosoftWindowsCurrentVersionPoliciesExplorer";name="NoDriveTypeAutoRun";regtype="DWord";operator="eq";value=255;msg="禁止全部驱动器自动播放"} # - 检查关闭默认共享盘 restrictanonymous = @{regname="HKEY_LOCAL_MACHINESYSTEMCurrentControlSetControlLsa";name="restrictanonymous";operator="eq";value=1;msg="系统网络基配核查-关闭默认共享盘策略"} restrictanonymoussam = @{regname="HKEY_LOCAL_MACHINESYSTEMCurrentControlSetControlLsa";name="restrictanonymoussam";regtype="DWord";operator="eq";value=1;msg="不允许SAM账户的匿名枚举值为(启用)"} # - 禁用磁盘共享(SMB) AutoShareWks = @{regname="HKEY_LOCAL_MACHINESYSTEMCurrentControlSetServiceslanmanserverparameters";name="AutoShareWks";regtype="DWord";operator="eq";value=0;msg="关闭禁用默认共享策略-Server2012"} AutoShareServer = @{regname="HKEY_LOCAL_MACHINESYSTEMCurrentControlSetServiceslanmanserverparameters";name="AutoShareServer";regtype="DWord";operator="eq";value=0;msg="关闭禁用默认共享策略-Server2012"} # - 系统、应用、安全、PS日志查看器大小设置(此处设置默认的两倍配置-建议一定通过日志采集平台采集系统日志比如ELK) EventlogSystemMaxSize = @{regname="HKEY_LOCAL_MACHINESYSTEMCurrentControlSetServicesEventlogSystem";name="MaxSize";operator="ge";value=41943040;msg="系统基日志配核查-系统日志查看器大小设置策略"} EventlogApplicationMaxSize = @{regname="HKEY_LOCAL_MACHINESYSTEMCurrentControlSetServicesEventlogApplication";name="MaxSize";operator="ge";value=41943040;msg="系统日志基配核查-应用日志查看器大小设置策略"} EventlogSecurityMaxSize = @{regname="HKEY_LOCAL_MACHINESYSTEMCurrentControlSetServicesEventlogSecurity";name="MaxSize";operator="ge";value=41943040;msg="系统日志基配核查-安全日志查看器大小设置策略"} EventlogPSMaxSize = @{regname="HKEY_LOCAL_MACHINESYSTEMCurrentControlSetServicesEventlogWindows PowerShell";name="MaxSize";operator="ge";value=31457280;msg="系统日志基配核查-PS日志查看器大小设置策略"} # - 防火墙相关操作设置(开启、协议、服务) DomainEnableFirewall = @{regname='HKEY_LOCAL_MACHINESYSTEMCurrentControlSetServicesSharedAccessParametersFirewallPolicyDomainProfile';name='EnableFirewall';regtype="DWord";operator="eq";value=1;msg="开启域网络防火墙"} StandardEnableFirewall = @{regname='HKEY_LOCAL_MACHINESYSTEMCurrentControlSetservicesSharedAccessParametersFirewallPolicyStandardProfile';name='EnableFirewall';regtype="DWord";operator="eq";value=1;msg="开启专用网络防火墙"} PPEnableFirewall = @{regname='HKEY_LOCAL_MACHINESYSTEMCurrentControlSetservicesSharedAccessParametersFirewallPolicyPublicProfile';name='EnableFirewall';regtype="DWord";operator="eq";value=1;msg="开启公用网络防火墙"} # - 结果存储 CheckResults=@() } Function F_SysRegistryPolicy { $Registry= $SysRegistryPolicy.Clone() foreach ( $item in $Registry.keys) { if ( $item -eq "CheckResults" ){ continue;} $Result = F_GetRegPropertyValue -Key $SysRegistryPolicy.$item.regname -Name $SysRegistryPolicy.$item.name -Operator $SysRegistryPolicy.$item.operator -DefaultValue $SysRegistryPolicy.$item.value -Msg $SysRegistryPolicy.$item.msg $SysRegistryPolicy['CheckResults'] += $Result } return $SysRegistryPolicy['CheckResults'] } # # * 操作系统服务及运行程序检查函数 * # # $SysProcessServicePolicy = @{"CheckResults"=@()} function F_SysProcessServicePolicy { # + 检测系统及用户开机启动项 $SysAutoStart = Get-Item -Path 'HKLM:SOFTWAREMicrosoftWindowsCurrentVersionRun' $SysAutoStart.GetValueNames() | % { $res += "$($_)#$($SysAutoStart.GetValue($_)) " } $Result = @{"SysProcessServicePolicy::SysAutoStart"=$res} $SysProcessServicePolicy['CheckResults'] += $Result $UserAutoStart = Get-Item -Path 'HKCU:SoftwareMicrosoftWindowsCurrentVersionRun' $UserAutoStart.GetValueNames() | % { $res += "$($_)#$($SysAutoStart.GetValue($_)) " } $Result = @{"SysProcessServicePolicy::UserAutoStart"=$res} $SysProcessServicePolicy['CheckResults'] += $Result # + 否启用远程桌面服务 $RDPStatus = (Get-Service -Name "TermService").Status # if ($RDP -eq "0" -and $RDPStatus -eq "Running" ) { # $Result = @{"SysProcessServicePolicy::RDPStatus"="当前系统【已启用】远程桌面服务."} # } else { # $Result = @{"SysProcessServicePolicy::RDPStatus"="当前系统【未启用】远程桌面服务."} # } if ($RDPStatus -eq "Running" ) { $Result = F_GetRegPropertyValue -Key 'HKEY_LOCAL_MACHINESystemCurrentControlSetControlTerminal Server' -Name 'fDenyTSConnections' -Operator "eq" -DefaultValue 0 -Msg "是否将远程桌面服务禁用" } else { $Result = @{"SysProcessServicePolicy::RDPStatus"="当前系统【未启用】远程桌面服务."} } $SysProcessServicePolicy['CheckResults'] += $Result # - 否启用NTP服务来同步时钟 # $NTP = F_GetReg -Key 'HKEY_LOCAL_MACHINESYSTEMCurrentControlSetServicesW32TimeTimeProvidersNtpServer' -Name 'Enabled' # if ( $NTP -eq "1") { # $Result = @{"SysProcessServicePolicy::NtpServerEnabled"="[合格项]|$NTP|1|系统基础配置核查-启用NTP服务同步时钟策略-【符合】等级保护标准."} # } else { # $Result = @{"SysProcessServicePolicy::NtpServerEnabled"="[异常项]|$NTP|1|系统基础配置核查-启用NTP服务同步时钟策略-【不符合】等级保护标准."} # } $Result = F_GetRegPropertyValue -Key 'HKEY_LOCAL_MACHINESYSTEMCurrentControlSetServicesW32TimeTimeProvidersNtpServer' -Name 'Enabled' -Operator "eq" -DefaultValue 1 -Msg "是否启用NTP服务同步时钟策略" $SysProcessServicePolicy['CheckResults'] += $Result # - 是否修改默认的远程桌面端口 $RDP1 = Get-Item 'HKLM:SYSTEMCurrentControlSetControlTerminal ServerWinStationsRDP-Tcp' | % {$_.GetValue("PortNumber")} $RDP2 = Get-Item 'HKLM:SYSTEMCurrentControlSetControlTerminal ServerWds dpwdTds cp' | % {$_.GetValue("PortNumber")} if ( $RDP1 -eq $RDP2 -and $RDP2 -ne "3389") { $Result = @{"SysProcessServicePolicy::RDPPort"="[合格项]|$RDP1|除3389以外的端口|系统基础配置核查-默认的远程桌面端口已修改-【符合】等级保护标准."} } else { $Result = @{"SysProcessServicePolicy::RDPPort"="[异常项]|$RDP1|除3389以外的端口|系统基础配置核查-默认的远程桌面端口未修改-【不符合】等级保护标准."} } $SysProcessServicePolicy['CheckResults'] += $Result } # # * 操作系统安全检测函数 * # # * 微软Windows服务器安全补丁列表信息 * # $Msrc_api = "https://api.msrc.microsoft.com/sug/v2.0/zh-CN/affectedProduct?%24orderBy=releaseDate+desc&%24filter=productFamilyId+in+%28%27100000010%27%29+and+severityId+in+%28%27100000000%27%2C%27100000001%27%29+and+%28releaseDate+gt+2020-01-14T00%3A00%3A00%2B08%3A00%29+and+%28releaseDate+lt+2021-05-22T23%3A59%3A59%2B08%3A00%29" $SysWSUSList = @{} $SysWSUSListId = @() $AvailableWSUSList = @{} function F_SysSecurityPolicy { # - 系统补丁验证 if ( $MsrcUpdate -or ! (Test-Path -Path .WSUSList.json) ) { $MSRC_JSON = F_UrlRequest -Msrc_api $Msrc_api $MSRC_JSON.value | % { $id = $_.id; $product = $_.product; $articleName = $_.kbArticles.articleName | Get-Unique; $fixedBuildNumber = $_.kbArticles.fixedBuildNumber | Get-Unique; $severity = $_.severity; $impact = $_.impact; $baseScore = $_.baseScore; $cveNumber = $_.cveNumber | Get-Unique; $releaseDate = $_.releaseDate $SysWSUSList += @{"$($id)"=@{"product"=$product;"articleName"=$articleName;"fixedBuildNumber"=$fixedBuildNumber;"severity"=$severity;"impact"=$impact;"baseScore"=$baseScore;"cveNumber"=$cveNumber;"releaseDate"=$releaseDate}} } while ($MSRC_JSON.'@odata.nextLink'.length) { $MSRC_JSON = F_UrlRequest -Msrc_api $MSRC_JSON.'@odata.nextLink' $MSRC_JSON.value | % { $id = $_.id; $product = $_.product; $articleName = $_.kbArticles.articleName | Get-Unique; $fixedBuildNumber = $_.kbArticles.fixedBuildNumber | Get-Unique; $severity = $_.severity; $impact = $_.impact; $baseScore = $_.baseScore; $cveNumber = $_.cveNumber | Get-Unique; $releaseDate = $_.releaseDate $SysWSUSList += @{"$($id)"=@{"product"=$product;"articleName"=$articleName;"fixedBuildNumber"=$fixedBuildNumber;"severity"=$severity;"impact"=$impact;"baseScore"=$baseScore;"cveNumber"=$cveNumber;"releaseDate"=$releaseDate }} } } Write-Host "[-] 已从 Microsoft 安全响应中心获取更新 $($MSRC_JSON.'@odata.count') 条补丁信息!" -ForegroundColor Green Write-Host "[-] 正在将获取的更新 $($MSRC_JSON.'@odata.count') 条补丁信息写入到本地 WSUSList.json 文件之中!" -ForegroundColor Green $SysWSUSList | ConvertTo-Json | Out-File WSUSList.json -Encoding utf8 $SysWSUSListId = $SysWSUSList.keys $SysWSUSList.keys | ConvertTo-Json | Out-File WSUSListId.json -Encoding utf8 } else { # 从本地读取JSON文件存储的补丁信息。 if (Test-Path -Path .WSUSList.json) { $SysWSUSList = Get-Content -Raw -Encoding UTF8 .WSUSList.json | ConvertFrom-Json $SysWSUSListId = Get-Content -Raw -Encoding UTF8 .WSUSListId.json | ConvertFrom-Json Write-Host "[-] 已从本地 WSUSList.json 文件获得 $($SysWSUSListId.count) 条补丁信息!" -ForegroundColor Green } else { Write-Host "[-] 本地未能找到存放补丁信息的 WSUSList.json 文件! 请采用 -Update True 标记从Microsoft 安全响应中心获取更新" -ForegroundColor Red break exit } } # 获取当前系统版本可用的补丁列表 $AvailableWSUSListId = @() if ($SysInfo.ProductType -eq "Client") { Write-Host "[-] Desktop Client" -ForegroundColor Gray foreach ($KeyName in $SysWSUSListId) { if(($SysWSUSList."$KeyName".product -match $SysInfo.ProductName) -and ($SysWSUSList."$KeyName".product -match $SysInfo.WindowsVersion) -and ($SysWSUSList."$KeyName".product -match ($SysInfo.CsSystemType -split " ")[0])) { if (($SysWSUSList."$KeyName".fixedBuildNumber -match $SysInfo.OsVersion) -or ($SysWSUSList."$KeyName".fixedBuildNumber.length -eq 0 )) { $AvailableWSUSList."$KeyName" = $SysWSUSList."$KeyName" $AvailableWSUSListId += "$KeyName" } } } } else { Write-Host "[-] Windows Server" -ForegroundColor Gray foreach ($KeyName in $SysWSUSListId) { if(($SysWSUSList."$KeyName".product -match $SysInfo.ProductName) -and ($SysWSUSList."$KeyName".product -match $SysInfo.ProductName)) { $AvailableWSUSList."$KeyName" = $SysWSUSList."$KeyName" $AvailableWSUSListId += "$KeyName" } } } Write-Host $SysInfo.ProductName $SysInfo.WindowsVersion ($SysInfo.CsSystemType -split " ")[0] $SysInfo.OsVersion Write-Host "[-] 已从梳理出适用于当前 $($SysInfo.ProductType) 系统版本的 $($AvailableWSUSList.count) 条补丁信息!`n" -ForegroundColor Green # 已安装的补丁 $InstallWSUSList = @{} $msg = @() foreach ($id in $AvailableWSUSListId) { if( $SysInfo.'Hotfix(s)' -match $AvailableWSUSList."$id".articleName ) { $InstallWSUSList."$id" = $SysWSUSList."$id" $msg += "[+]" + $SysWSUSList."$id".product + $SysWSUSList."$id".fixedBuildNumber + " " + $SysWSUSList."$id".articleName + "(" + $SysWSUSList."$id".cveNumber + ")" + $SysWSUSList."$id".severity + $SysWSUSList."$id".baseScore + "`n" } } Write-Host "[-] $($SysInfo.'Hotfix(s)') ,共 $($AvailableWSUSList.count) 条漏洞补丁信息!`n$($msg)" -ForegroundColor Green # 未安装的补丁 $NotInstallWSUSList = @{} $msg = @() foreach ($id in $AvailableWSUSListId) { if(-not($InstallWSUSList."$id")) { $NotInstallWSUSList."$id" = $SysWSUSList."$id" $msg += "[+]" + $SysWSUSList."$id".product + $SysWSUSList."$id".fixedBuildNumber + " " + $SysWSUSList."$id".articleName + "(" + $SysWSUSList."$id".cveNumber + ")" + $SysWSUSList."$id".severity + $SysWSUSList."$id".baseScore + "`n" } } Write-Host "[-] 未安装 $($NotInstallWSUSList.count) 条漏洞补丁信息,共 $($AvailableWSUSList.count) 条漏洞补丁信息!`n$($msg)" -ForegroundColor red } # # * 杂类检测函数 * # $OtherCheck = @{} function F_OtherCheckPolicy { # - 当前系统已安装的软件 $Product = Get-WmiObject -Class Win32_Product | Select-Object -Property Name,Version,IdentifyingNumber | Sort-Object Name | Out-String $OtherCheck += @{"Product"="$($Product)"} # - 当前系统最近访问文件或者目录 $Recent = (Get-ChildItem ~AppDataRoamingMicrosoftWindowsRecent).Name $OtherCheck += @{"Recent"="$($Recent)"} return $OtherCheck } function Main() { <# .SYNOPSIS main 函数程序执行入口 .DESCRIPTION 调用上述编写的相关检测脚本 .EXAMPLE main #> $ScanStartTime = Get-date -Format 'yyyy-M-d H:m:s' F_Logging -Level Info -Msg "#################################################################################" F_Logging -Level Info -Msg "- @Desc: Windows Server 安全配置策略基线检测脚本 [将会在Github上持续更新-star]" F_Logging -Level Info -Msg "- @Author: WeiyiGeek" F_Logging -Level Info -Msg "- @Blog: https://www.weiyigeek.top" F_Logging -Level Info -Msg "- @Github: https://github.com/WeiyiGeek/SecOpsDev/tree/master/OS-操作系统/Windows" F_Logging -Level Info -Msg "#################################################################################`n" F_Logging -Level Info -Msg "[*] Windows Server 安全配置策略基线检测脚本已启动." F_Logging -Level Info -Msg "[*] 脚本执行: $($Executor), 是否在线拉取微软安全中心的服务器安全补丁列表信息: $($MsrcUpdate)`n" # 1.判断当前运行的powershell终端是否管理员执行 F_Logging -Level Info -Msg "[-] 正在检测当前运行的PowerShell终端是否管理员权限...`n" $flag = F_IsCurrentUserAdmin if (!($flag)) { F_Logging -Level Error -Msg "[*] 脚本执行发生错误,请使用管理员权限运行该脚本..例如: Start-Process powershell -Verb runAs...." F_Logging -Level Warning -Msg "[*] 正在退出执行该脚本......" return } F_Logging -Level Info -Msg "[*] PowerShell 管理员权限检查通过...`n" # 2.当前系统策略配置文件导出 (注意必须系统管理员权限运行) F_Logging -Level Info -Msg "[-] 正在导出当前系统策略配置文件 config.cfg......`n" secedit /export /cfg config.cfg /quiet start-sleep 3 if ( -not(Test-Path -Path config.cfg)) { F_Logging -Level Error -Msg "[*] 当前系统策略配置文件 config.cfg 不存在,请检查......`n" F_Logging -Level Warning -Msg "[*] 正在退出执行该脚本......" return } else { Copy-Item -Path config.cfg -Destination config.cfg.bak -Force } $Config = Get-Content -path config.cfg # 3.系统相关信息以及系统安全组策略检测 F_Logging -Level Info -Msg "[-] 当前系统信息一览" $SysInfo = F_SysInfo $SysInfo F_Logging -Level Info -Msg "[-] 当前系统网络信息一览" $SysNetAdapter = F_SysNetAdapter $SysNetAdapter F_Logging -Level Info -Msg "[-] 当前系统磁盘信息一览" $SysDisk = F_SysDisk $SysDisk F_Logging -Level Info -Msg "[-] 当前系统账户信息一览" $SysAccount = F_SysAccount $SysAccount F_Logging -Level Info -Msg "[-] 当前系统安全策略信息一览" $SysAccountPolicy.CheckResults = F_SysAccountPolicy $SysEventAuditPolicy.CheckResults = F_SysEventAuditPolicy $SysUserPrivilegePolicy.CheckResults = F_SysUserPrivilegePolicy $SysSecurityOptionPolicy.CheckResults = F_SysSecurityOptionPolicy $SysRegistryPolicy.CheckResults = F_SysRegistryPolicy $SysProcessServicePolicy.CheckResults = F_SysProcessServicePolicy F_Logging -Level Info -Msg "[-] 当前系统杂类信息一览" $OtherCheck = F_OtherCheckPolicy $OtherCheck.Values F_Logging -Level Info -Msg "[-] 当前系统安全补丁情况信息一览" F_SysSecurityPolicy # 4.程序执行完毕 $ScanEndTime = Get-date -Format 'yyyy-M-d H:m:s' F_Logging -Level Info -Msg "- Windows Server 安全配置策略基线检测脚本已执行完毕......`n开始时间:${ScanStartTime}`n完成时间: ${ScanEndTime}" } Main
0x02 CentOS7 系统初始化安全加固
描述: 适用于企业内部 CentOS7 系列服务器操作系统初始化、系统安全加固脚本,内容包含了,网络初始化设置,软件更新源替换以及内核版本升级 ,时间时区初始化设置 系统安全加固(符合等保三级主机测评项) 安全运维设置 、系统内核参数优化、 常用软件安装等 一系列的操作直接开箱即用, 将跑过该脚本的机器可以克隆成为作为线上生产环境的基线模板。
原文链接: 完整的Windows与Linux服务器系统安全加固实践和基线检测脚本(等保2.0)( https://mp.weixin.qq.com/s/CDGzTzrAk9vJtbH4BisSlw )
CentOS7 安全加固效果
CentOS7 安全加固效果
项目地址: https://github.com/WeiyiGeek/SecOpsDev/tree/master/OS-%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F/Linux/CentOS
【GitHub Repo stars](https://img.shields.io/github/stars/weiyigeek/SecOpsDev?style=social) [![GitHub forks](https://img.shields.io/github/forks/WeiyiGeek/SecOpsDev?style=social) 】,欢迎大家 Star 与 Fork 。
CentOS7 TLS Security Initiate Link: https://github.com/WeiyiGeek/SecOpsDev/blob/master/OS-%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F/Linux/CentOS/7/CentOS7-InitializeSecurity.sh
温馨提示: 使用脚本时请按照你的需求调用相应函数即可。
#!/bin/bash # @Author: WeiyiGeek # @Description: CentOS7 TLS Security Initiate # @Create Time: 2019年5月6日 11:04:42 # @Last Modified time: 2021-11-15 11:06:31 # @E-mail: master@weiyigeek.top # @Blog: https://www.weiyigeek.top # @wechat: WeiyiGeeker # @Github: https://github.com/WeiyiGeek/SecOpsDev/tree/master/OS-操作系统/Linux/ # @Version: 3.3 ## ----------------------------------------- ## # 脚本主要功能说明: # (1) CentOS7系统初始化操作包括IP地址设置、基础软件包更新以及安装加固。 # (2) CentOS7系统容器以及JDK相关环境安装。 # (3) CentOS7系统中异常错误日志解决。 # (4) CentOS7系统中常规服务安装配置,加入数据备份目录。 # (4) CentOS7脚本错误解决和优化 ## ----------------------------------------- ## ## 系统全局变量定义 # [系统配置] HOSTNAME=CentOS-Security-Template EXECTIME=$(date +%Y%m%d-%m%S) # [网络配置] IPADDR=192.168.1.2 NETMASK=225.255.255.0 GATEWAY=192.168.1.1 DNSIP=("223.5.5.5" "223.6.6.6") SSHPORT=20211 # [用户设置] DefaultUser="WeiyiGeek" # 系统创建的用户名称非root用户 ROOTPASS=WeiyiGeek # 密码建议12位以上且包含数字、大小写字母以及特殊字符。 APPPASS=WeiyiGeek # [SNMP配置] SNMP_user=WeiyiGeek SNMP_group=testgroup SNMP_view=testview SNMP_password=dont_use_public SNMP_ip=127.0.0.1 # [配置备份目录] BACKUPDIR=/var/log/.backups if [ ! -d ${BACKUPDIR} ];then mkdir -vp ${BACKUPDIR}; fi # [配置记录目录] HISDIR=/var/log/.history if [ ! -d ${HISDIR} ];then mkdir -vp ${HISDIR}; fi ## 名称: err 、info 、warning ## 用途:全局Log信息打印函数 ## 参数: $@ log::err() { printf "[$(date +'%Y-%m-%dT%H:%M:%S')]: 33[31mERROR: $@ 33[0m " } log::info() { printf "[$(date +'%Y-%m-%dT%H:%M:%S')]: 33[32mINFO: $@ 33[0m " } log::warning() { printf "[$(date +'%Y-%m-%dT%H:%M:%S')]: 33[33mWARNING: $@ 33[0m " } ## 名称: os::Network ## 用途: 操作系统网络配置相关脚本包括(IP地址修改) ## 参数: 无 os::Network(){ log::info "[-] 操作系统网络配置相关脚本,开始执行....." # (1) 静态网络IP地址设置 tee /opt/network.sh <<'EOF' #!/bin/bash IPADDR="${1}" NETMASK="${2}" GATEWAY="${3}" DEVNAME="ifcfg-ens192" if [ "${4}" != "" ];then DEVNAME="ifcfg-${4}" fi if [[ $# -lt 3 ]];then echo -e "e[32m[*] Usage: $0 IP-Address MASK Gateway e[0m" echo -e "e[32m[*] Usage: $0 192.168.1.99 255.255.255.0 192.168.1.1 e[0m" exit 1 fi NET_FILE="/etc/sysconfig/network-scripts/${DEVNAME}" if [[ ! -f ${NET_FILE} ]];then log::err "[*] Not Found ${NET_FILE} File" exit 2 fi cp ${NET_FILE}{,.bak} sed -i -e 's/^ONBOOT=.*$/ONBOOT="yes"/' -e 's/^BOOTPROTO=.*$/BOOTPROTO="static"/' ${NET_FILE} grep -q "^IPADDR=.*$" ${NET_FILE} && sed -i "s/^IPADDR=.*$/IPADDR="${IPADDR}"/" ${NET_FILE} || echo "IPADDR="${IPADDR}"" >> ${NET_FILE} grep -q "^NETMASK=.*$" ${NET_FILE} && sed -i "s/^NETMASK=.*$/NETMASK="${NETMASK}"/" ${NET_FILE} || echo "NETMASK="${NETMASK}"" >> ${NET_FILE} grep -q "^GATEWAY=.*$" ${NET_FILE} && sed -i "s/^GATEWAY=.*$/IPADDR="${GATEWAY}"/" ${NET_FILE} || echo "GATEWAY="${GATEWAY}"" >> ${NET_FILE} EOF chmod +x /opt/network.sh /opt/network.sh ${IPADDR} ${NETMASK} ${GATEWAY} # (2) 系统主机名与本地解析设置 sudo hostnamectl set-hostname ${HOSTNAME} # sed -i "s/127.0.1.1s.w.*$/127.0.1.1 ${NAME}/g" /etc/hosts cp -a /etc/hosts ${BACKUPDIR}/hosts.bak grep -q "^$(hostname -I)s.w.*$" /etc/hosts && sed -i "s/$(hostname -I)s.w.*$/${IPADDR} ${HOSTNAME}" /etc/hosts || echo "${IPADDR} ${HOSTNAME}" >> /etc/hosts # (3) 系统DNS域名解析服务设置 cp -a /etc/resolv.conf ${BACKUPDIR}/resolv.conf.bak for dns in ${DNSIP[@]};do echo "nameserver ${dns}" >> /etc/resolv.conf;done log::info "[*] network configure modifiy successful! restarting Network........." service network restart && ip addr } ## 名称: os::Software ## 用途: 操作系统软件包管理及更新源配置相关脚本 ## 参数: 无 os::Software () { log::info "[-] 操作系统软件包管理及更新源配置相关脚本,开始执行....." cp -a /etc/yum.repos.d/CentOS-Base.repo ${BACKUPDIR}/CentOS-Base.repo # (1) CentOS 软件仓库镜像源配置&&初始化更新 log::info "[*] CentOS 软件仓库镜像源配置&&初始化更新 " curl -o /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo curl -o /etc/yum.repos.d/CentOS-epel.repo http://mirrors.aliyun.com/repo/epel-7.repo sed -i "s#mirrors.cloud.aliyuncs.com#mirrors.aliyun.com#g" /etc/yum.repos.d/CentOS-Base.repo rpm --import http://mirrors.aliyun.com/centos/RPM-GPG-KEY-CentOS-7 yum clean all && yum makecache yum --exclude=kernel* update -y && yum upgrade -y && yum -y install epel* # (2) CentOS 操作系统内核升级(可选) cp -a /etc/grub2.cfg ${BACKUPDIR}/grub2.cfg.kernelupdate.bak log::info "[*] CentOS 操作系统内核升级(可选) " rpm --import https://www.elrepo.org/RPM-GPG-KEY-elrepo.org yum -y install https://www.elrepo.org/elrepo-release-7.el7.elrepo.noarch.rpm yum --disablerepo="*" --enablerepo=elrepo-kernel repolist yum --disablerepo="*" --enablerepo=elrepo-kernel list kernel* # 内核安装,服务器里我们选择长期lt版本,安全稳定是我们最大的需求,除非有特殊的需求内核版本需求; yum update -y --enablerepo=elrepo-kernel # 内核版本介绍, lt:longterm 的缩写长期维护版, ml:mainline 的缩写最新主线版本; yum install -y --enablerepo=elrepo-kernel --skip-broken kernel-lt kernel-lt-devel kernel-lt-tools # yum -y --enablerepo=elrepo-kernel --skip-broken install kernel-ml.x86_64 kernel-ml-devel.x86_64 kernel-ml-tools.x86_64 log::warning "[*] 当前 CentOS 操作系统可切换的内核内核版本" awk -F ' '$1=="menuentry " {print i++ " : " $2}' /etc/grub2.cfg sudo grub2-set-default 0 #传统引导 # grub2-mkconfig -o /boot/grub2/grub.cfg # grubby --default-kernel reboot # (3) 安装常用的运维软件 # 编译软件 yum install -y gcc gcc-c++ g++ make jq libpam-cracklib openssl-devel bzip2-devel # 常规软件 yum install -y nano vim git unzip wget ntpdate dos2unix net-tools yum install -y tree htop ncdu nload sysstat psmisc bash-completion fail2ban nfs-utils chrony # 清空缓存和已下载安装的软件包 yum clean all log::info "[*] Software configure modifiy successful!Please Happy use........." } ## 名称: os::TimedataZone ## 用途: 操作系统系统时间时区配置相关脚本 ## 参数: 无 os::TimedataZone() { log::info "[*] 操作系统系统时间时区配置相关脚本,开始执行....." # (1) 时区设置东8区 log::info "[*] 时区设置前的时间: $(date -R) " timedatectl cp -a /etc/localtime ${BACKUPDIR}/localtime.bak ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime # (2) 时间同步软件安装 grep -q "192.168.12.254" /etc/chrony.conf || sudo tee -a /etc/chrony.conf <<'EOF' pool 192.168.12.254 iburst maxsources 1 pool 192.168.10.254 iburst maxsources 1 pool 192.168.4.254 iburst maxsources 1 pool ntp.aliyun.com iburst maxsources 4 keyfile /etc/chrony.keys driftfile /var/lib/chrony/chrony.drift logdir /var/log/chrony maxupdateskew 100.0 rtcsync makestep 1.0 3 #stratumweight 0.05 #noclientlog #logchange 0.5 EOF systemctl enable chronyd && systemctl restart chronyd && systemctl status chronyd -l # 将当前的 UTC 时间写入硬件时钟 (硬件时间默认为UTC) sudo timedatectl set-local-rtc 0 # 启用NTP时间同步: timedatectl set-ntp yes # 时间服务器连接查看 chronyc tracking # 手动校准-强制更新时间 # chronyc -a makestep # 硬件时钟(系统时钟同步硬件时钟 ) hwclock --systohc # 备用方案: 采用 ntpdate 进行时间同步 ntpdate 192.168.10.254 # (3) 重启依赖于系统时间的服务 sudo systemctl restart rsyslog.service crond.service log::info "[*] Tie confmigure modifiy successful! restarting chronyd rsyslog.service crond.service........." timedatectl } ## 名称: os::Security ## 用途: 操作系统安全加固配置脚本(符合等保要求-三级要求) ## 参数: 无 os::Security () { log::info "[-] 操作系统安全加固配置(符合等保要求-三级要求)" # (0) 系统用户及其终端核查配置 log::info "[-] 锁定或者删除多余的系统账户以及创建低权限用户" # cat /etc/passwd | cut -d ":" -f 1 | tr ' ' ' ' defaultuser=(root bin daemon adm lp sync shutdown halt mail operator games FTP nobody systemd-network dbus polkitd sshd postfix chrony ntp rpc rpcuser nfsnobody) for i in $(cat /etc/passwd | cut -d ":" -f 1,7);do flag=0; name=${i%%:*}; terminal=${i##*:} if [[ "${terminal}" == "/bin/bash" || "${terminal}" == "/bin/sh" ]];then log::warning "${i} 用户,shell终端为 /bin/bash 或者 /bin/sh" fi for j in ${defaultuser[@]};do if [[ "${name}" == "${j}" ]];then flag=1 break; fi done if [[ $flag -eq 0 ]];then log::warning "${i} 非默认用户" fi done cp -a /etc/shadow ${BACKUPDIR}/shadow-${EXECTIME}.bak passwd -l adm&>/dev/null 2&>/dev/null; passwd -l daemon&>/dev/null 2&>/dev/null; passwd -l bin&>/dev/null 2&>/dev/null; passwd -l sys&>/dev/null 2&>/dev/null; passwd -l lp&>/dev/null 2&>/dev/null; passwd -l uucp&>/dev/null 2&>/dev/null; passwd -l nuucp&>/dev/null 2&>/dev/null; passwd -l smmsplp&>/dev/null 2&>/dev/null; passwd -l mail&>/dev/null 2&>/dev/null; passwd -l operator&>/dev/null 2&>/dev/null; passwd -l games&>/dev/null 2&>/dev/null; passwd -l gopher&>/dev/null 2&>/dev/null; passwd -l ftp&>/dev/null 2&>/dev/null; passwd -l nobody&>/dev/null 2&>/dev/null; passwd -l nobody4&>/dev/null 2&>/dev/null; passwd -l noaccess&>/dev/null 2&>/dev/null; passwd -l listen&>/dev/null 2&>/dev/null; passwd -l webservd&>/dev/null 2&>/dev/null; passwd -l rpm&>/dev/null 2&>/dev/null; passwd -l dbus&>/dev/null 2&>/dev/null; passwd -l avahi&>/dev/null 2&>/dev/null; passwd -l mailnull&>/dev/null 2&>/dev/null; passwd -l nscd&>/dev/null 2&>/dev/null; passwd -l vcsa&>/dev/null 2&>/dev/null; passwd -l rpc&>/dev/null 2&>/dev/null; passwd -l rpcuser&>/dev/null 2&>/dev/null; passwd -l nfs&>/dev/null 2&>/dev/null; passwd -l sshd&>/dev/null 2&>/dev/null; passwd -l pcap&>/dev/null 2&>/dev/null; passwd -l ntp&>/dev/null 2&>/dev/null; passwd -l haldaemon&>/dev/null 2&>/dev/null; passwd -l distcache&>/dev/null 2&>/dev/null; passwd -l webalizer&>/dev/null 2&>/dev/null; passwd -l squid&>/dev/null 2&>/dev/null; passwd -l xfs&>/dev/null 2&>/dev/null; passwd -l gdm&>/dev/null 2&>/dev/null; passwd -l sabayon&>/dev/null 2&>/dev/null; passwd -l named&>/dev/null 2&>/dev/null # (2) 用户密码设置和口令策略设置 log::info "[-] 配置满足策略的root管理员密码 " echo "root:${ROOTPASS}" | chpasswd log::info "[-] 配置满足策略的app普通用户密码(根据需求配置)" groupadd application useradd -m -s /bin/bash -c "application primary user" -g application app echo "root:${APPPASS}" | chpasswd log::info "[-] 强制用户在下次登录时更改密码 " chage -d 0 -m 0 -M 90 -W 15 root && passwd --expire root chage -d 0 -m 0 -M 90 -W 15 app && passwd --expire app chage -d 0 -m 0 -M 90 -W 15 ${DefaultUser} && passwd --expire ${DefaultUser} log::info "[-] 用户口令复杂性策略设置 (密码过期周期0~90、到期前15天提示、密码长度至少15、复杂度设置至少有一个大小写、数字、特殊字符、密码三次不能一样、尝试次数为三次)" # 相关修改文件备份 cp /etc/login.defs ${BACKUPDIR}/login.defs.bak; cp /etc/pam.d/password-auth ${BACKUPDIR}/password-auth.bak cp /etc/pam.d/system-auth ${BACKUPDIR}/system-auth.bak egrep -q "^s*PASS_MIN_DAYSs+S*(s*#.*)?s*$" /etc/login.defs && sed -ri "s/^(s*)PASS_MIN_DAYSs+S*(s*#.*)?s*$/PASS_MIN_DAYS 0/" /etc/login.defs || echo "PASS_MIN_DAYS 0" >> /etc/login.defs egrep -q "^s*PASS_MAX_DAYSs+S*(s*#.*)?s*$" /etc/login.defs && sed -ri "s/^(s*)PASS_MAX_DAYSs+S*(s*#.*)?s*$/PASS_MAX_DAYS 90/" /etc/login.defs || echo "PASS_MAX_DAYS 90" >> /etc/login.defs egrep -q "^s*PASS_WARN_AGEs+S*(s*#.*)?s*$" /etc/login.defs && sed -ri "s/^(s*)PASS_WARN_AGEs+S*(s*#.*)?s*$/PASS_WARN_AGE 15/" /etc/login.defs || echo "PASS_WARN_AGE 15" >> /etc/login.defs egrep -q "^s*PASS_MIN_LENs+S*(s*#.*)?s*$" /etc/login.defs && sed -ri "s/^(s*)PASS_MIN_LENs+S*(s*#.*)?s*$/PASS_MIN_LEN 15/" /etc/login.defs || echo "PASS_MIN_LEN 15" >> /etc/login.defs egrep -q "^passwords.+pam_pwquality.sos+w+.*$" /etc/pam.d/password-auth && sed -ri '/^passwords.+pam_pwquality.so/{s/pam_pwquality.sos+w+.*$/pam_pwquality.so try_first_pass local_users_only retry=3 authtok_type= minlen=15 ucredit=-1 lcredit=-1 dcredit=-1 ocredit=-1 difok=1 enforce_for_root/g;}' /etc/pam.d/password-auth egrep -q "^passwords.+pam_unix.sos+w+.*$" /etc/pam.d/password-auth && sed -ri '/^passwords.+pam_unix.so/{s/pam_unix.sos+w+.*$/pam_unix.so sha512 shadow nullok try_first_pass use_authtok remember=3/g;}' /etc/pam.d/password-auth egrep -q "^passwords.+pam_pwquality.sos+w+.*$" /etc/pam.d/system-auth && sed -ri '/^passwords.+pam_pwquality.so/{s/pam_pwquality.sos+w+.*$/pam_pwquality.so try_first_pass local_users_only retry=3 authtok_type= minlen=15 ucredit=-1 lcredit=-1 dcredit=-1 ocredit=-1 difok=1 enforce_for_root/g;}' /etc/pam.d/system-auth egrep -q "^passwords.+pam_unix.sos+w+.*$" /etc/pam.d/system-auth && sed -ri '/^passwords.+pam_unix.so/{s/pam_unix.sos+w+.*$/pam_unix.so sha512 shadow nullok try_first_pass use_authtok remember=3/g;}' /etc/pam.d/system-auth log::info "[-] 存储用户密码的文件,其内容经过sha512加密,所以非常注意其权限" # 解决首次登录配置密码时提示"passwd: Authentication token manipulation error" touch /etc/security/opasswd && chown root:root /etc/security/opasswd && chmod 600 /etc/security/opasswd # (3) 设置用户sudo权限以及重要目录和文件的新建默认权限 log::info "[-] 用户sudo权限以及重要目录和文件的新建默认权限设置" cp /etc/sudoers ${BACKUPDIR}/sudoers.bak # 如CentOS安装时您创建的用户 WeiyiGeek 防止直接通过 sudo passwd 修改root密码(此时必须要求输入WeiyiGeek密码后才可修改root密码) # Tips: Sudo允许授权用户权限以另一个用户(通常是root用户)的身份运行程序, # DefaultUser="weiyigeek" sed -i "/# Allows members of the/i ${DefaultUser} ALL=(ALL) PASSWD:ALL" /etc/sudoers # 此参数需要根据业务来定,否则在使用时候会出现某些权限不足导致程序安装报错 log::info "[-] 配置用户 umask 为022 " cp -a /etc/profile ${BACKUPDIR}/profile egrep -q "^s*umasks+w+.*$" /etc/profile && sed -ri "s/^s*umasks+w+.*$/umask 022/" /etc/profile || echo "umask 022" >> /etc/profile # log::info "[-] 设置用户目录创建默认权限, (初始为077比较严格)在未设置umask为027则默认为077" # egrep -q "^s*umasks+w+.*$" /etc/csh.login && sed -ri "s/^s*umasks+w+.*$/umask 022/" /etc/csh.login || echo "umask 022" >> /etc/csh.login # egrep -q "^s*umasks+w+.*$" /etc/csh.cshrc && sed -ri "s/^s*umasks+w+.*$/umask 022/" /etc/csh.cshrc || echo "umask 022" >> /etc/csh.cshrc # egrep -q "^s*(umask|UMASK)s+w+.*$" /etc/login.defs && sed -ri "s/^s*(umask|UMASK)s+w+.*$/UMASK 027/" /etc/login.defs || echo "UMASK 027" >> /etc/login.defs log::info "[-] 设置或恢复重要目录和文件的权限(设置日志文件非全局可写)" chmod 600 ~/.ssh/authorized_keys; chmod 755 /etc; chmod 755 /etc/passwd; chmod 755 /etc/shadow; chmod 755 /etc/security; chmod 644 /etc/group; chmod 644 /etc/services; chmod 750 /etc/rc*.d; chmod 755 /var/log/messages; chmod 775 /var/log/spooler; chmod 775 /var/log/cron; chmod 775 /var/log/secure; chmod 775 /var/log/maillog; chmod 775 /var/log/mail&>/dev/null 2&>/dev/null; chmod 775 /var/log/localmessages&>/dev/null 2&>/dev/null log::info "[-] 删除潜在威胁文件 " find / -maxdepth 3 -name hosts.equiv | xargs rm -rf find / -maxdepth 3 -name .netrc | xargs rm -rf find / -maxdepth 3 -name .rhosts | xargs rm -rf # (4) SSHD 服务安全加固设置以及网络登陆Banner设置 log::info "[-] sshd 服务安全加固设置" cp /etc/ssh/sshd_config ${BACKUPDIR}/sshd_config.bak # 严格模式 sudo egrep -q "^s*StrictModess+.+$" /etc/ssh/sshd_config && sed -ri "s/^(#)?s*StrictModess+.+$/StrictModes yes/" /etc/ssh/sshd_config || echo "StrictModes yes" >> /etc/ssh/sshd_config # 默认的监听端口更改 if [ -e ${SSHPORT} ];then export SSHPORT=20211;fi sudo egrep -q "^s*Ports+.+$" /etc/ssh/sshd_config && sed -ri "s/^(#)?s*Ports+.+$/Port ${SSHPORT}/" /etc/ssh/sshd_config || echo "Port ${SSHPORT}" >> /etc/ssh/sshd_config # 禁用X11转发以及端口转发 sudo egrep -q "^s*X11Forwardings+.+$" /etc/ssh/sshd_config && sed -ri "s/^(#)?s*X11Forwardings+.+$/X11Forwarding no/" /etc/ssh/sshd_config || echo "X11Forwarding no" >> /etc/ssh/sshd_config sudo egrep -q "^s*X11UseLocalhosts+.+$" /etc/ssh/sshd_config && sed -ri "s/^(#)?s*X11UseLocalhosts+.+$/X11UseLocalhost yes/" /etc/ssh/sshd_config || echo "X11UseLocalhost yes" >> /etc/ssh/sshd_config sudo egrep -q "^s*AllowTcpForwardings+.+$" /etc/ssh/sshd_config && sed -ri "s/^(#)?s*AllowTcpForwardings+.+$/AllowTcpForwarding no/" /etc/ssh/sshd_config || echo "AllowTcpForwarding no" >> /etc/ssh/sshd_config sudo egrep -q "^s*AllowAgentForwardings+.+$" /etc/ssh/sshd_config && sed -ri "s/^(#)?s*AllowAgentForwardings+.+$/AllowAgentForwarding no/" /etc/ssh/sshd_config || echo "AllowAgentForwarding no" >> /etc/ssh/sshd_config # 关闭禁用用户的 .rhosts 文件 ~/.ssh/.rhosts 来做为认证: 缺省IgnoreRhosts yes egrep -q "^(#)?s*IgnoreRhostss+.+$" /etc/ssh/sshd_config && sed -ri "s/^(#)?s*IgnoreRhostss+.+$/IgnoreRhosts yes/" /etc/ssh/sshd_config || echo "IgnoreRhosts yes" >> /etc/ssh/sshd_config # 禁止root远程登录(推荐配置-根据需求配置) egrep -q "^s*PermitRootLogins+.+$" /etc/ssh/sshd_config && sed -ri "s/^s*PermitRootLogins+.+$/PermitRootLogin no/" /etc/ssh/sshd_config || echo "PermitRootLogin no" >> /etc/ssh/sshd_config # 登陆前后欢迎提示设置 egrep -q "^s*(banner|Banner)s+W+.*$" /etc/ssh/sshd_config && sed -ri "s/^s*(banner|Banner)s+W+.*$/Banner /etc/issue/" /etc/ssh/sshd_config || echo "Banner /etc/issue" >> /etc/ssh/sshd_config log::info "[-] 远程SSH登录前后提示警告Banner设置" # SSH登录前后提示警告Banner设置 sudo tee /etc/issue <<'EOF' ****************** [ 安全登陆 (Security Login) ] ***************** Authorized only. All activity will be monitored and reported.By Security Center. EOF # SSH登录后提示Banner # 艺术字B格: http://www.network-science.de/ascii/ sudo tee /etc/motd <<'EOF' ################## [ 安全运维 (Security Operation) ] #################### __ __ _ _ _____ _ / / (_) (_)/ ____| | | / / /__ _ _ _ _| | __ ___ ___| | __ / / / _ | | | | | | |_ |/ _ / _ |/ / / / __/ | |_| | | |__| | __/ __/ < / / ___|_|__, |_|_____|___|___|_|_ __/ | |___/ Login success. Please execute the commands and operation data after carefully.By WeiyiGeek EOF # (5) 用户远程登录失败次数与终端超时设置 log::info "[-] 用户远程连续登录失败10次锁定帐号5分钟包括root账号" cp /etc/pam.d/sshd ${BACKUPDIR}/sshd.bak cp /etc/pam.d/login ${BACKUPDIR}/login.bak # 远程登陆 sed -ri "/^s*auths+requireds+pam_tally2.sos+.+(s*#.*)?s*$/d" /etc/pam.d/sshd sed -ri '2a auth required pam_tally2.so deny=10 unlock_time=300 even_deny_root root_unlock_time=300' /etc/pam.d/sshd # 宿主机控制台登陆(可选) # sed -ri "/^s*auths+requireds+pam_tally2.sos+.+(s*#.*)?s*$/d" /etc/pam.d/login # sed -ri '2a auth required pam_tally2.so deny=10 unlock_time=300 even_deny_root root_unlock_time=300' /etc/pam.d/login log::info "[-] 设置登录超时时间为10分钟 " egrep -q "^s*(export|)s*TMOUTSw+.*$" /etc/profile && sed -ri "s/^s*(export|)s*TMOUT.Sw+.*$/export TMOUT=600 readonly TMOUT/" /etc/profile || echo -e "export TMOUT=600 readonly TMOUT" >> /etc/profile egrep -q "^s*.*ClientAliveIntervalsw+.*$" /etc/ssh/sshd_config && sed -ri "s/^s*.*ClientAliveIntervalsw+.*$/ClientAliveInterval 600/" /etc/ssh/sshd_config || echo "ClientAliveInterval 600" >> /etc/ssh/sshd_config # (6) 切换用户日志记录和切换命令更改名称为SU log::info "[-] 切换用户日志记录和切换命令更改名称为SU " cp -a /etc/rsyslog.conf ${BACKUPDIR}/rsyslog.conf-${EXECTIME}.bak egrep -q "^s*authpriv.*s+.+$" /etc/rsyslog.conf && sed -ri "s/^s*authpriv.*s+.+$/authpriv.* /var/log/secure/" /etc/rsyslog.conf || echo "authpriv.* /var/log/secure" >> /etc/rsyslog.conf egrep -q "^(s*)SULOG_FILEs+S*(s*#.*)?s*$" /etc/login.defs && sed -ri "s/^(s*)SULOG_FILEs+S*(s*#.*)?s*$/SULOG_FILE /var/log/.history/sulog/" /etc/login.defs || echo "SULOG_FILE /var/log/.history/sulog" >> /etc/login.defs egrep -q "^s*SU_NAMEs+S*(s*#.*)?s*$" /etc/login.defs && sed -ri "s/^(s*)SU_NAMEs+S*(s*#.*)?s*$/SU_NAME SU/" /etc/login.defs || echo "SU_NAME SU" >> /etc/login.defs mkdir -vp /usr/local/bin cp /usr/bin/su ${BACKUPDIR}/su.bak mv /usr/bin/su /usr/bin/SU chmod 777 /var/log/.history chattr -R +a /var/log/.history chattr +a /var/log/.backups # (7) 用户终端执行的历史命令记录 log::info "[-] 用户终端执行的历史命令记录 " egrep -q "^HISTSIZEWw+.*$" /etc/profile && sed -ri "s/^HISTSIZEWw+.*$/HISTSIZE=101/" /etc/profile || echo "HISTSIZE=101" >> /etc/profile sudo tee /etc/profile.d/history-record.sh <<'EOF' # 历史命令执行记录文件路径 LOGTIME=$(date +%Y%m%d-%H-%M-%S) export HISTFILE="/var/log/.history/${USER}.${LOGTIME}.history" if [ ! -f ${HISTFILE} ];then touch ${HISTFILE} fi chmod 600 /var/log/.history/${USER}.${LOGTIME}.history # 历史命令执行文件大小记录设置 HISTFILESIZE=128 HISTTIMEFORMAT="%F_%T $(whoami)#$(who -u am i 2>/dev/null| awk '{print $NF}'|sed -e 's/[()]//g'):" EOF # (8) GRUB 安全设置 log::info "[-] 系统 GRUB 安全设置(防止物理接触从grub菜单中修改密码) " # Grub 关键文件备份 cp -a /etc/grub.d/00_header ${BACKUPDIR}/'00_header'${EXECTIME}.bak cp -a /etc/grub.d/10_linux ${BACKUPDIR}/'10_linux'${EXECTIME}.bak # 设置Grub菜单界面显示时间 sed -i -e 's|set timeout_style=${style}|#set timeout_style=${style}|g' -e 's|set timeout=${timeout}|set timeout=3|g' /etc/grub.d/00_header # sed -i -e 's|GRUB_TIMEOUT_STYLE=hidden|#GRUB_TIMEOUT_STYLE=hidden|g' -e 's|GRUB_TIMEOUT=0|GRUB_TIMEOUT=3|g' /etc/default/grub # grub 用户认证密码创建 sudo grub2-mkpasswd-pbkdf2 # 输入口令: # Reeter password:n PBKDF2 hash of your password is grub.pbkdf2.sha512.10000.A4A6B06EFAB660C11DD8EBC3BE73C5AB5D763ED937060477DB533B3E7D60F1DE66C3AC12DA795B46762AB8C4A1911B69B94FFCD88FB4499938150405DCB116F8.35D290F5B8D2677AEE5E8BAB4DB133206D417F99A26B14EAB8D0A5379DCD3632F40037388C9D2CA3001E0D6A8B74837549970EEEAEC3420CE38E2236DE1A8565 # 设置认证用户以及上面生成的password_pbkdf2认证密钥 tee -a /etc/grub.d/00_header <<'END' cat <<'EOF' # GRUB Authentication set superusers="grub" password_pbkdf2 grub grub.pbkdf2.sha512.10000.A4A6B06EFAB660C11DD8EBC3BE73C5AB5D763ED937060477DB533B3E7D60F1DE66C3AC12DA795B46762AB8C4A1911B69B94FFCD88FB4499938150405DCB116F8.35D290F5B8D2677AEE5E8BAB4DB133206D417F99A26B14EAB8D0A5379DCD3632F40037388C9D2CA3001E0D6A8B74837549970EEEAEC3420CE38E2236DE1A8565 EOF END # 设置进入正式系统不需要认证如进入单用户模式进行重置账号密码时需要进行认证。 (高敏感数据库系统不建议下述操作) # 在 135 加入 -unrestricted ,例如, 此处与Ubuntu不同的是不加--user=grub # 133 echo "menuentry $(echo "$title" | grub_quote)' ${CLASS} $menuentry_id_option 'gnulinux-$version-$type- $boot_device_id' {" | sed "s/^/$submenu_indentation/" # 134 else # 135 echo "menuentry --unrestricted '$(echo "$os" | grub_quote)' ${CLASS} $menuentry_id_option 'gnulinux-simple-$boot_devic e_id' {" | sed "s/^/$submenu_indentation/" sed -i '/echo "$title" | grub_quote/ { s/menuentry /menuentry /;}' /etc/grub.d/10_linux sed -i '/echo "$os" | grub_quote/ { s/menuentry /menuentry --unrestricted /;}' /etc/grub.d/10_linux # CentOS 方式更新GRUB从而生成boot启动文件 grub2-mkconfig -o /boot/grub2/grub.cfg # (9) 记录安全事件日志 log::info "[-] 记录安全事件日志" touch /var/log/.history/adm&>/dev/null; chmod 755 /var/log/.history/adm semanage fcontext -a -t security_t '/var/log/.history/adm' restorecon -v '/var/log/.history/adm'&>/dev/null egrep -q "^s**.err;kern.debug;daemon.notices+.+$" /etc/rsyslog.conf && sed -ri "s/^s**.err;kern.debug;daemon.notices+.+$/*.err;kern.debug;daemon.notice /var/log/.history/adm/" /etc/rsyslog.conf || echo "*.err;kern.debug;daemon.notice /var/log/.history/adm" >> /etc/rsyslog.conf # (10) 配置自动屏幕锁定(适用于具备图形界面的设备), 非图形界面不需要执行 log::info "[-] 对于有图形界面的系统配置10分钟屏幕锁定" # gconftool-2 --direct # --config-source xml:readwrite:/etc/gconf/gconf.xml.mandatory # --type bool # --set /apps/gnome-screensaver/idle_activation_enabled true # --set /apps/gnome-screensaver/lock_enabled true # --type int # --set /apps/gnome-screensaver/idle_delay 10 # --type string # --set /apps/gnome-screensaver/mode blank-only # (10) 关闭CentOS服务器中 SELINUX 以及防火墙端口放行 log::info "[-] SELINUX 禁用以及系统防火墙规则设置 " sed -i "s/SELINUX=enforcing/SELINUX=disabled/g" /etc/selinux/config semanage port -m -t ssh_port_t -p tcp 20211 # 添加sshd服务20211端口到SELinux firewall-cmd --zone=public --add-port=20211/tcp --permanent firewall-cmd --zone=public --add-port=161/udp --permanent firewall-cmd --reload systemctl restart sshd reboot } ## 名称: os::Operation ## 用途: 操作系统安全运维设置相关脚本 ## 参数: 无 os::Operation () { log::info "[-] 操作系统安全运维设置相关脚本" # (0) 禁用ctrl+alt+del组合键对系统重启 (必须要配置,我曾入过坑) log::info "[-] 禁用控制台ctrl+alt+del组合键重启" mv /usr/lib/systemd/system/ctrl-alt-del.target ${BACKUPDIR}/ctrl-alt-del.target-${EXECTIME}.bak # (1) 设置文件删除回收站别名 log::info "[-] 设置文件删除回收站别名(防止误删文件) " sudo tee -a /etc/profile.d/alias.sh <<'EOF' # User specific aliases and functions # 删除回收站 # find ~/.trash -delete # 删除空目录 # find ~/.trash -type d -delete alias rm="sh /usr/local/bin/remove.sh" EOF sudo tee /usr/local/bin/remove.sh <<'EOF' #!/bin/sh # 定义回收站文件夹目录.trash trash="/.trash" deltime=$(date +%Y%m%d-%H-%M-%S) TRASH_DIR="${HOME}${trash}/${deltime}" # 建立回收站目录当不存在的时候 if [ ! -e ${TRASH_DIR} ];then mkdir -p ${TRASH_DIR} fi for i in $*;do if [ "$i" = "-rf" ];then continue;fi # 防止误操作 if [ "$i" = "/" ];then echo '# Danger delete command, Not delete / directory!';exit -1;fi #定义秒时间戳 STAMP=$(date +%s) #得到文件名称(非文件夹),参考man basename fileName=$(basename $i) #将输入的参数,对应文件mv至.trash目录,文件后缀,为当前的时间戳 mv $i ${TRASH_DIR}/${fileName}.${STAMP} done EOF sudo chmod +775 /usr/local/bin/remove.sh /etc/profile.d/alias.sh /etc/profile.d/history-record.sh sudo chmod a+x /usr/local/bin/remove.sh /etc/profile.d/alias.sh /etc/profile.d/history-record.sh source /etc/profile.d/alias.sh /etc/profile.d/history-record.sh } ## 名称: os::DisableService ## 用途: 禁用与设置操作系统中某些服务(需要根据实际环境进行) ## 参数: 无 os::DisableService () { log::info "[-] 禁用操作系统中某些服务(需要根据实际环境进行配置)" log::info "[-] 配置禁用telnet服务" cp /etc/services ${BACKUPDIR}/'services-'${EXECTIME}.bak egrep -q "^s*telnets+d*.+$" /etc/services && sed -ri "/^s*telnets+d*.+$/s/^/# /" /etc/services log::info "[-] 禁止匿名与root用户用户登录FTP" if [ -f /etc/vsftpd/vsftpd.conf ];then cp /etc/vsftpd/vsftpd.conf /etc/vsftpd/'vsftpd.conf-'`date +%Y%m%d`.bak systemctl list-unit-files|grep vsftpd > /dev/null && sed -ri "/^s*anonymous_enables*W+.+$/s/^/#/" /etc/vsftpd/vsftpd.conf && echo "anonymous_enable=NO" >> /etc/vsftpd/vsftpd.conf systemctl list-unit-files|grep vsftpd > /dev/null && echo "root" >> /etc/vsftpd/ftpusers log::info "[-] 限制FTP用户上传的文件所具有的权限" systemctl list-unit-files|grep vsftpd > /dev/null && sed -ri "/^s*write_enables*W+.+$/s/^/#/" /etc/vsftpd/vsftpd.conf && echo "write_enable=NO" >> /etc/vsftpd/vsftpd.conf systemctl list-unit-files|grep vsftpd > /dev/null && sed -ri "/^s*ls_recurse_enables*W+.+$/s/^/#/" /etc/vsftpd/vsftpd.conf && echo "ls_recurse_enable=NO" >> /etc/vsftpd/vsftpd.conf systemctl list-unit-files|grep vsftpd > /dev/null && sed -ri "/^s*anon_umasks*W+.+$/s/^/#/" /etc/vsftpd/vsftpd.conf && echo "anon_umask=077" >> /etc/vsftpd/vsftpd.conf systemctl list-unit-files|grep vsftpd > /dev/null && sed -ri "/^s*local_umasks*W+.+$/s/^/#/" /etc/vsftpd/vsftpd.conf && echo "local_umask=022" >> /etc/vsftpd/vsftpd.conf log::info "[-] 限制FTP用户登录后能访问的目录" systemctl list-unit-files|grep vsftpd > /dev/null && sed -ri "/^s*chroot_local_users*W+.+$/s/^/#/" /etc/vsftpd/vsftpd.conf && echo "chroot_local_user=NO" >> /etc/vsftpd/vsftpd.conf log::info "[-] FTP Banner 设置" systemctl list-unit-files|grep vsftpd > /dev/null && sed -ri "/^s*ftpd_banners*W+.+$/s/^/#/" /etc/vsftpd/vsftpd.conf && echo "ftpd_banner='Authorized only. All activity will be monitored and reported.'" >> /etc/vsftpd/vsftpd.conf log::info "[-] 限制不必要的服务 (根据实际环境配置)" # systemctl disable rsh&>/dev/null 2&>/dev/null;systemctl disable talk&>/dev/null 2&>/dev/null;systemctl disable telnet&>/dev/null 2&>/dev/null;systemctl disable tftp&>/dev/null 2&>/dev/null;systemctl disable rsync&>/dev/null 2&>/dev/null;systemctl disable xinetd&>/dev/null 2&>/dev/null;systemctl disable nfs&>/dev/null 2&>/dev/null;systemctl disable nfslock&>/dev/null 2&>/dev/null fi log::info "[-] 配置SNMP默认团体字" if [ -f /etc/snmp/snmpd.conf ];then cp /etc/snmp/snmpd.conf ${BACKUPDIR}/'snmpd.conf-'${EXECTIME}.bak cat > /etc/snmp/snmpd.conf <<EOF com2sec $SNMP_user default $SNMP_password group $SNMP_group v1 $SNMP_user group $SNMP_group v2c $SNMP_user view systemview included .1 80 view systemview included .1.3.6.1.2.1.1 view systemview included .1.3.6.1.2.1.25.1.1 view $SNMP_view included .1.3.6.1.4.1.2021.80 access $SNMP_group "" any noauth exact systemview none none access $SNMP_group "" any noauth exact $SNMP_view none none dontLogTCPWrappersConnects yes trapcommunity $SNMP_password authtrapenable 1 trap2sink $SNMP_ip agentSecName $SNMP_user rouser $SNMP_user defaultMonitors yes linkUpDownNotifications yes EOF fi } ## 名称: os::optimizationn ## 用途: 操作系统优化设置(内核参数) ## 参数: 无 os::Optimizationn () { log::info "[-] 正在进行操作系统内核参数优化设置......." # (1) 系统内核参数的配置(/etc/sysctl.conf) log::info "[-] 系统内核参数的配置/etc/sysctl.conf" # /etc/sysctl.d/99-kubernetes-cri.conf egrep -q "^(#)?net.ipv4.ip_forward.*" /etc/sysctl.conf && sed -ri "s|^(#)?net.ipv4.ip_forward.*|net.ipv4.ip_forward = 1|g" /etc/sysctl.conf || echo "net.ipv4.ip_forward = 1" >> /etc/sysctl.conf # egrep -q "^(#)?net.bridge.bridge-nf-call-ip6tables.*" /etc/sysctl.conf && sed -ri "s|^(#)?net.bridge.bridge-nf-call-ip6tables.*|net.bridge.bridge-nf-call-ip6tables = 1|g" /etc/sysctl.conf || echo "net.bridge.bridge-nf-call-ip6tables = 1" >> /etc/sysctl.conf # egrep -q "^(#)?net.bridge.bridge-nf-call-iptables.*" /etc/sysctl.conf && sed -ri "s|^(#)?net.bridge.bridge-nf-call-iptables.*|net.bridge.bridge-nf-call-iptables = 1|g" /etc/sysctl.conf || echo "net.bridge.bridge-nf-call-iptables = 1" >> /etc/sysctl.conf egrep -q "^(#)?net.ipv6.conf.all.disable_ipv6.*" /etc/sysctl.conf && sed -ri "s|^(#)?net.ipv6.conf.all.disable_ipv6.*|net.ipv6.conf.all.disable_ipv6 = 1|g" /etc/sysctl.conf || echo "net.ipv6.conf.all.disable_ipv6 = 1" >> /etc/sysctl.conf egrep -q "^(#)?net.ipv6.conf.default.disable_ipv6.*" /etc/sysctl.conf && sed -ri "s|^(#)?net.ipv6.conf.default.disable_ipv6.*|net.ipv6.conf.default.disable_ipv6 = 1|g" /etc/sysctl.conf || echo "net.ipv6.conf.default.disable_ipv6 = 1" >> /etc/sysctl.conf egrep -q "^(#)?net.ipv6.conf.lo.disable_ipv6.*" /etc/sysctl.conf && sed -ri "s|^(#)?net.ipv6.conf.lo.disable_ipv6.*|net.ipv6.conf.lo.disable_ipv6 = 1|g" /etc/sysctl.conf || echo "net.ipv6.conf.lo.disable_ipv6 = 1" >> /etc/sysctl.conf egrep -q "^(#)?net.ipv6.conf.all.forwarding.*" /etc/sysctl.conf && sed -ri "s|^(#)?net.ipv6.conf.all.forwarding.*|net.ipv6.conf.all.forwarding = 1|g" /etc/sysctl.conf || echo "net.ipv6.conf.all.forwarding = 1" >> /etc/sysctl.conf egrep -q "^(#)?vm.max_map_count.*" /etc/sysctl.conf && sed -ri "s|^(#)?vm.max_map_count.*|vm.max_map_count = 262144|g" /etc/sysctl.conf || echo "vm.max_map_count = 262144" >> /etc/sysctl.conf tee -a /etc/sysctl.conf <<'EOF' # 调整提升服务器负载能力之外,还能够防御小流量的Dos、CC和SYN攻击 net.ipv4.tcp_syncookies = 1 net.ipv4.tcp_tw_reuse = 1 # net.ipv4.tcp_tw_recycle = 1 net.ipv4.tcp_fin_timeout = 60 net.ipv4.tcp_synack_retries = 1 net.ipv4.tcp_syn_retries = 1 net.ipv4.tcp_fastopen = 3 # 优化TCP的可使用端口范围及提升服务器并发能力(注意一般流量小的服务器上没必要设置如下参数) net.ipv4.tcp_keepalive_time = 1200 net.ipv4.tcp_max_syn_backlog = 8192 net.ipv4.tcp_max_tw_buckets = 5000 net.ipv4.ip_local_port_range = 1024 65535 # 优化核套接字TCP的缓存区 net.core.netdev_max_backlog = 8192 net.core.somaxconn = 8192 net.core.rmem_max = 12582912 net.core.rmem_default = 6291456 net.core.wmem_max = 12582912 net.core.wmem_default = 6291456 EOF # (2) Linux 系统的最大进程数和最大文件打开数限制 log::info "[-] Linux 系统的最大进程数和最大文件打开数限制 " egrep -q "^s*ulimit -HSns+w+.*$" /etc/profile && sed -ri "s/^s*ulimit -HSns+w+.*$/ulimit -HSn 65535/" /etc/profile || echo "ulimit -HSn 65535" >> /etc/profile egrep -q "^s*ulimit -HSus+w+.*$" /etc/profile && sed -ri "s/^s*ulimit -HSus+w+.*$/ulimit -HSu 65535/" /etc/profile || echo "ulimit -HSu 65535" >> /etc/profile sed -i "/# End/i * soft nofile 65535" /etc/security/limits.conf sed -i "/# End/i * hard nofile 65535" /etc/security/limits.conf sed -i "/# End/i * soft nproc 65535" /etc/security/limits.conf sed -i "/# End/i * hard nproc 65535" /etc/security/limits.conf sysctl -p # 需重启生效 reboot } ## 名称: os::Swap ## 用途: Liunx 系统创建SWAP交换分区(默认2G) ## 参数: $1(几G) os::Swap () { if [ -e $1 ];then sudo dd if=/dev/zero of=/swapfile bs=1024 count=2097152 # 2G Swap 分区 1024 * 1024 , centos 以 1000 为标准 else number=$(echo "${1}*1024*1024"|bc) sudo dd if=/dev/zero of=/swapfile bs=1024 count=${number} # 2G Swap 分区 1024 * 1024 , centos 以 1000 为标准 fi sudo mkswap /swapfile && sudo swapon /swapfile if [ $(grep -c "/swapfile" /etc/fstab) -eq 0 ];then sudo tee -a /etc/fstab <<'EOF' /swapfile swap swap default 0 0 EOF fi sudo swapon --show && sudo free -h } ## 名称: software::Java ## 用途: java 环境安装与设置 ## 参数: 无 software::Java () { # 基础变量 JAVA_FILE="/root/Downloads/jdk-8u211-linux-x64.tar.gz" JAVA_SRC="/usr/local/" JAVA_DIR="/usr/local/jdk" # 环境配置 sudo tar -zxvf ${JAVA_FILE} -C ${JAVA_SRC} sudo rm -rf /usr/local/jdk JAVA_SRC=$(ls /usr/local/ | grep "jdk") sudo ln -s ${JAVA_SRC} ${JAVA_DIR} export PATH=${JAVA_DIR}/bin:${PATH} sudo cp /etc/profile /etc/profile.$(date +%Y%m%d-%H%M%S).bak sudo tee -a /etc/profile <<'EOF' export JAVA_HOME=/usr/local/jdk export JRE_HOME=/usr/local/jdk/jre export CLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar export PATH=$JAVA_HOME/bin:$PATH EOF java -version } ## 名称: disk::Lvsmanager ## 用途: CentOS7 操作系统磁盘 LVS 逻辑卷添加与配置(扩容流程) ## 参数: 无 disk::lvsmanager () { echo " 分区信息:" sudo df -Th sudo lsblk echo -e " 磁盘信息:" sudo fdisk -l echo -e " PV物理卷查看:" sudo pvscan echo -e " vgs虚拟卷查看:" sudo vgs echo -e " lvscan逻辑卷扫描:" sudo lvscan echo -e " 分区扩展" echo "CentOS lvextend -L +24G /dev/centos/root" echo "lsblk" echo -e "Centos # xfs_growfs /dev/mapper/centos-root" } # 安全加固过程临时文件清理为基线镜像做准备 unalias rm find ~/.trash/* -delete find /home/ -type d -name .trash -exec find {} -delete ; find /var/log -name "*.gz" -delete find /var/log -name "*log.*" -delete find /var/log -name "vmware-*.*.log" -delete find /var/log -name "*.log" -exec truncate -s 0 {} ; find /var/log -name "system@*" -delete find /var/log -name "user-1000@*" -delete find /tmp/* -delete
至此 CentOS7 安全加固脚本完毕。
原文地址: Linux与Windows服务器操作系统安全防御实践指南 ( https://blog.weiyigeek.top/2020/10-13-585.html )
0x03 Ubuntu 20.04 系统初始化安全加固
描述: 适用于企业内部 Ubuntu 系列服务器操作系统初始化、系统安全加固脚本,内容包含了,网络初始化设置,软件更新源替换以及内核版本升级 ,时间时区初始化设置 系统安全加固(等保三级操作系统主机检查项) 安全运维设置 系统内核参数 常用软件安装等 一系列的操作直接开箱即用, 将跑过该脚本的机器可以克隆成为作为线上生产环境的基线模板。
原文链接: 完整的Windows与Linux服务器系统安全加固实践和基线检测脚本(等保2.0)( https://mp.weixin.qq.com/s/CDGzTzrAk9vJtbH4BisSlw )
脚本适用说明: Ubuntu 20.04 (已测试) Ubuntu 18.04 (部分适用)
Ubuntu 安全加固效果
Ubuntu 安全加固效果
项目地址: https://github.com/WeiyiGeek/SecOpsDev/tree/master/OS-%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F/Linux/Ubuntu
【GitHub Repo stars](https://img.shields.io/github/stars/weiyigeek/SecOpsDev?style=social) [![GitHub forks](https://img.shields.io/github/forks/WeiyiGeek/SecOpsDev?style=social 】,欢迎大家 Star 与 Fork 。
Ubuntu TLS Security Initiate Link: https://github.com/WeiyiGeek/SecOpsDev/blob/master/OS-%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F/Linux/Ubuntu/Ubuntu-InitializeSecurity.sh
温馨提示: 使用脚本时请按照你的需求调用相应函数即可,默认未调用任何函数。
#!/bin/bash # @Author: WeiyiGeek # @Description: Ubuntu TLS Security Initiate # @Create Time: 2019年9月1日 16:43:33 # @Last Modified time: 2021-11-15 11:06:31 # @E-mail: master@weiyigeek.top # @Blog: https://www.weiyigeek.top # @wechat: WeiyiGeeker # @Github: https://github.com/WeiyiGeek/SecOpsDev/tree/master/OS-操作系统/Linux/ # @Version: 3.3 #-------------------------------------------------# # 脚本主要功能说明: # (1) Ubuntu 系统初始化操作包括IP地址设置、基础软件包更新以及安装加固。 # (2) Ubuntu 系统容器以及JDK相关环境安装。 # (3) Ubuntu 系统中异常错误日志解决。 # (4) Ubuntu 系统常规服务安装配置,加入数据备份目录。 # (5) Ubuntu 脚本错误优化、添加禁用cloud-init #-------------------------------------------------# ## 系统全局变量定义 HOSTNAME=Ubuntu-Security-Template IP=192.168.1.2 GATEWAY=192.168.1.1 DNSIP=("223.5.5.5" "223.6.6.6") SSHPORT=20211 DefaultUser="WeiyiGeek" # 系统创建的用户名称非root用户 ROOTPASS=WeiyiGeek # 密码建议12位以上且包含数字、大小写字母以及特殊字符。 APPPASS=WeiyiGeek ## 名称: err 、info 、warning ## 用途:全局Log信息打印函数 ## 参数: $@ log::err() { printf "[$(date +'%Y-%m-%dT%H:%M:%S')]: 33[31mERROR: $@ 33[0m " } log::info() { printf "[$(date +'%Y-%m-%dT%H:%M:%S')]: 33[32mINFO: $@ 33[0m " } log::warning() { printf "[$(date +'%Y-%m-%dT%H:%M:%S')]: 33[33mWARNING: $@ 33[0m " } ## 名称: os::Network ## 用途: 网络配置相关操作脚本包括(IP地址修改) ## 参数: 无 os::Network () { log::info "[-] 操作系统网络配置相关脚本,开始执行....." # (1) IP地址与主机名称设置 sudo cp /etc/netplan/00-installer-config.yaml{,.bak} mkdir /opt/init/ sudo tee /opt/init/network.sh <<'EOF' #!/bin/bash CURRENT_IP=$(hostname -I | cut -f 1 -d " ") GATEWAY=$(hostname -I | cut -f 1,2,3 -d ".") if [[ $# -lt 3 ]];then echo "Usage: $0 IP Gateway Hostname" exit fi echo "IP:${1} # GATEWAY:${2} # HOSTNAME:${3}" sudo sed -i "s#${CURRENT_IP}#${1}#g" /etc/netplan/00-installer-config.yaml sudo sed -i "s#${GATEWAY}.1#${2}#g" /etc/netplan/00-installer-config.yaml sudo hostnamectl set-hostname ${3} sudo netplan apply EOF sudo chmod +x /opt/init/network.sh # (2) 本地主机名解析设置 sed -i "s/127.0.1.1s.w.*$/127.0.1.1 ${HOSTNAME}/g" /etc/hosts grep -q "^$(hostname -I)s.w.*$" /etc/hosts && sed -i "s/$(hostname -I)s.w.*$/${IPADDR} ${HOSTNAME}" /etc/hosts || echo "${IPADDR} ${HOSTNAME}" >> /etc/hosts # (3) 系统DNS域名解析服务设置 cp -a /etc/resolv.conf{,.bak} for dns in ${DNSIP[@]};do echo "nameserver ${dns}" >> /etc/resolv.conf;done sudo /opt/init/network.sh ${IP} ${GATEWAY} ${HOSTNAME} log::info "[*] network configure modifiy successful! restarting Network........." } ## 名称: os::Software ## 用途: 操作系统软件包管理及更新源配置 ## 参数: 无 os::Software () { log::info "[-] 操作系统软件包管理及更新源配置相关脚本,开始执行....." # (1) 卸载多余软件,例如 snap 软件及其服务 sudo systemctl stop snapd snapd.socket #停止snapd相关的进程服务 sudo apt autoremove --purge -y snapd sudo systemctl daemon-reload sudo rm -rf ~/snap /snap /var/snap /var/lib/snapd /var/cache/snapd /run/snapd # (2) 软件源设置与系统更新 sudo cp /etc/apt/sources.list{,.bak} sudo tee /etc/apt/sources.list <<'EOF' #阿里云Mirrors - Ubuntu deb http://mirrors.aliyun.com/ubuntu/ focal main restricted universe multiverse deb-src http://mirrors.aliyun.com/ubuntu/ focal main restricted universe multiverse deb http://mirrors.aliyun.com/ubuntu/ focal-security main restricted universe multiverse deb-src http://mirrors.aliyun.com/ubuntu/ focal-security main restricted universe multiverse deb http://mirrors.aliyun.com/ubuntu/ focal-updates main restricted universe multiverse deb-src http://mirrors.aliyun.com/ubuntu/ focal-updates main restricted universe multiverse deb http://mirrors.aliyun.com/ubuntu/ focal-proposed main restricted universe multiverse deb-src http://mirrors.aliyun.com/ubuntu/ focal-proposed main restricted universe multiverse deb http://mirrors.aliyun.com/ubuntu/ focal-backports main restricted universe multiverse deb-src http://mirrors.aliyun.com/ubuntu/ focal-backports main restricted universe multiverse EOF # (3) 内核版本升级以及常规软件安装 sudo apt autoclean && sudo apt update && sudo apt upgrade -y sudo apt install -y nano vim git unzip wget ntpdate dos2unix net-tools tree htop ncdu nload sysstat psmisc bash-completion fail2ban gcc g++ make jq nfs-common rpcbind libpam-cracklib # (4) 代理方式进行更新 # sudo apt autoclean && sudo apt -o Acquire::http::proxy="http://proxy.weiyigeek.top/" update && sudo apt -o Acquire::http::proxy="http://proxy.weiyigeek.top" upgrade -y # sudo apt install -o Acquire::http::proxy="http://proxy.weiyigeek.top/" -y nano vim git unzip wget ntpdate dos2unix net-tools tree htop ncdu nload sysstat psmisc bash-completion fail2ban } ## 名称: os::TimedataZone ## 用途: 操作系统时间与时区同步配置 ## 参数: 无 os::TimedataZone () { log::info "[*] 操作系统系统时间时区配置相关脚本,开始执行....." # (1) 时间同步服务端容器(可选也可以用外部ntp服务器) : docker run -d --rm --cap-add SYS_TIME -e ALLOW_CIDR=0.0.0.0/0 -p 123:123/udp geoffh1977/chrony echo "同步前的时间: $(date -R)" # 方式1.Chrony 客户端配置 apt install -y chrony grep -q "192.168.12.254" /etc/chrony/chrony.conf || sudo tee -a /etc/chrony/chrony.conf <<'EOF' pool 192.168.10.254 iburst maxsources 1 pool 192.168.12.254 iburst maxsources 1 pool 192.168.4.254 iburst maxsources 1 pool ntp.aliyun.com iburst maxsources 4 keyfile /etc/chrony/chrony.keys driftfile /var/lib/chrony/chrony.drift logdir /var/log/chrony maxupdateskew 100.0 rtcsync # 允许跳跃式校时 如果在前 3 次校时中时间差大于 1.0s makestep 1 3 EOF systemctl enable chrony && systemctl restart chrony && systemctl status chrony -l # 方式2 # sudo ntpdate 192.168.10.254 || sudo ntpdate 192.168.12.215 || sudo ntpdate ntp1.aliyun.com # 方式3 # echo 'NTP=192.168.10.254 192.168.4.254' >> /etc/systemd/timesyncd.conf # echo 'FallbackNTP=ntp.aliyun.com' >> /etc/systemd/timesyncd.conf # systemctl restart systemd-timesyncd.service # (2) 时区与地区设置: sudo cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime sudo timedatectl set-timezone Asia/Shanghai # sudo dpkg-reconfigure tzdata # 修改确认 # sudo bash -c "echo 'Asia/Shanghai' > /etc/timezone" # 与上一条命令一样 # 将当前的 UTC 时间写入硬件时钟 (硬件时间默认为UTC) sudo timedatectl set-local-rtc 0 # 启用NTP时间同步: sudo timedatectl set-ntp yes # 校准时间服务器-时间同步(推荐使用chronyc进行平滑同步) sudo chronyc tracking # 手动校准-强制更新时间 # chronyc -a makestep # 系统时钟同步硬件时钟 # sudo hwclock --systohc sudo hwclock -w # (3) 重启依赖于系统时间的服务 sudo systemctl restart rsyslog.service cron.service log::info "[*] Tie confmigure modifiy successful! restarting chronyd rsyslog.service crond.service........." timedatectl } ## 名称: os::Security ## 用途: 操作系统安全加固配置脚本(符合等保要求-三级要求) ## 参数: 无 os::Security () { log::info "正在进行->操作系统安全加固(符合等保要求-三级要求)配置" # (0) 系统用户核查配置 log::info "[-] 锁定或者删除多余的系统账户以及创建低权限用户" userdel -r lxd groupdel lxd defaultuser=(root daemon bin sys games man lp mail news uucp proxy www-data backup list irc gnats nobody systemd-network systemd-resolve systemd-timesync messagebus syslog _apt tss uuidd tcpdump landscape pollinate usbmux sshd systemd-coredump _chrony) for i in $(cat /etc/passwd | cut -d ":" -f 1,7);do flag=0; name=${i%%:*}; terminal=${i##*:} if [[ "${terminal}" == "/bin/bash" || "${terminal}" == "/bin/sh" ]];then log::warning "${i} 用户,shell终端为 /bin/bash 或者 /bin/sh" fi for j in ${defaultuser[@]};do if [[ "${name}" == "${j}" ]];then flag=1 break; fi done if [[ $flag -eq 0 ]];then log::warning "${i} 非默认用户" fi done cp /etc/shadow /etc/shadow-`date +%Y%m%d`.bak passwd -l adm&>/dev/null 2&>/dev/null; passwd -l daemon&>/dev/null 2&>/dev/null; passwd -l bin&>/dev/null 2&>/dev/null; passwd -l sys&>/dev/null 2&>/dev/null; passwd -l lp&>/dev/null 2&>/dev/null; passwd -l uucp&>/dev/null 2&>/dev/null; passwd -l nuucp&>/dev/null 2&>/dev/null; passwd -l smmsplp&>/dev/null 2&>/dev/null; passwd -l mail&>/dev/null 2&>/dev/null; passwd -l operator&>/dev/null 2&>/dev/null; passwd -l games&>/dev/null 2&>/dev/null; passwd -l gopher&>/dev/null 2&>/dev/null; passwd -l ftp&>/dev/null 2&>/dev/null; passwd -l nobody&>/dev/null 2&>/dev/null; passwd -l nobody4&>/dev/null 2&>/dev/null; passwd -l noaccess&>/dev/null 2&>/dev/null; passwd -l listen&>/dev/null 2&>/dev/null; passwd -l webservd&>/dev/null 2&>/dev/null; passwd -l rpm&>/dev/null 2&>/dev/null; passwd -l dbus&>/dev/null 2&>/dev/null; passwd -l avahi&>/dev/null 2&>/dev/null; passwd -l mailnull&>/dev/null 2&>/dev/null; passwd -l nscd&>/dev/null 2&>/dev/null; passwd -l vcsa&>/dev/null 2&>/dev/null; passwd -l rpc&>/dev/null 2&>/dev/null; passwd -l rpcuser&>/dev/null 2&>/dev/null; passwd -l nfs&>/dev/null 2&>/dev/null; passwd -l sshd&>/dev/null 2&>/dev/null; passwd -l pcap&>/dev/null 2&>/dev/null; passwd -l ntp&>/dev/null 2&>/dev/null; passwd -l haldaemon&>/dev/null 2&>/dev/null; passwd -l distcache&>/dev/null 2&>/dev/null; passwd -l webalizer&>/dev/null 2&>/dev/null; passwd -l squid&>/dev/null 2&>/dev/null; passwd -l xfs&>/dev/null 2&>/dev/null; passwd -l gdm&>/dev/null 2&>/dev/null; passwd -l sabayon&>/dev/null 2&>/dev/null; passwd -l named&>/dev/null 2&>/dev/null # (2) 用户密码设置和口令策略设置 log::info "[-] 配置满足策略的root管理员密码 " echo ${ROOTPASS} | passwd --stdin root log::info "[-] 配置满足策略的app普通用户密码(根据需求配置)" groupadd application useradd -m -s /bin/bash -c "application primary user" -g application app echo ${APPPASS} | passwd --stdin app log::info "[-] 强制用户在下次登录时更改密码 " chage -d 0 -m 0 -M 90 -W 15 root && passwd --expire root chage -d 0 -m 0 -M 90 -W 15 ${DefaultUser} && passwd --expire ${DefaultUser} chage -d 0 -m 0 -M 90 -W 15 app && passwd --expire app log::info "[-] 用户口令复杂性策略设置 (密码过期周期0~90、到期前15天提示、密码长度至少15、复杂度设置至少有一个大小写、数字、特殊字符、密码三次不能一样、尝试次数为三次)" egrep -q "^s*PASS_MIN_DAYSs+S*(s*#.*)?s*$" /etc/login.defs && sed -ri "s/^(s*)PASS_MIN_DAYSs+S*(s*#.*)?s*$/PASS_MIN_DAYS 0/" /etc/login.defs || echo "PASS_MIN_DAYS 0" >> /etc/login.defs egrep -q "^s*PASS_MAX_DAYSs+S*(s*#.*)?s*$" /etc/login.defs && sed -ri "s/^(s*)PASS_MAX_DAYSs+S*(s*#.*)?s*$/PASS_MAX_DAYS 90/" /etc/login.defs || echo "PASS_MAX_DAYS 90" >> /etc/login.defs egrep -q "^s*PASS_WARN_AGEs+S*(s*#.*)?s*$" /etc/login.defs && sed -ri "s/^(s*)PASS_WARN_AGEs+S*(s*#.*)?s*$/PASS_WARN_AGE 15/" /etc/login.defs || echo "PASS_WARN_AGE 15" >> /etc/login.defs egrep -q "^s*PASS_MIN_LENs+S*(s*#.*)?s*$" /etc/login.defs && sed -ri "s/^(s*)PASS_MIN_LENs+S*(s*#.*)?s*$/PASS_MIN_LEN 15/" /etc/login.defs || echo "PASS_MIN_LEN 15" >> /etc/login.defs egrep -q "^passwords.+pam_cracklib.sos+w+.*$" /etc/pam.d/common-password && sed -ri '/^passwords.+pam_cracklib.so/{s/pam_cracklib.sos+w+.*$/pam_cracklib.so retry=3 minlen=15 ucredit=-1 lcredit=-1 dcredit=-1 ocredit=-1 difok=1/g;}' /etc/pam.d/common-password egrep -q "^passwords.+pam_unix.sos+w+.*$" /etc/pam.d/common-password && sed -ri '/^passwords.+pam_unix.so/{s/pam_unix.sos+w+.*$/pam_unix.so obscure use_authtok try_first_pass sha512 remember=3/g;}' /etc/pam.d/common-password log::info "[-] 存储用户密码的文件,其内容经过sha512加密,所以非常注意其权限" touch /etc/security/opasswd && chown root:root /etc/security/opasswd && chmod 600 /etc/security/opasswd # (3) 用户sudo权限以及重要目录和文件的权限设置 log::info "[-] 用户sudo权限以及重要目录和文件的新建默认权限设置" # 如uBuntu安装时您创建的用户 WeiyiGeek 防止直接通过 sudo passwd 修改root密码(此时必须要求输入WeiyiGeek密码后才可修改root密码) # Tips: Sudo允许授权用户权限以另一个用户(通常是root用户)的身份运行程序, # DefaultUser="weiyigeek" sed -i "/# Members of the admin/i ${DefaultUser} ALL=(ALL) PASSWD:ALL" /etc/sudoers log::info "[-] 配置用户 umask 为022 " egrep -q "^s*umasks+w+.*$" /etc/profile && sed -ri "s/^s*umasks+w+.*$/umask 022/" /etc/profile || echo "umask 022" >> /etc/profile egrep -q "^s*umasks+w+.*$" /etc/bash.bashrc && sed -ri "s/^s*umasks+w+.*$/umask 022/" /etc/bashrc || echo "umask 022" >> /etc/bash.bashrc # log::info "[-] 设置用户目录创建默认权限, (初始为077比较严格),在设置 umask 为022 及 777 - 022 " # egrep -q "^s*(umask|UMASK)s+w+.*$" /etc/login.defs && sed -ri "s/^s*(umask|UMASK)s+w+.*$/UMASK 022/" /etc/login.defs || echo "UMASK 022" >> /etc/login.defs log::info "[-] 设置或恢复重要目录和文件的权限" chmod 755 /etc; chmod 777 /tmp; chmod 700 /etc/inetd.conf&>/dev/null 2&>/dev/null; chmod 755 /etc/passwd; chmod 755 /etc/shadow; chmod 644 /etc/group; chmod 755 /etc/security; chmod 644 /etc/services; chmod 750 /etc/rc*.d chmod 600 ~/.ssh/authorized_keys log::info "[-] 删除潜在威胁文件 " find / -maxdepth 3 -name hosts.equiv | xargs rm -rf find / -maxdepth 3 -name .netrc | xargs rm -rf find / -maxdepth 3 -name .rhosts | xargs rm -rf # (4) SSHD 服务安全加固设置 log::info "[-] sshd 服务安全加固设置" # 严格模式 sudo egrep -q "^s*StrictModess+.+$" /etc/ssh/sshd_config && sed -ri "s/^(#)?s*StrictModess+.+$/StrictModes yes/" /etc/ssh/sshd_config || echo "StrictModes yes" >> /etc/ssh/sshd_config # 监听端口更改 if [ -e ${SSHPORT} ];then export SSHPORT=20211;fi sudo egrep -q "^s*Ports+.+$" /etc/ssh/sshd_config && sed -ri "s/^(#)?s*Ports+.+$/Port ${SSHPORT}/" /etc/ssh/sshd_config || echo "Port ${SSHPORT}" >> /etc/ssh/sshd_config # 禁用X11转发以及端口转发 sudo egrep -q "^s*X11Forwardings+.+$" /etc/ssh/sshd_config && sed -ri "s/^(#)?s*X11Forwardings+.+$/X11Forwarding no/" /etc/ssh/sshd_config || echo "X11Forwarding no" >> /etc/ssh/sshd_config sudo egrep -q "^s*X11UseLocalhosts+.+$" /etc/ssh/sshd_config && sed -ri "s/^(#)?s*X11UseLocalhosts+.+$/X11UseLocalhost yes/" /etc/ssh/sshd_config || echo "X11UseLocalhost yes" >> /etc/ssh/sshd_config sudo egrep -q "^s*AllowTcpForwardings+.+$" /etc/ssh/sshd_config && sed -ri "s/^(#)?s*AllowTcpForwardings+.+$/AllowTcpForwarding no/" /etc/ssh/sshd_config || echo "AllowTcpForwarding no" >> /etc/ssh/sshd_config sudo egrep -q "^s*AllowAgentForwardings+.+$" /etc/ssh/sshd_config && sed -ri "s/^(#)?s*AllowAgentForwardings+.+$/AllowAgentForwarding no/" /etc/ssh/sshd_config || echo "AllowAgentForwarding no" >> /etc/ssh/sshd_config # 关闭禁用用户的 .rhosts 文件 ~/.ssh/.rhosts 来做为认证: 缺省IgnoreRhosts yes egrep -q "^(#)?s*IgnoreRhostss+.+$" /etc/ssh/sshd_config && sed -ri "s/^(#)?s*IgnoreRhostss+.+$/IgnoreRhosts yes/" /etc/ssh/sshd_config || echo "IgnoreRhosts yes" >> /etc/ssh/sshd_config # 禁止root远程登录(推荐配置-根据需求配置) egrep -q "^s*PermitRootLogins+.+$" /etc/ssh/sshd_config && sed -ri "s/^s*PermitRootLogins+.+$/PermitRootLogin no/" /etc/ssh/sshd_config || echo "PermitRootLogin no" >> /etc/ssh/sshd_config # 登陆前后欢迎提示设置 egrep -q "^s*(banner|Banner)s+W+.*$" /etc/ssh/sshd_config && sed -ri "s/^s*(banner|Banner)s+W+.*$/Banner /etc/issue/" /etc/ssh/sshd_config || echo "Banner /etc/issue" >> /etc/ssh/sshd_config log::info "[-] 远程SSH登录前后提示警告Banner设置" # SSH登录前警告Banner sudo tee /etc/issue <<'EOF' ****************** [ 安全登陆 (Security Login) ] ***************** Authorized only. All activity will be monitored and reported.By Security Center. EOF # SSH登录后提示Banner sed -i '/^fi/an echo "e[1;37;41;5m################## 安全运维 (Security Operation) ####################e[0m" echo "e[32mLogin success. Please execute the commands and operation data carefully.By WeiyiGeek.e[0m"' /etc/update-motd.d/00-header # (5) 用户远程登录失败次数与终端超时设置 log::info "[-] 用户远程连续登录失败10次锁定帐号5分钟包括root账号" sed -ri "/^s*auths+requireds+pam_tally2.sos+.+(s*#.*)?s*$/d" /etc/pam.d/sshd sed -ri '2a auth required pam_tally2.so deny=10 unlock_time=300 even_deny_root root_unlock_time=300' /etc/pam.d/sshd # 宿主机控制台登陆(可选) # sed -ri "/^s*auths+requireds+pam_tally2.sos+.+(s*#.*)?s*$/d" /etc/pam.d/login # sed -ri '2a auth required pam_tally2.so deny=5 unlock_time=300 even_deny_root root_unlock_time=300' /etc/pam.d/login log::info "[-] 设置登录超时时间为10分钟 " egrep -q "^s*(export|)s*TMOUTSw+.*$" /etc/profile && sed -ri "s/^s*(export|)s*TMOUT.Sw+.*$/export TMOUT=600 readonly TMOUT/" /etc/profile || echo -e "export TMOUT=600 readonly TMOUT" >> /etc/profile egrep -q "^s*.*ClientAliveIntervalsw+.*$" /etc/ssh/sshd_config && sed -ri "s/^s*.*ClientAliveIntervalsw+.*$/ClientAliveInterval 600/" /etc/ssh/sshd_config || echo "ClientAliveInterval 600" >> /etc/ssh/sshd_config # (5) 切换用户日志记录或者切换命令更改(可选) log::info "[-] 切换用户日志记录和切换命令更改名称为SU " egrep -q "^(s*)SULOG_FILEs+S*(s*#.*)?s*$" /etc/login.defs && sed -ri "s/^(s*)SULOG_FILEs+S*(s*#.*)?s*$/SULOG_FILE /var/log/.history/sulog/" /etc/login.defs || echo "SULOG_FILE /var/log/.history/sulog" >> /etc/login.defs egrep -q "^s*SU_NAMEs+S*(s*#.*)?s*$" /etc/login.defs && sed -ri "s/^(s*)SU_NAMEs+S*(s*#.*)?s*$/SU_NAME SU/" /etc/login.defs || echo "SU_NAME SU" >> /etc/login.defs mkdir -vp /usr/local/bin /var/log/.backups /var/log/.history /var/log/.history/sulog cp /usr/bin/su /var/log/.backups/su.bak mv /usr/bin/su /usr/bin/SU # 只能写入不能删除其目标目录中的文件 # chmod -R 1777 /var/log/.history chattr -R +a /var/log/.history chattr +a /var/log/.backups # (6) 用户终端执行的历史命令记录 log::info "[-] 用户终端执行的历史命令记录 " egrep -q "^HISTSIZEWw+.*$" /etc/profile && sed -ri "s/^HISTSIZEWw+.*$/HISTSIZE=101/" /etc/profile || echo "HISTSIZE=101" >> /etc/profile # 方式1 sudo tee /etc/profile.d/history-record.sh <<'EOF' # 历史命令执行记录文件路径 LOGTIME=$(date +%Y%m%d-%H-%M-%S) export HISTFILE="/var/log/.history/${USER}.${LOGTIME}.history" if [ ! -f ${HISTFILE} ];then touch ${HISTFILE} fi chmod 600 /var/log/.history/${USER}.${LOGTIME}.history # 历史命令执行文件大小记录设置 HISTFILESIZE=128 HISTTIMEFORMAT="%F_%T $(whoami)#$(who -u am i 2>/dev/null| awk '{print $NF}'|sed -e 's/[()]//g'):" EOF # 方式2.未能成功(如后续有小伙伴成功了欢迎留言分享) # sudo tee /usr/local/bin/history.sh <<'EOF' # #!/bin/bash # logfiletime=$(date +%Y%m%d-%H-%M-%S) # # unalias "history" # if [ $# -eq 0 ];then history;fi # for i in $*;do # if [ "$i" = "-c" ];then # mv ~/.bash_history > /var/log/.history/${logfiletime}.history # history -c # continue; # fi # done # alias history="source /usr/local/bin/history.sh" # EOF # (7) GRUB 安全设置 (需要手动设置请按照需求设置) log::info "[-] 系统 GRUB 安全设置(防止物理接触从grub菜单中修改密码) " # Grub 关键文件备份 cp -a /etc/grub.d/00_header /var/log/.backups cp -a /etc/grub.d/10_linux /var/log/.backups # 设置Grub菜单界面显示时间 sed -i -e 's|GRUB_TIMEOUT_STYLE=hidden|#GRUB_TIMEOUT_STYLE=hidden|g' -e 's|GRUB_TIMEOUT=0|GRUB_TIMEOUT=3|g' /etc/default/grub sed -i -e 's|set timeout_style=${style}|#set timeout_style=${style}|g' -e 's|set timeout=${timeout}|set timeout=3|g' /etc/grub.d/00_header # 创建认证密码 (此处密码: WeiyiGeek) sudo grub-mkpasswd-pbkdf2 # Enter password: # Reenter password: # PBKDF2 hash of your password is grub.pbkdf2.sha512.10000.21AC9CEF61B96972BF6F918D2037EFBEB8280001045ED32DFDDCC260591CC6BC8957CF25A6755904A7053E97940A9E4CD5C1EF833C1651C1BCF09D899BED4C7C.9691521F5BB34CD8AEFCED85F4B830A86EC93B61A31885BCBE3FEE927D54EFDEE69FA8B51DBC00FCBDB618D4082BC22B2B6BA4161C7E6B990C4E5CFC9E9748D7 # 设置认证用户以及password_pbkdf2认证 tee -a /etc/grub.d/00_header <<'END' cat <<'EOF' # GRUB Authentication set superusers="grub" password_pbkdf2 grub grub.pbkdf2.sha512.10000.21AC9CEF61B96972BF6F918D2037EFBEB8280001045ED32DFDDCC260591CC6BC8957CF25A6755904A7053E97940A9E4CD5C1EF833C1651C1BCF09D899BED4C7C.9691521F5BB34CD8AEFCED85F4B830A86EC93B61A31885BCBE3FEE927D54EFDEE69FA8B51DBC00FCBDB618D4082BC22B2B6BA4161C7E6B990C4E5CFC9E9748D7 EOF END # 设置进入正式系统不需要认证如进入单用户模式进行重置账号密码时需要进行认证。 (高敏感数据库系统不建议下述操作) # 在191和193 分别加入--user=grub 和 --unrestricted # 191 echo "menuentry --user=grub '$(echo "$title" | grub_quote)' ${CLASS} $menuentry_id_option 'gnulinux-$version-$type-$boot_device_id' {" | sed "s/^/$submenu_indentation/" # 如果按e进行menu菜单则需要用grub进行认证 # 192 else # 193 echo "menuentry --unrestricted '$(echo "$os" | grub_quote)' ${CLASS} $menuentry_id_option 'gnulinux-simple-$boot_device_id' {" | sed "s/^/$submenu_indentation/" # 正常进入系统则不认证 sed -i '/echo "$title" | grub_quote/ { s/menuentry /menuentry --user=grub /;}' /etc/grub.d/10_linux sed -i '/echo "$os" | grub_quote/ { s/menuentry /menuentry --unrestricted /;}' /etc/grub.d/10_linux # Ubuntu 方式更新GRUB从而生成boot启动文件。 update-grub # (8) 操作系统防火墙启用以及策略设置 log::info "[-] 系统防火墙启用以及规则设置 " systemctl enable ufw.service && systemctl start ufw.service && ufw enable sudo ufw allow proto tcp to any port 20211 # 重启修改配置相关服务 systemctl restart sshd } ## 名称: os::Operation ## 用途: 操作系统安全运维设置 ## 参数: 无 os::Operation () { log::info "[-] 操作系统安全运维设置相关脚本" # (0) 禁用ctrl+alt+del组合键对系统重启 (必须要配置,我曾入过坑) log::info "[-] 禁用控制台ctrl+alt+del组合键重启" mv /usr/lib/systemd/system/ctrl-alt-del.target /var/log/.backups/ctrl-alt-del.target-$(date +%Y%m%d).bak # (1) 设置文件删除回收站别名 log::info "[-] 设置文件删除回收站别名(防止误删文件) " sudo tee /etc/profile.d/alias.sh <<'EOF' # User specific aliases and functions # 删除回收站 # find ~/.trash -delete # 删除空目录 # find ~/.trash -type d -delete alias rm="sh /usr/local/bin/remove.sh" EOF sudo tee /usr/local/bin/remove.sh <<'EOF' #!/bin/sh # 定义回收站文件夹目录.trash trash="/.trash" deltime=$(date +%Y%m%d-%H-%M-%S) TRASH_DIR="${HOME}${trash}/${deltime}" # 建立回收站目录当不存在的时候 if [ ! -e ${TRASH_DIR} ];then mkdir -p ${TRASH_DIR} fi for i in $*;do if [ "$i" = "-rf" ];then continue;fi # 防止误操作 if [ "$i" = "/" ];then echo '# Danger delete command, Not delete / directory!';exit -1;fi #定义秒时间戳 STAMP=$(date +%s) #得到文件名称(非文件夹),参考man basename fileName=$(basename $i) #将输入的参数,对应文件mv至.trash目录,文件后缀,为当前的时间戳 mv $i ${TRASH_DIR}/${fileName}.${STAMP} done EOF sudo chmod +775 /usr/local/bin/remove.sh /etc/profile.d/alias.sh /etc/profile.d/history-record.sh sudo chmod a+x /usr/local/bin/remove.sh /etc/profile.d/alias.sh /etc/profile.d/history-record.sh source /etc/profile.d/alias.sh /etc/profile.d/history-record.sh # (2) 解决普通定时任务无法后台定时执行 log::info "[-] 解决普通定时任务无法后台定时执行 " linenumber=`expr $(egrep -n "pam_unix.sos$" /etc/pam.d/common-session-noninteractive | cut -f 1 -d ":") - 2` sudo sed -ri "${linenumber}a session [success=1 default=ignore] pam_succeed_if.so service in cron quiet use_uid" /etc/pam.d/common-session-noninteractive # (3) 解决 ubuntu20.04 multipath add missing path 错误 # 添加以下内容,sda视本地环境做调整 tee -a /etc/multipath.conf <<'EOF' blacklist { devnode "^sda" } EOF # 重启multipath-tools服务 sudo service multipath-tools restart # (4) 禁用 Ubuntu 中的 cloud-init # 在 /etc/cloud 目录下创建 cloud-init.disabled 文件,注意重启后生效 sudo touch /etc/cloud/cloud-init.disabled } ## 名称: os::optimizationn ## 用途: 操作系统优化设置(内核参数) ## 参数: 无 os::optimizationn () { log::info "[-] 正在进行操作系统内核参数优化设置......." # (1) 系统内核参数的配置(/etc/sysctl.conf) log::info "[-] 系统内核参数的配置/etc/sysctl.conf" # /etc/sysctl.d/99-kubernetes-cri.conf egrep -q "^(#)?net.ipv4.ip_forward.*" /etc/sysctl.conf && sed -ri "s|^(#)?net.ipv4.ip_forward.*|net.ipv4.ip_forward = 1|g" /etc/sysctl.conf || echo "net.ipv4.ip_forward = 1" >> /etc/sysctl.conf # egrep -q "^(#)?net.bridge.bridge-nf-call-ip6tables.*" /etc/sysctl.conf && sed -ri "s|^(#)?net.bridge.bridge-nf-call-ip6tables.*|net.bridge.bridge-nf-call-ip6tables = 1|g" /etc/sysctl.conf || echo "net.bridge.bridge-nf-call-ip6tables = 1" >> /etc/sysctl.conf # egrep -q "^(#)?net.bridge.bridge-nf-call-iptables.*" /etc/sysctl.conf && sed -ri "s|^(#)?net.bridge.bridge-nf-call-iptables.*|net.bridge.bridge-nf-call-iptables = 1|g" /etc/sysctl.conf || echo "net.bridge.bridge-nf-call-iptables = 1" >> /etc/sysctl.conf egrep -q "^(#)?net.ipv6.conf.all.disable_ipv6.*" /etc/sysctl.conf && sed -ri "s|^(#)?net.ipv6.conf.all.disable_ipv6.*|net.ipv6.conf.all.disable_ipv6 = 1|g" /etc/sysctl.conf || echo "net.ipv6.conf.all.disable_ipv6 = 1" >> /etc/sysctl.conf egrep -q "^(#)?net.ipv6.conf.default.disable_ipv6.*" /etc/sysctl.conf && sed -ri "s|^(#)?net.ipv6.conf.default.disable_ipv6.*|net.ipv6.conf.default.disable_ipv6 = 1|g" /etc/sysctl.conf || echo "net.ipv6.conf.default.disable_ipv6 = 1" >> /etc/sysctl.conf egrep -q "^(#)?net.ipv6.conf.lo.disable_ipv6.*" /etc/sysctl.conf && sed -ri "s|^(#)?net.ipv6.conf.lo.disable_ipv6.*|net.ipv6.conf.lo.disable_ipv6 = 1|g" /etc/sysctl.conf || echo "net.ipv6.conf.lo.disable_ipv6 = 1" >> /etc/sysctl.conf egrep -q "^(#)?net.ipv6.conf.all.forwarding.*" /etc/sysctl.conf && sed -ri "s|^(#)?net.ipv6.conf.all.forwarding.*|net.ipv6.conf.all.forwarding = 1|g" /etc/sysctl.conf || echo "net.ipv6.conf.all.forwarding = 1" >> /etc/sysctl.conf egrep -q "^(#)?vm.max_map_count.*" /etc/sysctl.conf && sed -ri "s|^(#)?vm.max_map_count.*|vm.max_map_count = 262144|g" /etc/sysctl.conf || echo "vm.max_map_count = 262144" >> /etc/sysctl.conf tee -a /etc/sysctl.conf <<'EOF' # 调整提升服务器负载能力之外,还能够防御小流量的Dos、CC和SYN攻击 net.ipv4.tcp_syncookies = 1 net.ipv4.tcp_tw_reuse = 1 # net.ipv4.tcp_tw_recycle = 1 net.ipv4.tcp_fin_timeout = 60 net.ipv4.tcp_synack_retries = 1 net.ipv4.tcp_syn_retries = 1 net.ipv4.tcp_fastopen = 3 # 优化TCP的可使用端口范围及提升服务器并发能力(注意一般流量小的服务器上没必要设置如下参数) net.ipv4.tcp_keepalive_time = 1200 net.ipv4.tcp_max_syn_backlog = 8192 net.ipv4.tcp_max_tw_buckets = 5000 net.ipv4.ip_local_port_range = 1024 65535 # 优化核套接字TCP的缓存区 net.core.netdev_max_backlog = 8192 net.core.somaxconn = 8192 net.core.rmem_max = 12582912 net.core.rmem_default = 6291456 net.core.wmem_max = 12582912 net.core.wmem_default = 6291456 EOF # (2) Linux 系统的最大进程数和最大文件打开数限制 log::info "[-] Linux 系统的最大进程数和最大文件打开数限制" egrep -q "^s*ulimit -HSns+w+.*$" /etc/profile && sed -ri "s/^s*ulimit -HSns+w+.*$/ulimit -HSn 65535/" /etc/profile || echo "ulimit -HSn 65535" >> /etc/profile egrep -q "^s*ulimit -HSus+w+.*$" /etc/profile && sed -ri "s/^s*ulimit -HSus+w+.*$/ulimit -HSu 65535/" /etc/profile || echo "ulimit -HSu 65535" >> /etc/profile tee -a /etc/security/limits.conf <<'EOF' # ulimit -HSn 65535 # ulimit -HSu 65535 * soft nofile 65535 * hard nofile 65535 * soft nproc 65535 * hard nproc 65535 # End of file EOF # sed -i "/# End/i * soft nproc 65535" /etc/security/limits.conf # sed -i "/# End/i * hard nproc 65535" /etc/security/limits.conf sysctl -p # 需重启生效 reboot } ## 名称: system::swap ## 用途: Liunx 系统创建SWAP交换分区(默认2G) ## 参数: $1(几G) system::swap () { if [ -e $1 ];then sudo dd if=/dev/zero of=/swapfile bs=1024 count=2097152 # 2G Swap 分区 1024 * 1024 , centos 以 1000 为标准 else number=$(echo "${1}*1024*1024"|bc) sudo dd if=/dev/zero of=/swapfile bs=1024 count=${number} # 2G Swap 分区 1024 * 1024 , centos 以 1000 为标准 fi sudo mkswap /swapfile && sudo swapon /swapfile if [ $(grep -c "/swapfile" /etc/fstab) -eq 0 ];then sudo tee -a /etc/fstab <<'EOF' /swapfile swap swap default 0 0 EOF fi sudo swapon --show && sudo free -h } ## 名称: software::Java ## 用途: java 环境安装配置 ## 参数: 无 software::Java () { # 基础变量 JAVA_FILE="/root/Downloads/jdk-8u211-linux-x64.tar.gz" JAVA_SRC="/usr/local/" JAVA_DIR="/usr/local/jdk" # 环境配置 sudo tar -zxvf ${JAVA_FILE} -C ${JAVA_SRC} sudo rm -rf /usr/local/jdk JAVA_SRC=$(ls /usr/local/ | grep "jdk") sudo ln -s ${JAVA_SRC} ${JAVA_DIR} export PATH=${JAVA_DIR}/bin:${PATH} sudo cp /etc/profile /etc/profile.$(date +%Y%m%d-%H%M%S).bak sudo tee -a /etc/profile <<'EOF' export JAVA_HOME=/usr/local/jdk export JRE_HOME=/usr/local/jdk/jre export CLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar export PATH=$JAVA_HOME/bin:$PATH EOF java -version } ## 名称: software::docker ## 用途: 软件安装之Docker安装 ## 参数: 无 # 帮助: https://docs.docker.com/engine/install/ubuntu/ # Ubuntu Focal 20.04 (LTS) # Ubuntu Bionic 18.04 (LTS) # Ubuntu Xenial 16.04 (LTS) function InstallDocker(){ # 1.卸载旧版本 sudo apt-get remove docker docker-engine docker.io containerd runc # 2.更新apt包索引并安装包以允许apt在HTTPS上使用存储库 sudo apt-get install -y apt-transport-https ca-certificates curl gnupg-agent software-properties-common # 3.添加Docker官方GPG密钥 # -fsSL sudo curl https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add - # 4.通过搜索指纹的最后8个字符进行密钥验证 sudo apt-key fingerprint 0EBFCD88 # 5.设置稳定存储库 sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" # 6.Install Docker Engine 默认最新版本 sudo apt-get update && sudo apt-get install -y docker-ce=5:20.10.7~3-0~ubuntu-focal docker-ce-cli=5:20.10.7~3-0~ubuntu-focal containerd.io docker-compose # - 强制IPv4 # sudo apt-get -o Acquire::ForceIPv4=true install -y docker-ce=5:19.03.15~3-0~ubuntu-focal docker-ce-cli=5:19.03.15~3-0~ubuntu-focal containerd.io docker-compose # 7.安装特定版本的Docker引擎,请在repo中列出可用的版本 apt-cache madison docker-ce # docker-ce | 5:20.10.6~3-0~ubuntu-focal| https://download.docker.com/linux/ubuntu focal/stable amd64 Packages # docker-ce | 5:19.03.15~3-0~ubuntu-focal | https://download.docker.com/linux/ubuntu xenial/stable amd64 Packages # 使用第二列中的版本字符串安装特定的版本,例如:5:18.09.1~3-0~ubuntu-xenial。 # $sudo apt-get install docker-ce=<VERSION_STRING> docker-ce-cli=<VERSION_STRING> containerd.io #8.将当前用户加入docker用户组然后重新登陆当前用户使得低权限用户 sudo gpasswd -a ${USER} docker # sudo gpasswd -a weiyigeek docker #9.加速器建立 mkdir -vp /etc/docker/ sudo tee /etc/docker/daemon.json <<-'EOF' { "registry-mirrors": ["https://xlx9erfu.mirror.aliyuncs.com"], "exec-opts": ["native.cgroupdriver=systemd"], "storage-driver": "overlay2", "log-driver": "json-file", "log-level": "warn", "log-opts": { "max-size": "100m", "max-file": "10" }, "live-restore": true, "dns": ["192.168.10.254","223.6.6.6"] } EOF # "data-root":"/monitor/container", # "insecure-registries": ["harbor.weiyigeek.top"] # 9.自启与启动 sudo systemctl daemon-reload sudo systemctl enable docker sudo systemctl restart docker # 10.退出登陆生效 exit } ## 名称: disk::Lvsmanager ## 用途: uBuntu操作系统磁盘 LVS 逻辑卷添加与配置(扩容流程) ## 参数: 无 disk::Lvsmanager () { echo " 分区信息:" sudo df -Th sudo lsblk echo -e " 磁盘信息:" sudo fdisk -l echo -e " PV物理卷查看:" sudo pvscan echo -e " vgs虚拟卷查看:" sudo vgs echo -e " lvscan逻辑卷扫描:" sudo lvscan echo -e " 分区扩展" echo "Ubuntu lvextend -L +74G /dev/ubuntu-vg/ubuntu-lv" echo "lsblk" echo -e "ubuntu general # resize2fs -p -F /dev/mapper/ubuntu--vg-ubuntu--lv" } # 安全加固过程临时文件清理为基线镜像做准备 unalias rm find ~/.trash/* -delete find /home/ -type d -name .trash -exec find {} -delete ; find /var/log -name "*.gz" -delete find /var/log -name "*log.*" -delete find /var/log -name "vmware-*.*.log" -delete find /var/log -name "*.log-*" -delete find /var/log -name "*.log" -exec truncate -s 0 {} ; find /tmp/* -delete
至此 Ubuntu 安全加固脚本完毕。
原文地址: Linux与Windows服务器操作系统安全防御实践指南 ( https://blog.weiyigeek.top/2020/10-13-585.html )
0x04 补充说明
第一次投稿给安全客,心里还是有点小激动的,在投稿时让我想起曾经深夜挖洞的过往,不知不觉已过几年了,颇多的感慨,仰望众多大佬的脚步前行,勿忘初心、不骄不躁。
后续我将针对 数据库应用软件以及中间件方面的等保测评项进行搜寻整理,编写安全加固配脚本供大家使用,争取再搞一个系列。
文章中脚本如有错误,欢迎各位大佬指正。
加载全部内容