7

Web_番外篇_AWD芝士 | Charmersix's Blog

 2 years ago
source link: https://charmersix.icu/2023/04/25/AWD/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

Charmersix's Blog

Web_番外篇_AWD芝士
Charmersix
  2023-04-25 00:00  2.7k Words  13 Mins  3

由于我对二进制一窍不通, 这里以web_awd为主, 这也不是我的教程, 而是参考了其他大佬文章做的笔记这里主要参考了两位大佬nul1
哈喽沃德er
的两篇文章

AWD: Attack With Defence, 强调攻防/实战/对抗, 综合考量队伍的渗透能力和防护能力

比赛中, 每个队伍维护多台服务器, 服务器中存在多个漏洞, 利用漏洞攻击其他队伍就可以进行得分, 修复漏洞避免其他队伍攻击可以防止丢分

  • 一般分配web服务器(多数为Linux) 某处存在flag(一般在根目录下)
  • 肯能会提供一台流量分析虚拟机, 可以下载流量文件进行数据分析
  • flag在主办方的设定下每隔一定时间刷新一轮
  • 各队一般有自己的初始分数
  • flag被其他队伍拿走, 该队就会扣除一定积分
  • 扣除的积分由获取flag的队伍均分
  • 主办方会对每个队伍的服务进行check, 服务器宕机扣除本轮flag分数, 扣除的分数由服务check正常的队伍均分
  • 一般每个队伍会给一个低权限用户, 非root权限

image

比赛中获取flag一般有两种模式

  1. flag在根目录下, 读取flag内容提交即可得分
  2. 拿到其他队伍的shell后, 执行指定命令curl 10.0.0.2即可从上图flag机获取flag内容

比赛可能会告诉你其他队伍的IP, 也有可能不告诉你, 一般实在同一个C段或者B段, 可以利用nmap等攻击扫描发现其他队伍的IP

SHELL
nmap -sn 192.168.71.0/24

或者用https://github.com/zer0h/httpscan 的脚本进行扫描

修改弱口令密码, 主办方设置的密码极有可能时弱口令, 包括但不限于ssh/phpcms/wordpress, 需要立即修改口令, 改完自己队伍的之后可以看一下其他队伍的有没有修改.

不过, 有些比赛不允许修改后台口令, 如果修改视为服务器宕机

备份源码并查找预留后门

备份源码, 比赛开始第一件事就是备份源码, 将网站源码下载后复制一下, 用D盾扫描一份预留一份防止宕机, D盾扫描后也会发现一些预留后门, 第一时间删除后门后, 然后利用这个后门发起一波攻击

数据库备份

登录数据库备份, 当数据被删除的时候可以使用命令快速还原

mysqldump -u db_user -p db_passwd db_name > 1.sql //备份指定数据库 
mysql -u db_user -p db_passwd db_name < 1.sql //还原指定数据库 

关闭不必要的端口

一些端口会存在漏洞, 为了保证安全, 我们关闭一些不必要的端口

image

部署WAF

这里推荐一个AoiAWD

CTFDefense

但是这里要注意规则是否允许第三方通防

也可以使用这个

<?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. 在页面中加入防护, 有两种做法, 根据情况二选一即可

在首页面加入代码

require_once('waf.php');

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

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

在每个文件最前加上代码
在php.ini中找到:

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

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

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

比赛中我们的对手不止有一个, 这里就需要我们批量getshell, 批量提交flag

就像上面所说的预留后门, 不需要专门去打, 可以直接批量getshell

可以使用discuz-ml-rce

flag也是批量提交效率才会高一些

#!/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)

通过流量、日志的分析:

1.感知可能正在发生的攻击,从而规避存在的安全风险

2.应急响应,还原攻击者的攻击路径,从而挽回已经造成的损失

3.学习别人的攻击方法

基于流量监控来实现,一个简单的脚本如下:

<?php
date_default_timezone_set('Asia/Shanghai');
$ip = $_SERVER["REMOTE_ADDR"]; //记录访问者的ip
$filename = $_SERVER['PHP_SELF']; //访问者要访问的文件名
$parameter = $_SERVER["QUERY_STRING"]; //访问者要请求的参数
$time = date('Y-m-d H:i:s',time()); //访问时间
$logadd = '来访时间:'.$time.'-->'.'访问链接:'.'http://'.$ip.$filename.'?'.$parameter."\r\n";
// log记录
$fh = fopen("log.txt", "a");
fwrite($fh, $logadd);
fclose($fh);
?>
SHELL
find / -name *flag* #查找flag位置
SHELL
find .|xargs grep "password" #查找password
SHELL
netstat -antulp | grep EST #查看以建立的连接和进程
SHELL
kill PID 
killall <进程名> #结束进程
SHELL
netstat -ant|awk|grep |sed -e-e |sort|uniq -c|sort -rn #检测TCP连接数量
SHELL
chattr +i /etc/resolv.conf #chattr命令防止系统中某个关键文件被修改

Recommend

  • 3

    Charmersix  2023-04-23 21:49  6.8k Words  31 Mins  3Flask学习提到python就离不开flask, 这里我们先借用flask写一个helloworld首先直接pip install...

  • 8
    • charmersix.github.io 1 year ago
    • Cache

    Web_9_PHP代码审计 | Charmersix's Blog

    Charmersix  2023-03-24 00:00  7.5k Words  30 Mins  1首先总结一下代码审计的思路检查敏感函数的参数, 然后回溯变量, 判断变量是否可控, 并且有没有经过严格的过滤, 这是一个逆...

  • 11
    • charmersix.github.io 1 year ago
    • Cache

    Python_Selenium_Study | Charmersix's Blog

    Charmersix  2023-03-08 00:00  9.7k Words  41 Mins  1在一切的开始,先感谢白月黑羽师傅这是师傅的blog:

  • 4
    • charmersix.github.io 1 year ago
    • Cache

    西湖论剑MISC | Charmersix's Blog

    Charmersix's Blog西湖论剑MISCCharmersix  2023-02-28 00:00  2.2k Words  9 Mins  1拖进winhex, 发现结尾是一张png, foremost分出来试一下foremost /home...

  • 6
    • charmersix.github.io 1 year ago
    • Cache

    Web_7_SSRF/JWT/XXE | Charmersix's Blog

    Charmersix  2022-10-30 00:00  3.7k Words  15 Mins  1第一节 SSRF的漏洞利用0x1 ssrf原理解析什么是ssrf

  • 5
    • charmersix.github.io 1 year ago
    • Cache

    Web_6_PHP反序列化 | Charmersix's Blog

    Charmersix  2022-10-20 00:00  9.2k Words  39 Mins  1第一节 php基础、类与对象读文档类与对象0x1 php中的面向对象在...

  • 3
    • charmersix.github.io 1 year ago
    • Cache

    Web_11_Node.js | Charmersix's Blog

    Charmersix  2023-05-30 21:49  6.8k Words  30 Mins  12Node.js基础简单的说nodejs就是运行在服务端的JavaScript, Node.js是一个基于chrome JavaScript运行时建立的一个平台, N...

  • 2

    Charmersix  2023-02-19 00:00  3.2k Words  15 Mins  6第一节 认识thinkphp0x1 php开发框架为了避免重复造轮子, 这里就出现了PHP开发框...

  • 5
    • charmersix.icu 1 year ago
    • Cache

    ATK&CK(一) | Charmersix's Blog

    Charmersix  2023-10-13 00:00  4.1k Words  16 Mins  22靶机下载: http://vulnstack.qiyuanxuetang.net/vuln/detail/2

  • 6
    • charmersix.icu 1 year ago
    • Cache

    AoiAWD踩雷指南 | Charmersix's Blog

    Charmersix  2023-10-17 00:00  505 Words  2 Mins  11AoiAWD环境搭建官方其实提提供了构建流程, 但是其搭建过程中的坑网上的处理方式还是很少的, 网上大部分教程也已经很老...

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK