前言
每年下半年至年底都是各行业等保评测的时间段,在信息安/全等级保护二、三级认证中,其中操作系统安全要求中会要求不能有多余的系统账号,越多的账号会对系统带来较大的安全隐患。所以应当定时、定期的清理或者停用系统里的不活跃账号,但是当业务系统越来越多,服务器、虚拟机达到一定数量级的时候,一台一台登录查看已不现实,故在此分享几个Linux、Windows下查找账号的脚本。
一、查找系统所有账号
(1)Windows查找系统所有未锁定的账号:
##########Find all local users, filter kown users####################
#####之所以采用Get-WmiObject -Class Win32_UserAccount这种方式,而没用采用get-localusers,是因为get-localuser是PowerShell 5.0之后才开始支持的。考虑兼容性,WMI的方法更加适用。可以在where里面添加你想要过滤掉的用户名、指定域名下的用户等等,如果服务器加入了域,可能会搜索域下面可登录的所有用户名,效率会非常慢。WMI方式是没用lastlogin这个属性的。######
$detail1=Get-WmiObject -Class Win32_UserAccount | where { $_.Disabled -ne "False" -and $_.Name -ne "ops_admin_qyry" -and $_.Domain -ne "QYRY0" } | select PSComputerName,Status,Name,FullName,Disabled,Domain | fl
####如果你的.NET版本比较低,会提示没用IsNullOrWhiteSpace这个方法,你可以将下面IsNullOrWhiteSpace替换成IsNullOrEmpty####
if ( [String]::IsNullOrWhiteSpace($detail1) ){
echo "no user, over!~"
}else{
########这里用foreach方法将每个网卡的IP赋值给变量ip1,其中 -split ' : '是以冒号为分隔符,冒号后面的空格是必须的,否则取到的IP前面会带有空格###########
$local_IP=foreach($ipv4 in (ipconfig) -like '*IPv4*') { ($ipv4 -split ' : ')[-1]}
#######将获取到用户信息输出到C:\PS_FindUsers\$local_IP.txt文件,文件名是操作系统的IP####
if ( (Test-path C:\PS_FindUsers) -ne "True" ){
New-Item C:\PS_FindUsers -type Directory
echo "make dir~~~"
}
if ( (Test-path C:\PS_FindUsers\$local_IP.txt) -ne "True" ){
New-Item C:\PS_FindUsers\$local_IP.txt -type File
echo "make file~~~"
}
$detail1 | out-file -append C:\PS_FindUsers\$local_IP.txt
####下面Get-WmiObject -Class Win32_UserAccount重新获取用户信息,是只有Name属性,方便整理清单,不需要的话删除即可###
$simple1=Get-WmiObject -Class Win32_UserAccount | where { $_.Disabled -ne "False" -and $_.Name -ne "ops_admin_qyry" -and $_.Domain -ne "QYRY0" } | select Name | out-file -append C:\PS_FindUsers\$local_IP.txt
echo "PS COMMIT over!~~"
}
(2)查找Linux系统下所有可登录的账号
以下脚本执行环境为CentOS 7.x,其他发行版本不保证得到理想的结果。
##############find all lacol users#################
#!/bin/bash
name1=( `cat /etc/passwd | grep -v "nologin\|root\|shutdown\|halt\|sync\|gdm" | cut -d ":" -f 1` )
if [[ $name1 == "" ]]; then
echo "no user,over~"
else
####将找到的用户输出到/tmp/$ip1.txt文件,文件名和windows脚本一样是系统的IP。
ip1=`hostname -I|awk '{print $1}'`
echo "$name1" >> /tmp/$ip1.txt
echo "find over! look up /tmp/$ip1.txt ~"
fi
我们可以对其优化一下,让其可以直接复制到你的ssh连接工具下,自动写入文件、赋予执行权限、执行文件。
####需要注意的是,从标准输入获取内容并输出到文件时,有些命令会优先执行一遍,比如``里面的内,此时我们需要添加\转义符。####
cat << EOF > findlocaluser.sh
#!/bin/bash
####此处可以添加需要过滤掉的信息,比如root用户####
name1=( \`cat /etc/passwd | grep -v "nologin\|root\|shutdown\|halt\|sync\|gdm" | cut -d ":" -f 1\` )
if [[ \$name1 == "" ]]; then
echo "no user,over~"
else
ip1=`hostname -I|awk '{print $1}'`
echo "\$name1" >> /tmp/\$ip1.txt
echo "find over! look up /tmp/\$ip1.txt ~"
fi
EOF
chmod +x findlocaluser.sh
/bin/bash findlocaluser.sh
二、找出系统超过90天未登录的用户账户
(1)查找Windows下超过90天未登录系统账户
########这里用foreach方法将每个网卡的IP赋值给变量ip1,其中 -split ' : '是以冒号为分隔符,冒号后面的空格是必须的,否则取到的IP前面会带有空格###########
[string]$ip1=foreach($ipv4 in (ipconfig) -like '*IPv4*') { ($ipv4 -split ' : ')[-1]}
####自定义Get-LocalUsers函数
function Get-LocalUsers {
Param([string]$ComputerName=$env:COMPUTERNAME)
[ADSI]$computer="WinNT://$ComputerName"
$computer.PsBase.Children | Where-Object {$_.SchemaClassName -match "user"} |
Select-Object @{Name="ComputerName"; Expression={$computer.Name}},
@{Name="User"; Expression={$_.PsBase.Properties.Name.Value}},
@{Name="IP"; Expression={$ip1}},
@{Name="Description"; Expression={$_.PsBase.Properties.Description.Value}},
@{Name="Disabled"; Expression={[bool]($_.PsBase.Properties.Item("userflags").Value -band 2)}},
@{Name="LastLogin"; Expression={ if ($_.PsBase.Properties.LastLogin.Value) {
[datetime]$_.PsBase.Properties.LastLogin.Value
} else { "Never" }}}
}
#########set the date to compare against to midnight using '.Date'
####计算90天前的日期
$refDate = (Get-Date).AddDays(-90).Date
####将找到的账户输出到C:\1\$ip1.txt
Get-LocalUsers | Where-Object { $_.Disabled -ne 'False' -and $_.LastLogin -lt $refDate } | out-file C:\1\$ip1.txt
(2)查找linux下超过90天未登录的用户
#!/bin/bash
name1=( `cat /etc/passwd | grep -v "nologin\|root\|shutdown\|halt\|sync\|gdm\|ops_admin_qyry\|ops_user_snmp" | cut -d ":" -f 1` )
if [[ $name1 == "" ]]; then
echo "no user,over~"
else
count1=0
for (( i=0;i<${#name1[@]};i++)) do
name2=`lastlog -b 90 -u ${name1[i]}`
if [[ $name2 != "" ]]; then
echo "$name2" >> ip.txt
count1=$(($count1+1))
fi
done
if [ $count1 -eq 0 ]; then
echo "these users are active,over~"
else
echo "search $count1 users~"
ip1=`hostname -I|awk '{print $1}'`
echo "$ip1--$count1.txt"
`mv ip.txt $ip1--$count1.txt`
fi
fi
总结
上述脚本依然有需要可以优化的地方,但目前等保整改基本结束,所以也懒得修改优化了。
顺带吐槽一下,最近这个客户没有搞ansible、saltstack等自动化工具,且业务系统密码均是不会给到外部运维人员,登录方式为堡垒机配置好的账号自动登录。被逼一台一台系统操作进行等保要求的整改,不幸中的万幸是系统只有100-150台左右,如果在多些,估计能给我整吐血。