审计系统 (知识点)
一. 简单开发:
yum install epel-release -y yum install strace chmod u+s `which strace` yum install git git clone https://github.com/317828332/LuffyAudit.git git branch -a git branch fangshaowei python3 manage.py makemigrations python3 manage.py migrate python3 manage.py createsuperuser python3 manage.py runserver 0.0.0.0:8000 数据库加数据 #openssh wget https://mirror.leaseweb.com/pub/OpenBSD/OpenSSH/portable/openssh-7.5p1.tar.gz tar -zxvf openssh-7.5p1.tar.gz cd openssh-7.5p1 修改源码 611 while ((opt = getopt(ac, av, "1246ab:c:e:fgi:kl:m:no:p:qstvxz:" "ACD:E:F:GI:J:KL:MNO:PQ:R:S:TVw:W:XYyZ:")) != -1) { 934 case 'Z': fprintf(stdout,"session_tag: %s\n" ,optarg); break; ./configure --prefix=/usr/local/openssh/ make make install #sshpass tar -zxvf sshpass-1.06.tar.gz cd sshpass-1.06 ./configure make make install 317828332qq.com
二. paramiko收集日志(vim table 等需要优化):
#把项目放在/usr/local/ #如果是普通用户安装的pip3 安装的各种包需要移动到 /usr/local/python3/lib/python3.6/site-packages目录下 >>> sys.path /usr/local/python3/lib/python3.6/site-packages #登陆堡垒机默认显示和执行脚本 vim ~/.bashrc echo "-------welcome to oyoui system------" python3 /usr/local/LuffyAudit/audit_shell.py echo "-------bye..."
from django.contrib import admin from audit import models # Register your models here. class AuditLogAdmin(admin.ModelAdmin): list_display = ['session','cmd','date'] list_filter = ['date','session'] class SessionLogAdmin(admin.ModelAdmin): list_display = ['id','account','host_user_bind','start_date','end_date'] list_filter = ['start_date','account'] admin.site.register(models.Host) admin.site.register(models.HostUser) admin.site.register(models.HostGroup) admin.site.register(models.HostUserBind) admin.site.register(models.Account) admin.site.register(models.IDC) admin.site.register(models.AuditLog,AuditLogAdmin) admin.site.register(models.SessionLog,SessionLogAdmin)
#!/bin/bash #for loop 30.get process id by random tag #if got the process id , start strace command path=$0 echo $0 path_start=${path%audit/*} path_end=log/ssh_audit_$2.log for i in $(seq 1 30);do #echo $i $1 process_id=`ps -ef |grep $1 |grep -v sshpass |grep -v grep | grep -v 'session_tracker.sh' |awk '{print $2}'` # run cmd and set the result to variable cmd #echo "process: $process_id" if [ ! -z "$process_id" ];then echo 'start run strace....' #strace -fp $process_id -t -o $path_objlog/ssh_audit_$2.log; strace -fp $process_id -t -o $path_start$path_end; break; fi sleep 1 done;
#!/usr/bin/env python # Copyright (C) 2003-2007 Robey Pointer <robeypointer@gmail.com> # # This file is part of paramiko. # # Paramiko is free software; you can redistribute it and/or modify it under the # terms of the GNU Lesser General Public License as published by the Free # Software Foundation; either version 2.1 of the License, or (at your option) # any later version. # # Paramiko is distributed in the hope that it will be useful, but WITHOUT ANY # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR # A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more # details. # # You should have received a copy of the GNU Lesser General Public License # along with Paramiko; if not, write to the Free Software Foundation, Inc., # 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. import base64 from binascii import hexlify import getpass import os import select import socket import sys import time import traceback from paramiko.py3compat import input from audit import models import paramiko try: import interactive except ImportError: from . import interactive def manual_auth(t, username, password): t.auth_password(username, password) def ssh_session(bind_host_user, user_obj): # now connect hostname = bind_host_user.host.ip_addr port = bind_host_user.host.port username = bind_host_user.host_user.username password = bind_host_user.host_user.password try: sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.connect((hostname, port)) except Exception as e: print('*** Connect failed: ' + str(e)) traceback.print_exc() sys.exit(1) try: t = paramiko.Transport(sock) try: t.start_client() except paramiko.SSHException: print('*** SSH negotiation failed.') sys.exit(1) try: keys = paramiko.util.load_host_keys(os.path.expanduser('~/.ssh/known_hosts')) except IOError: try: keys = paramiko.util.load_host_keys(os.path.expanduser('~/ssh/known_hosts')) except IOError: print('*** Unable to open host keys file') keys = {} # check server's host key -- this is important. key = t.get_remote_server_key() if hostname not in keys: print('*** WARNING: Unknown host key!') elif key.get_name() not in keys[hostname]: print('*** WARNING: Unknown host key!') elif keys[hostname][key.get_name()] != key: print('*** WARNING: Host key has changed!!!') sys.exit(1) else: print('*** Host key OK.') if not t.is_authenticated(): manual_auth(t, username, password) if not t.is_authenticated(): print('*** Authentication failed. :(') t.close() sys.exit(1) chan = t.open_session() chan.get_pty() # terminal chan.invoke_shell() print('*** Here we go!\n') session_obj = models.SessionLog.objects.create(account=user_obj.account, host_user_bind=bind_host_user) interactive.interactive_shell(chan, session_obj) chan.close() t.close() except Exception as e: print('*** Caught exception: ' + str(e.__class__) + ': ' + str(e)) traceback.print_exc() try: t.close() except: pass sys.exit(1)
__author__ = 'Administrator' import subprocess,random,string from django.contrib.auth import authenticate from django.conf import settings from audit import models from audit.backend import ssh_interactive class UserShell(object): """用户登录堡垒机后的shell""" def __init__(self,sys_argv): self.sys_argv = sys_argv self.user = None def auth(self): count = 0 while count < 3: username = input("username:").strip() password = input("password:").strip() user = authenticate(username=username,password=password) #None 代表认证不成功 #user object ,认证对象 ,user.name if not user: count += 1 print("Invalid username or password!") else: self.user = user return True else: print("too many attempts.") def start(self): """启动交互程序""" if self.auth(): #print(self.user.account.host_user_binds.all()) #select_related() while True: host_groups = self.user.account.host_groups.all() for index,group in enumerate(host_groups): print("%s.\t%s[%s]"%(index,group,group.host_user_binds.count())) print("%s.\t未分组机器[%s]"%(len(host_groups),self.user.account.host_user_binds.count())) try: choice = input("select group>:").strip() if choice.isdigit(): choice = int(choice) host_bind_list = None if choice >=0 and choice < len(host_groups): selected_group = host_groups[choice] host_bind_list = selected_group.host_user_binds.all() elif choice == len(host_groups): #选择的未分组机器 #selected_group = self.user.account.host_user_binds.all() host_bind_list = self.user.account.host_user_binds.all() if host_bind_list: while True: for index,host in enumerate(host_bind_list): print("%s.\t%s"%(index,host,)) choice2 = input("select host>:").strip() if choice2.isdigit(): choice2 = int(choice2) if choice2 >=0 and choice2 < len(host_bind_list): selected_host = host_bind_list[choice2] ssh_interactive.ssh_session(selected_host,self.user) elif choice2 == 'b': break except KeyboardInterrupt as e: pass
# Copyright (C) 2003-2007 Robey Pointer <robeypointer@gmail.com> # # This file is part of paramiko. # # Paramiko is free software; you can redistribute it and/or modify it under the # terms of the GNU Lesser General Public License as published by the Free # Software Foundation; either version 2.1 of the License, or (at your option) # any later version. # # Paramiko is distributed in the hope that it will be useful, but WITHOUT ANY # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR # A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more # details. # # You should have received a copy of the GNU Lesser General Public License # along with Paramiko; if not, write to the Free Software Foundation, Inc., # 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. import socket import sys from paramiko.py3compat import u from audit import models # windows does not have termios... try: import termios import tty has_termios = True except ImportError: has_termios = False def interactive_shell(chan,session_obj): if has_termios: # posix_shell(chan,session_obj) #unix 通用协议标准 else: windows_shell(chan) def posix_shell(chan,session_obj): import select oldtty = termios.tcgetattr(sys.stdin) try: tty.setraw(sys.stdin.fileno()) tty.setcbreak(sys.stdin.fileno()) chan.settimeout(0.0) cmd = '' while True: r, w, e = select.select([chan, sys.stdin], [], []) if chan in r:#远程 由返回 命令结果 try: x = u(chan.recv(1024)) if len(x) == 0: sys.stdout.write('\r\n*** EOF\r\n') break sys.stdout.write(x) sys.stdout.flush() except socket.timeout: pass if sys.stdin in r: x = sys.stdin.read(1) if len(x) == 0: break if x == '\r': models.AuditLog.objects.create(session=session_obj,cmd=cmd) cmd = '' else: cmd += x chan.send(x) finally: termios.tcsetattr(sys.stdin, termios.TCSADRAIN, oldtty) # thanks to Mike Looijmans for this code def windows_shell(chan): import threading sys.stdout.write("Line-buffered terminal emulation. Press F6 or ^Z to send EOF.\r\n\r\n") def writeall(sock): while True: data = sock.recv(256) if not data: sys.stdout.write('\r\n*** EOF ***\r\n\r\n') sys.stdout.flush() break sys.stdout.write(data) sys.stdout.flush() writer = threading.Thread(target=writeall, args=(chan,)) writer.start() try: while True: d = sys.stdin.read(1) if not d: break chan.send(d) except EOFError: # user hit ^Z or F6 pass