• 线下AWD平台搭建以及一些相关问题解决


    线下AWD平台搭建以及一些相关问题解决

     

     

    一.前言

      文章首发于tools,因为发现了一些新问题但是没法改,所以在博客进行补充。

      因为很多人可能没有机会参加线下的AWD比赛,导致缺乏这方面经验,比如我参加过五次线下AWD攻防,虽然看过许多网上的AWD打发套路,但终究都是纸上谈兵,所以前几次都是被吊锤,一来不熟悉环境,二来有点手忙脚乱,其实根本原因就是缺乏经验,因此最近翻了翻Github,终于找到一个不错的项目,下面便是搭建过程和一些注意事项。

    二、平台搭建过程:

    准备工作:需要准备一台Ubuntu虚拟机,我的版本是16.04,过程比较详细,如果会这些的大佬挑重点看就行。
    1.更新apt包索引
         $ sudo apt-get update
    2.安装git
         $ sudo apt install git
    3.安装docker
         $ sudo apt-get install -y apt-transport-https ca-certificates curl software-properties-common
         $ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
         $ sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu$(lsb_release -cs) stable"
         //查看可用的docker
         $ sudo apt-cache madison docker-ce
          [attach]79574[/attach]
         //选择要安装的特定版本
         $ sudo apt-get install docker-ce=<VERSION>
         //比如我要安装 18.06.3~ce~3-0~ubuntu,命令如下
         $ sudo apt-get install docker-ce=18.06.3~ce~3-0~ubuntu
    4.克隆项目
         $ sudo git clone https://github.com/zhl2008/awd-platform.git
    5.进入项目
         $ sudo cd awd-platform/
    6.下载镜像
         $ sudo docker pull zhl2008/web_14.04
    到此环境已经搭建完毕了,接下来讲一下操作方法和规则:

    三、操作方法:

    以root权限进入/awd-platform目录下,以yunnan_simple镜像为例:
    镜像已下载,直接启动即可
    1.复制镜像
         # python batch.py web_yunnan_simple 3//复制3个web_yunnan_simple的靶机,数值可改
         # python start.py ./ 3 //启动三个docker靶机和check服务器、flag_server服务器。数值可改
    2.裁判机启动:这里他写的check.py有问题,是无法启用的,所以我改了一下,根据爬取页面关键字判断网页是否被删除,当然也可以添加其他的页面,比如不允许删除admin.php,可以添加admin_check()函数,根据admin页面关键字判断是否被删除。

    #!/usr/bin/env python
    # -*- coding:utf8 -*-
    '''
    
    '''
    import hashlib
    import base64
    
    sleep_time  = 300
    debug = True
    headers = {"User-Agent":"Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.90 Safari/537.36"}
    
    import time
    import httplib
    import urllib2
    import ssl 
    
    my_time = 'AAAA' 
    __doc__ = 'http(method,host,port,url,data,headers)'
    flag_server = '172.17.0.1'
    key = '744def038f39652db118a68ab34895dc'
    hosts = open('host.lists','r').readlines()
    user_id = [host.split(':')[0] for host in hosts]
    hosts = [host.split(':')[1] for host in hosts]
    port = 80
    
    def http(method,host,port,url,data,headers):
        con=httplib.HTTPConnection(host,port,timeout=2)
        if method=='post' or method=='POST':
            headers['Content-Length']=len(data)
            headers['Content-Type']='application/x-www-form-urlencoded'  
            con.request("POST",url,data,headers=headers)
        else:
            headers['Content-Length'] = 0    
            con.request("GET",url,headers=headers)
        res = con.getresponse()
        if res.getheader('set-cookie'):
            #headers['Cookie'] = res.getheader('set-cookie')
            pass
        if res.getheader('Location'):
            print "Your 302 direct is: "+res.getheader('Location')
        a = res.read()
        con.close()
        return a
    
    
    def https(method,host,port,url,data,headers):
        url = 'https://' + host + ":" + str(port) + url
        req = urllib2.Request(url,data,headers)
        response = urllib2.urlopen(req)
        return response.read()
    
    def get_score():
        res = http('get',flag_server,8080,'/score.php?key=%s'%key,'',headers)
        print res
        user_scores = res.split('|')
        print "******************************************************************"
        res = ''
    
        print res
        print "******************************************************************" 
        return user_scores
    
    def write_score(scores):
        scores = '|'.join(scores)
        res = http('get',flag_server,8080,'/score.php?key=%s&write=1&score=%s'%(key,scores),'',headers)
        if res == "success":
            return True
        else:   
            print res
            raise ValueError
    
    class check():
        
        def index_check(self):
            res = http('get',host,port,'/index.php?file=%s'%str(my_time),'',headers)
            if 'perspi' in res:
                return True
            if debug:
                print "[fail!] index_fail"
            return False
    
    def server_check():
        try:
            a = check()
            if not a.index_check():
                return False
            return True
        except Exception,e:
            print e
            return False
    
    game_round = 0
    while True:
        
        scores = get_score()
        scores = []
        print "--------------------------- round %d -------------------------------"%game_round
        for host in hosts:
            print "---------------------------------------------------------------"
            host = host[:-1]
            if server_check():
                print "Host: "+host+" seems ok"
                scores.append("0")
            else:
                print "Host: "+host+" seems down"
                scores.append("-10")
        game_round += 1
        write_score(scores)
        time.sleep(sleep_time)

    #docker attach check_server
    #python check.py

     

    我稍微改了一下它的check时间和flag刷新时间,因为原版两分钟一次,太快了,所以我把它改为了5分钟。具体修改方法只要将/awd-platform/check_server/gen_flag.py  的time_span 变量设置为5*60即可,也可以改成其他的,同理还有/awd-platform/flag_server/config.php 的 min_time_span变量设置为300、/awd-platform/flag.py 变量time_span设置为5*60
    3.关闭环境命令:
    #python stop_clean.py

    四、注意事项及规则:

    1.靶机端口规则:(假设服务器ip为192.168.1.1)
    Team1:192.168.1.1:8801
    Team2:192.168.1.1:8802
    Team3:192.168.1.1:8803
    ……
    以此类推
    2.各个靶机的ssh密码可以在项目的文件夹下的pass.txt文件中,开始比赛时告知各个选手ssh密码。
    SSH的端口规则为:(假设服务器ip为192.168.1.1)
    Team1:192.168.1.1:2201
    Team2:192.168.1.1:2202
    Team3:192.168.1.1:2203
    ……
    以此类推
    3.提交flag方法:(假设服务器ip为192.168.1.1)
    http://192.168.1.1:8080/flag_file.php?token=teamX&flag=xxxx
    (teamX中的X为自己队伍号,flag为其他队伍的flag)
    4.记分牌:查看实时分数情况,没做到实时刷新一下(假设服务器ip为192.168.1.1)
    http://192.168.1.1:8080
    5.攻击情况:(假设服务器ip为192.168.1.1)
    http://192.168.1.1:8080/result.txt
    愉快的玩耍吧

    五、解决的一些问题:

    在一次测试中,发现在一轮的五分钟有效时间内一直提交某个对手的正确flag可以无限加分,在审计一波代码后发现,关键点在这里

    config.php:

    <?php
    
    $team_number = 3;
    $user_list = [];
    $token_list = array();
    $ip_list = array();
    for ($i=1; $i <= $team_number; $i++) { 
        array_push($user_list,'team'.$i);
        $token_list['team'.$i] = $i - 1;
        $ip_list['172.17.0.'.($i+1)] = $i - 1;
    }
    
    $key = '744def038f39652db118a68ab34895dc';
    $time_file = './time.txt';
    $min_time_span = 120;
    $record = './score.txt';

    flag_file.php:

    require 'config.php';
    $now_time = time();
    $flag_file = 'xxxxxxxx_flag';
    
    function check_time($attack_uid,$victim_uid){
        global $time_file;
        global $min_time_span;
        global $now_time;
        global $team_number;
        $old_times = explode('|' , file_get_contents($time_file));
        //print $now_time;
        $id = $attack_uid * $team_number + $victim_uid;
        //print $old_times[$id];
        if ($now_time - $old_times[$id] < $min_time_span){
        die("error: submit too quick ". ($min_time_span + $old_times[$id] - $now_time). " seconds left");
        }else{
        return True;
        }
    }

    这边的flag_file.php包含了config.php的配置,即变量$min_time_span和变量$time_file,通过$now_time记录当前时间戳,然后通过与$time_file记录的时间戳节点进行相减,如果符合小于预设的时间差(即一轮多长时间)这一条件则当前时间段无法再次提交flag。

    然而  $time_file = './time.txt'; 中的time.txt是这样的

    哈哈 ,为了辨别每一支队伍代表的格子,将其写为0|1|2|3|4......,然后将变量$old_times输出,经过对比后得出team对应的位置(我这里只找了三个)

    此时只需要写一个脚本将五分钟为周期的时间戳更新到time.txt中即可

    脚本如下,在启动docker之前五分钟运行,或者后五分钟也可以,改一下脚本内的配置即可,这个脚本是按照某一个时间整点的00 05 10 15 进行记录时间戳的,按自己需要也可以改为其他的

    #!/usr/bin/env python
    
    #coding:UTF-8
    
    import time
    
    import os
    
    
    print int(time.time())
    
    Unix_time = int(time.time())
    
    print time.ctime(Unix_time)
    
    while True:
    
        time_his = []
    
        time_list = ["00","05","10","15","20","25","30"]
    
        for i in time_list:
    
            dt = "2019-04-28 10:"+str(i)+":00"
    
            time_his.append(dt)
    
        a = time_his[0]
    
        b = time_his[1]
    
        c = time_his[2]
    
        d = time_his[3]
    
        e = time_his[4]
    
        f = time_his[5]
    
        g = time_his[6]
    
        time_stamp = [a,b,c,d,e,f,g]
    
        for k in time_stamp:
    
                h = open("time.txt", 'w+')
    
                timeArray = time.strptime(k, "%Y-%m-%d %H:%M:%S")
    
                timestamp = time.mktime(timeArray)
    
                print (int(timestamp))
    
                data = (int(timestamp))
    
                separated = '|'
    
                zero = '0'
    
                print >>h,(zero),(separated),(data),(separated),(zero),(separated),(data),(separated),(zero),(separated),(zero),(separated),(data),(separated),(zero),(separated),(zero),
    
                #           0|data|0|data|0|0|data|0|0
    
                h.close()
    
                time.sleep(300)

    目前这个问题解决了,但是需要一点技巧,就是开启这个脚本的时间要把握好。多调试几次应该就差不多了。

     参考:

    https://mp.weixin.qq.com/s?__biz=MzU1MzE3Njg2Mw==&mid=2247486325&idx=1&sn=96c04f3609a04260eabdd187fc7c38b1&chksm=fbf79105cc8018131579ad228dbf22a33bbdf0c8c71d3b8c090583b42ea21d80de53fc1efa70&scene=27&key=593393174013ce6d958e86eb764289b105cb7cea44d471bd3f9fe1a2ed76f546343dacb9b40a352e642e425b55c2a4d9698146a114ecd9680ed3262c8f96f6a206f0c78d6818ce0028c9bc75830936f0&ascene=7&uin=NTQ5ODg5NzY1&devicetype=Windows+10&version=6206061c&lang=zh_CN&pass_ticket=s3n8uD0SG7m1vojw%2F%2BN7uxdrTxvWnumzuUe%2BTLY12QY9yFKjU7n%2FNruWi9PS1sJO&winzoom=1

  • 相关阅读:
    (总结)Nginx/LVS/HAProxy负载均衡软件的优缺点详解
    一个自动安装LNMP的简洁Shell脚本
    (总结)Nginx配置文件nginx.conf中文详解
    Linux 的启动流程
    Linux运维文档之nginx
    nginx索引目录配置
    nginx实现图片防盗链(referer指令)
    nginx记录分析网站响应慢的请求(ngx_http_log_request_speed)
    C# 使用WinRar命令压缩和解压缩
    localStorage存值取值以及存取JSON,以及基于html5 localStorage的购物车
  • 原文地址:https://www.cnblogs.com/pureqh/p/10869327.html
Copyright © 2020-2023  润新知