Dragon
  • 一个纯白的黑客网站,一直在努力,apt的路上,更精彩!
lsh4ckLsh4ck  2019-08-09 01:59 lsh4ck's Blog 隐藏边栏 |   抢沙发  740 
文章评分 1 次,平均分 5.0

当企业被攻击者入侵,系统被挂暗链、内容遭到恶意篡改,服务器出现异常链接、卡顿等情况时,需要进行紧急处理,使系统在最短时间内恢复正常。由于应急处理往往时间紧,所以尝试将应急中常见处理方法整合到脚本中,可自动化实现部分应急工作。应急脚本采用python2.0完成,由于所有需要执行的命令都是依靠ssh进行远程链接,所以在运行脚本之前,需要输入正确的主机ip地址、ssh远程连接端口、ssh远程登录账户、ssh远程登录密码。

一、脚本实现的主要功能

1、获取主机信息

获取的主机信息包括:主机ip地址、主机名、当前系统内核版本、当前系统版本、系统当前时间;

2、获取异常进程

获取异常进程主要是采用两种方式,第一种,通过执行netstat -antp获取当前主机存在哪些链接,并通过判断外部链接地址归属地,如果归属地不是中国,则会提取相关pid,并根据pid定位出文件所在位置。第二种,通过cpu占有率,一旦发现cpu占用率高于%15时,会提取对应程序的pid,根据pid定位异常文件位置。

3、判断常见命令是否被篡改

在之前的应急响应中出现过常见命令被非法篡改情况,如ps、netstat命令被恶意替换,利用stat查看文件详细信息,通过比对时间的方式判断命令是否被篡改。

4、查看系统启动项

很多恶意程序会修改系统启动项,这样即使系统进行重启时,恶意程序也能自动启动,查看init.d目录下的启动文件,根据修改时间提取最近被修改的启动文件,并根据时间排序列出前5个。

5、查看历史命令

查看.bash_history历史命令,通过匹配关键字,如wget、cur等,来查看系统在被入侵后是否被执行了恶意操作。

6、判断非系统默认账户

恶意程序可能会在系统中新建账户,通过查看login.defs文件获取最小uid,从而根据uid查看passwd文件,获取之后新建的系统用户。

7、获取当前登录用户

通过调用who,查看当前登录用户(tty为本地登录,pts为远程登录),判断是否存在异常用户登录情况。

8、查看系统当前用户

通过查看etc/passwd,查看相关用户信息,确定是否存在异常用户。

9、查看crontab定时任务

查看/etc/crontab定时任务,并将输出结果保存到log中

10、查看、保存最近三天系统文件修改情况

通过find命令,查找最近三天修改过的文件,由于修改的系统文件较多,所以修改文件被单独保存在本地file_edit文件中

11、查找特权用户。

查看passwd文件,查找用户id为0的特权用户

12、secure日志分析

日志分析是应急的重头工作,尤其是在应急后期的溯源阶段,日志分析更显得尤为重要,由于日志种类包括服务器日志、应用日志,此处只是分析了secure服务器日志,提取日志的ip地址进行判断,并对ip归属地进行判断,查看的secure日志单独保存在本地secure中。

脚本整体的思路比较简单,就是远程登录到linux执行常见的应急命令,脚本中的命令在centos下都是可正常运行的,可以在根据实际环境自行在对命令做调整。上面的部分功能如果有好的实现方法也可灵活调整,如判断常见命令是否被篡改,脚本中是根据时间进行判断,在实际应用中也可根据文件大小进行判断,代码整体写的比较渣,有意见欢迎大家多多指出,希望通过改进能让功能更加完善。

#!/usr/bin/env python
# -*- coding:utf-8 -*-
'''
#作者:tide_应急小组
# 版本:v1.0
应急自动化分析脚本,采用python2.0,主要是通过ssh远程登录实现常见命令查看,所以在使用之前需要输入正确的服务器ip、ssh连接端口、ssh登录用户名、ssh登录密码,
主要实现如下功能:
1、获取系统基本信息,ip地址,主机名称,版本;
2、根据netstat、cpu占用率,获取异常程序pid,并定位异常所在路径;
3、常见系统命令可能会被恶意文件替换修改,识别常见系统命令是否被修改;
4、查看系统启动项目,根据时间排序,列出最近修改的前5个启动项
5、查看历史命令,列出处存在可疑参数的命令;
6、查看非系统用户;
7、查看当前登录用户(tty 本地登陆  pts 远程登录);
8、通过查看passwd文件,确定系统当前用户
9、查看crontab定时任务
10、查看、保存最近三天系统文件修改情况
11、查看passwd,存在哪些用户id为0的特权用户
12、分析secure日志,判断其中是否存在异常ip地址
上述所有操作均输出保存在log文件中
'''
import requests
import paramiko
import re
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())  # 跳过了远程连接中选择‘是’的环节,
ssh.connect('192.168.157.139', 22, 'root', 'abc-123')
# 通过netstat、top确定异常程序pid,通过pid定位异常程序位置
class netstat_Analysis:
    def __init__(self):
        self.pid=' '
        # 获取网络链接,并查看是否存在异常
    def check_netstat(self):
        try:
            ip=set()
            command="netstat -antp  | grep 'ESTABLISHED \| SYN_SENT \|SYN_RECEIVED' | awk '{print $1,$5,$7}' "
            command1="netstat -antp"
            stdin, stdout, stderr = ssh.exec_command(command)
            info= stdout.read().splitlines()
            stdin, stdout1, stderr = ssh.exec_command(command1)
            info1 = stdout1.read()
            file2.write(info1)
            return info
        except  Exception, e:
            print str(e)
    # 判断ip地址归属地,看是否是异常连接
    def check_yichangip(self):
        yichang=list()
        remot_ip=set()
        result=self.check_netstat()
        try:
            for net in result:
                # print net
                ip = str(net).split(' ')[1].split(':')[0]
                pid = str(net).split(' ')[2].split('/')[0]
                application = str(net).split(' ')[2].split('/')[1]
                remot_ip.add(ip)
            for i in  remot_ip:
                URL = 'http://ip.taobao.com/service/getIpInfo.php?ip='+i
                try:
                    r = requests.get(URL, timeout=3)
                except requests.RequestException as e:
                    print (e)
                else:
                    json_data = r.json()
                    if  json_data[u'code'] == 0:
                        country= json_data[u'data'][u'country'].encode('utf-8')
                        # print country
                        keyword=['中国','局域网','共享地址','本机地址','本地链路','保留地址','XX']
                        if country not  in keyword:
                            wrong_ip=i
                            info= "异常链接ip:"+wrong_ip+',ip归属地:'+country
                            file.write(info)
                            # print info
                            command1="netstat -antp  | grep "+wrong_ip+" | awk '{print $1,$5,$7}' "
                            stdin, stdout1, stderr = ssh.exec_command(command1)
                            info1= stdout1.read().splitlines()
                            # print type(info1)
                            yichang=yichang+info1
                            return yichang
                        else:
                            file.write('\n'+"查看netstat未发现国外ip地址链接"+'\n')

                    else:
                        print '查询失败,请稍后再试!'
        except:
            print "暂时未发现异常链接"
 # 对异常pid进行检测,定位文件位置
    def jiance_pid(self):
        try:
            # pid=1
            command1 = "ls -l /proc/"+self.pid
            stdin, stdout, stderr = ssh.exec_command(command1)
            info = stdout.read().splitlines()
            mulu=str(info[9]).split(' ')[10:]
            kezhixingwenjian=str(info[11]).split(' ')[10:]
            yichangtixing= "pid 为"+self.pid+"的异常程序,存在位置为:"+mulu[0]+",可执行文件为"+kezhixingwenjian[0]+",请手工进行验证。"
            file.write(yichangtixing+'\n')
            print yichangtixing
        except:
            print "未发现异常行为"
    # 检测cpu高于15%的程序,并获取其pid,查看是否为异常进程
    def check_cpu(self):
        command_cpu = "ps -aux | sort -nr -k 3 | head -5 | awk '{if($3>=15) print $2,$3}'"
        stdin, stdout, stderr = ssh.exec_command(command_cpu)
        yichang_cpu = stdout.read().splitlines()
        try:
            for n in range(len(yichang_cpu)):
                self.pid=yichang_cpu[n].split(' ')[0]
                # print self.pid
                info= "pid 为"+self.pid+"的程序,cpu占用率为"+yichang_cpu[n].split(' ')[1]
                file.write(info+'\n')
                print info
                self.jiance_pid()
        except Exception, e:
            print str(e)
    # 通过netstat查看链接,获取异常pid的程序位置
    def ps_aux(self):
        a = self.check_yichangip()
        if a!=None:
            try:
                for i in a:
                    # print i
                    self.pid = str(i).split(' ')[2].split('/')[0]
                    self.jiance_pid()
            except Exception, e:
                print str(e)
        else:
            print "查看netstat未发现异常ip地址"

# 有些恶意程序会替换ps,netstat命令,此处用来判断系统命令是否被替换(此处判断bin目录下命令)
class check_mingling:
    def __init__(self):
        stdin, stdout, stderr = ssh.exec_command("stat /bin/mkdir")
        info = stdout.read().splitlines()
        if __name__ == '__main__':
            self.time=info[5].split(' ')[1].split('-')[0]
    def mingling(self):
        command=['ps','netstat']
        for i in range(len(command)):
            try:
                command1 = "stat  /bin/"+command[i]
                stdin, stdout, stderr = ssh.exec_command(command1)
                info1 = stdout.read().splitlines()
                time=info1[5].split(' ')[1].split('-')[0]
            except:
                print "所查询命令不在bin目录下"
            # print time,self.time
            # print int(self.time),int(time)
            try:
                if int(self.time)<int(time):
                    info1= command[i]+' 命令存在异常,修改时间为:'+info1[5].split(' ')[1]
                    file.write(info1+'\n')
                    print info1
                else:
                    print '未发现'+command[i]+'命令存在异常'
            except:
                print '暂无异常命令'
# 检查系统启动项目,查看init.d文件
class check_init():
    def get_init(self):
        try:
            command1 = "ls -lth /etc/rc.d/init.d | sed -n '2,6p'"
            stdin, stdout, stderr = ssh.exec_command(command1)
            info1 = stdout.read()
            tishi="根据最近修改时间,系统启动项前5名如下:"
            if len(info1) !=0:
                info=(tishi+'\n'+info1)
                file.write(info+'\n')
            else:
                print "查看默认启动项时,查看路径与实际不符合,请根据情况自行修改commad1中路径"
        except Exception, e:
            print str(e)
#历史命令查看
class check_history():
    def get_history(self):
        try:
            command1 = "cat /root/.bash_history | grep -a 'wget\|curl\|rpm\|install\|tar\|zip\|chmod\|rm\|mv'"
            stdin, stdout, stderr = ssh.exec_command(command1)
            info1 = stdout.read()
            print '通过查看历史命令发现以下可疑命令,需要进行手动确认'+'\n'+info1
            file.write('通过查看历史命令发现以下可疑命令,需要进行手动确认'+'\n'+info1)
        except Exception, e:
            print str(e)
# 获取主机信息
class Host_Info:
    def __init__(self):
        self.ip = ""
        # 主机名
        self.hostname = ""
        # 主机ip
        self.ip = ""
        # 主机内核版本
        self.version = ""
        #主机系统版本
        self.version1=""
        # 主机时间
        self.time = ""
    def get_ip(self):
        try:
            command1 = "ifconfig -a | grep -w inet | grep -v 127.0.0.1 | awk 'NR==1{print $2}'&&hostname&&uname -a &&date&&cat " \
                       "/etc/issue| awk 'NR==1' "
            stdin, stdout, stderr = ssh.exec_command(command1)
            info=stdout.read().splitlines()
            # print info
            self.ip=info[0]
            self.hostname=info[1]
            self.version=info[2]
            self.time=info[3]
            self.version1=info[4]
            info_write='当前系统IP地址为:'+self.ip+'\n'+'当前系统主机名称为:'+self.hostname+'\n'+'当前系统内核版本为:'+self.version+'\n'+"当前系统版本:"+self.version1+'\n'+'当前系统时间为:'+self.time+'\n'
            file.write(info_write)
            print info_write
        except Exception, e:
            print str(e)
# 获取当前用户情况
class check_user:
    def __init__(self):
        self.user=""
        self.nosystemuser=""
        self.current_yonghu=""
    def get_user(self):
        command1 = ["uid=$(grep UID_MIN /etc/login.defs | awk '{print $2}') &&gawk -F: '{if ($3>='$uid' && $3!=65534) {print            $1}}' /etc/passwd","who","cat /etc/passwd"]
        try:
            stdin, stdout, stderr = ssh.exec_command(command1[0])
            if len(self.nosystemuser) ==0:
                self.nosystemuser='无'
            else:
                self.nosystemuser = stdout.read()
        except:
            print "查看非系统用户时出错"
        try:
            stdin, stdout, stderr = ssh.exec_command(command1[1])
            self.current_yonghu=stdout.read()
        except:
            print "查看当前登录用户出错"
        try:
            stdin, stdout, stderr = ssh.exec_command(command1[2])
            self.user=stdout.read()
        except:
            print "查看用户信息出错"
        # print self.user
        text='\n'+'存在以下非系统用户:'+'\n'+self.nosystemuser+'\n'+"当前登录用户如下:"+'\n'+self.current_yonghu+'\n'+'系统当前用户信''息如下:'+'\n'+self.user
        print text
        file.write(text)
class find_filerevise():
    def get_filerevise(self):
        try:
            command2 = "find ./ -mtime 0 -o -mtime 1 -o -mtime 2  -o -mtime 3"
            stdin, stdout, stderr = ssh.exec_command(command2)
            info2 = stdout.read()
            file1.write('近三天修改文件如下:'+'\n'+info2)
        except Exception, e:
            print str(e)
 #查看、保存当前定时任务
class find_crontab():
    def get_crontab(self):
        try:
            command3 = "cat /etc/crontab"
            stdin, stdout, stderr = ssh.exec_command(command3)
            info3 = str(stdout.read()).strip()
            print 'crontab当前定时任务如下:'+'\n'+info3
            file.write('crontab当前定时任务如下:'+'\n'+info3)
        except Exception, e:
            print str(e)
 #排查提权账户
class find_gid():
    def get_gid(self):
        user_list=set()
        try:
            command4 = "cat /etc/passwd"
            stdin, stdout, stderr = ssh.exec_command(command4)
            info3 = stdout.read().splitlines()
            # print(info3)

            for i in info3:
                # print(i)
                gid = str(i).split(':')[3]
                # print(type(gid))
                if gid == str(0):
                    user = str(i).split(':')[0]
                    user_list.add(user)
            if len(user_list) !=0:
                print 'gid为0账户如下:'+str(user_list)
                file.write('\n' + 'gid为0账户如下:')
                for i in user_list:
                    file.write('\n' +i)
            else:
                print "不存在uid为0的特权用户"
        except Exception, e:
            print str(e)
#查看日志文件,判断secure日志是否存在异常,由于日志查看的内容比较多,此处只是对secure日志中ip地址进行分析,判断是否存在国外异常ip归属
class check_log():
    try:
        def cat_log(self):
            command="cat /var/log/secure"
            stdin, stdout, stderr = ssh.exec_command(command)
            info3 = stdout.read()
            if len(info3)!=0:
                file4.write(info3)
                file4.close()
                ip_list=set()
                for i in open("secure.txt",'r').readlines():
                    ip = re.findall(r'(?<![\.\d])(?:\d{1,3}\.){3}\d{1,3}(?![\.\d])', str(i), re.S)
                    if len(ip) !=0:
                        ip_list.add(ip[0])
                    else:
                        pass
                for i in  ip_list:
                    URL = 'http://ip.taobao.com/service/getIpInfo.php?ip=' + i
                    try:
                        r = requests.get(URL, timeout=3)
                    except requests.RequestException as e:
                        file.write('在secure日志中未发现异常ip地址' + '\n')
                        print(e)
                    else:
                        json_data = r.json()
                        if json_data[u'code'] == 0:
                            country = json_data[u'data'][u'country'].encode('utf-8')
                            keyword = ['中国', '共享地址','局域网', '本机地址', '本地链路', '保留地址','XX']
                            if country not in keyword:
                                print '在secure日志中发现如下异常ip地址:'+'\n'+i+"  地址归属地"+country+'\n'
                                file.write('在secure日志中发现如下异常ip地址:'+'\n'+i+"  地址归属地"+country+'\n')
                            else:
                                pass
            else:
                print "系统未发现存在secure日志,请根据实际情况修改所需要查看的日志路径"
    except:
        print "系统未发现存在secure日志"
if __name__=='__main__':
    '''
    输出结果默认保存在log.txt中,查看最近3天文件的修改情况默认保存在file_edit.txt中,
    通过netstat查看链接情况默认保存在netstat.txt中,secure日志的查看情况保存在secure.txt中
    '''
    file = open("log.txt", 'a')
    file1=open("file_edit.txt",'w')
    file2=open("netstat.txt",'w')
    file4 = open("secure.txt", 'w')
    e = Host_Info()
    e.get_ip()
    a=netstat_Analysis()
    a.ps_aux()
    a.check_cpu()
    b=check_mingling()
    b.mingling()
    c=check_init()
    c.get_init()
    d=check_history()
    d.get_history()
    f=check_user()
    f.get_user()
    g = find_filerevise()
    g.get_filerevise()
    h = find_crontab()
    h.get_crontab()
    i = find_gid()
    i.get_gid()
    j=check_log()
    j.cat_log()

 



本文为原创文章,版权归所有,欢迎分享本文,转载请保留出处!

lsh4ck
Lsh4ck 关注:0    粉丝:8 最后编辑于:2019-09-08
这个人很懒,什么都没写
×

予人玫瑰,手有余香

打赏 Lsh4ck

打开支付宝扫一扫,即可进行扫码打赏哦

发表评论

表情 格式 链接 私密 签到

扫一扫二维码分享

无觅相关文章插件,快速提升流量