注:linux上很少出现远程溢出漏洞,攻进linux一般拷爆破或通过控制Windows监视Linux行为进入(键盘记录器)
##运维流程-SSH
* 密钥登录
#禁止密码登录并配置公私钥登录
#编辑sshd_config文件 vi /etc/ssh/sshd_config #禁用密码验证 PasswordAuthentication no #启用密钥验证 RSAAuthentication yes PubkeyAuthentication yes #指定公钥数据库文件 AuthorsizedKeysFile .ssh/authorized_keys#或者直接输入下面的命令
sed -i "s/^PasswordAuthentication.*/PasswordAuthentication no/g" /etc/ssh/sshd_config sed -i "s/^#RSAAuthentication.*/RSAAuthentication yes/g" /etc/ssh/sshd_config sed -i "s/^#PubkeyAuthentication.*/PubkeyAuthentication yes/g" /etc/ssh/sshd_config sed -i "s/^#AuthorizedKeysFile.*/AuthorizedKeysFile .ssh\/authorized_keys/g" /etc/ssh/sshd_config
#配置SSHD公钥登陆
https://blog.csdn.net/mchdba/article/details/52193812
#重启SSH服务前建议多保留一个会话以防不测
#RHEL/CentOS系统 service sshd restart #ubuntu系统 service ssh restart #debian系统 /etc/init.d/ssh restart
* ssh弱密码爆破
nmap 扫描 22
hydra -user -p
crunch 字典生成工具
https://blog.csdn.net/qq_33936481/article/details/51277679
##web源码备份
远程获取文件
scp -r Web1:/var/www/html/ webbak/
备份最好基于时间备份,每隔一个小时备份一次,最好保留原始备份。
#!/bin/bash time=`/bin/date +%F` bak_file="/data/backup/$time.tar.gz" webdir="/data/www/" tar zcvf $bak_file $webdir >/dev/null 2>&1 &
计划任务 crontable -e
30 * * * * /bin/bash /data/bak.sh #添加定时执行任务ctl+o #保存 ctl+x #退出
##数据库备份
mysqldump -uroot -p --single-transaction --all-databases > backup.sql # 所有 mysqldump -u root -p --single-transaction dataname > dataname.sql #单个 mysqldump --skip-lock-tables -uxxxx -pxxxxxx -h 166.111.9.173 -R 数据库名 > ./urlevent20180319.sql mysqldump -h127.0.0.1 -uroot -ppassword database |gzip >$backupDir/$database-$today.sql.gz`然后,scp回来。
shell脚本原理:
#备份目录 backupDir=/home/backup/database #mysqlDump mysqldump=/usr/local/mariadb/bin/mysqldump host=127.0.0.1 username=root password=42342342 today=`date +%Y%m%d` #要备份的数据库数组 databases=(blog chinese_medicine) # echo $databaseCount for database in ${databases[@]} do echo '开始备份'$database $mysqldump -h$host -u$username -p$password $database | gzip > $backupDir/$database-$today.sql.gz echo '成功备份'$database'到'$backupDir/$database-$today.sql.gz done
恢复mysql mysql -uroot -p TEST < bak.sql
##数据库运维
取消远程登录(不需要远程管理)
取消mysql密码认证: 修改my.cnf ,添加 skip-grant-tables 修改mysql密码 update mysql.user set password=PASSWORD('skyboy') where user='root' and host='localhost'; flush privileges; 最好先修改mysql,再修改php。一般不存在需要修改mysql密码的情况。 禁止数据库的远程连接: use mysql; update user set host='localhost' where user='root'; flush privileges;
数据库降权
CREATE USER ‘dog’@‘localhost’ IDENTIFIED BY ‘123456’; GRANT ALL ON databasename.* TO ‘dog’@‘localhost flush privileges; 调整站点配置文件,修改数据库连接的用户名和密码。通过本机或ssh登录。
##权限配置--Linux的精髓
对于非必须可写的目录:
权限设置为755,拥有者设为非www-data用户;从而防止文件被篡改/删除。
对于必须可写的目录:
根据服务器类型,上一个.htaccess, 或者修改nginx的目录配置文件,去除此路径的脚本执行权限。
对于apache:
<FileMatch ".(pjp|php3|php4|php5)|phtml)"> Order Allow.Deny Deny from all <FilesMaych> #禁止恶意脚本的上传
对于Nginx:修改配置文件
location ~ /mm/(data|uploads|templets)/*.(php)$ { deny all; } location ~ .php$ { try_files $uri /404.html; fastcgi_pass 127.0.0.1:9000; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; include fastcgi_params; } 修改完成之后,nginx -S reload
##防御脚本
* waf脚本 WAF需要同时具备拦截和抓取流量的作用。
php-WAF的批量添加:
find /var/www/html -type f -path "*.php" | xargs sed -i "s/<?php/<?php require_once('/tmp/waf.php');n/g“port-forwarding.py
import socket import threading import sys def handle(buffer): return buffer def transfer(src, dst, direction): src_name = src.getsockname() src_address = src_name[0] src_port = src_name[1] dst_name = dst.getsockname() dst_address = dst_name[0] dst_port = dst_name[1] while True: buffer = src.recv(0x400) if len(buffer) == 0: print "[-] No data received! Breaking..." break # print "[+] %s:%d => %s:%d [%s]" % (src_address, src_port, dst_address, dst_port, repr(buffer)) if direction: print "[+] %s:%d >>> %s:%d [%d]" % (src_address, src_port, dst_address, dst_port, len(buffer)) else: print "[+] %s:%d <<< %s:%d [%d]" % (dst_address, dst_port, src_address, src_port, len(buffer)) dst.send(handle(buffer)) print "[+] Closing connecions! [%s:%d]" % (src_address, src_port) src.shutdown(socket.SHUT_RDWR) src.close() print "[+] Closing connecions! [%s:%d]" % (dst_address, dst_port) dst.shutdown(socket.SHUT_RDWR) dst.close() def server(local_host, local_port, remote_host, remote_port, max_connection): server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) server_socket.bind((local_host, local_port)) server_socket.listen(max_connection) print '[+] Server started [%s:%d]' % (local_host, local_port) print '[+] Connect to [%s:%d] to get the content of [%s:%d]' % (local_host, local_port, remote_host, remote_port) while True: local_socket, local_address = server_socket.accept() print '[+] Detect connection from [%s:%s]' % (local_address[0], local_address[1]) print "[+] Trying to connect the REMOTE server [%s:%d]" % (remote_host, remote_port) remote_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) remote_socket.connect((remote_host, remote_port)) print "[+] Tunnel connected! Tranfering data..." # threads = [] s = threading.Thread(target=transfer, args=( remote_socket, local_socket, False)) r = threading.Thread(target=transfer, args=( local_socket, remote_socket, True)) # threads.append(s) # threads.append(r) s.start() r.start() print "[+] Releasing resources..." remote_socket.shutdown(socket.SHUT_RDWR) remote_socket.close() local_socket.shutdown(socket.SHUT_RDWR) local_socket.close() print "[+] Closing server..." server_socket.shutdown(socket.SHUT_RDWR) server_socket.close() print "[+] Server shuted down!" def main(): if len(sys.argv) != 5: print "Usage : " print "\tpython %s [L_HOST] [L_PORT] [R_HOST] [R_PORT]" % (sys.argv[0]) print "Example : " print "\tpython %s 127.0.0.1 8888 127.0.0.1 22" % (sys.argv[0]) exit(1) LOCAL_HOST = sys.argv[1] LOCAL_PORT = int(sys.argv[2]) REMOTE_HOST = sys.argv[3] REMOTE_PORT = int(sys.argv[4]) MAX_CONNECTION = 0x10 server(LOCAL_HOST, LOCAL_PORT, REMOTE_HOST, REMOTE_PORT, MAX_CONNECTION) if __name__ == "__main__": main()
* 监控脚本
#!/usr/bin/env python # encoding:utf-8 import sys import pyinotify import os import time def detect_waf(pathname): try: with open(pathname) as f: content = f.read() black_list = ["<?", "<%"] black_list += ['eval', 'assert'] black_list += ['passthru', 'exec', 'system', 'shell_exec', 'popen', 'proc_open'] black_list += ['hightlight_file', 'show_source', 'php_strip_whitespace', 'file_get_contents', 'readfile', 'file', 'fopen', 'fread', 'include', 'include_once', 'require', 'require_once', 'fread', 'fgets', 'fpassthru', 'fgetcsv', 'fgetss', 'fscanf', 'parse_ini_file'] black_list += ['glob', 'opendir', 'dir', 'readdir', 'scandir'] FLAG = False for black in black_list: if black in content: print "[!] Dangerous php script! (%s)" % (black) print "[*] Content : " print content.rstrip("\n") FLAG = True break if FLAG: target_path = "webshells/%s.log" % (time.strftime('%Y-%m-%d-%H:%M:%S',time.localtime(time.time()))) print "[+] Detect webshell , moving from %s to %s" % (pathname, target_path) os.rename(pathname, target_path) except Exception as e: print "[-] %s" % (str(e)) class EventHandler(pyinotify.ProcessEvent): def process_IN_CREATE(self, event): if event.dir: print "Create Directory : %s" % (event.pathname) else: print "Create File : %s" % (event.pathname) def process_IN_DELETE(self, event): if event.dir: print "Delete Directory : %s" % (event.pathname) else: print "Delete File : %s" % (event.pathname) def process_IN_CLOSE_WRITE(self, event): if event.dir: print "Close Writable Directory : %s" % (event.pathname) else: print "Close Writable File : %s" % (event.pathname) detect_waf(event.pathname) def main(): if len(sys.argv) != 2: print "Usage : " print "\tpython %s [PATH]" % (sys.argv[0]) exit(1) path = sys.argv[1] wm = pyinotify.WatchManager() wm.add_watch(path, pyinotify.ALL_EVENTS, rec=True) eh = EventHandler() notifier = pyinotify.Notifier(wm, eh) notifier.loop() if __name__ == "__main__": main()
* 一句话木马 用以后期运维 具有web的权限以便于web操作(运维人员的权限往往不是web权限)
<?php $serverList = array( "127.0.0.1", "::1" ); $ip = $_SERVER['REMOTE_ADDR']; foreach ($serverList as $host){ if( $ip===$host){ $a = $_POST['n985de9']; if(isset($a)) { eval(base64_decode($a)); } }else{ die(); } }
## 查看网络拓扑 查看别人的防御机制 通过跳板机接入内网
masscan(一般用这个就好): masscan -p 80 172.16.0.0/24 masscan -p0-65535 172.16.0.0/24 -oJ result.json Nmap: nmap -sn -T4 ip/24 nmap -Pn ip/24
##木马查杀
运维选手需要随时:
* 关注服务的可用性状况* 查看文件监控情况
* 在被攻击的时候进行响应,保存相应的流量,查找/清除后门;
查看木马流程:
需要用www-data 权限进行查询 (web权限,如apache;具体可以通过上面一句话木马实现)crontab -l #查看计划任务
ps aux|grep www-data #查看以www-data权限运行的可疑流程
清除计划任务:
crontab -r
crontab -r -u USERNAME
杀死内存马:
ps aux|grep www-data|awk '{print $2}'|xargs kill -9
杀死文件马: 通过文件监控脚本或流量监视定位木马
需要以www-data权限
rm -rf
webshell实在不好删的话(三种挂马方式如果是环链的激活关系),直接恢复备份。