0xA3 安全域划分和系统基本加固

我们接着前面的时间线,现在人基本上也已经找齐了,而且情况基本了解了,我们应该放手开始干了。

由于我们的情况是一个小的公司里面的安全团队,我们最近要做的应该是去补全企业的基础安全措施。其实不管是安全实践多么厉害的公司,他们的安全体系都离不开一些必要的基本的安全措施,基本安全措施是后期纵深防御体系建立的必要基础。在一些低成本的安全解决方案里,一个安全设备放在链路上检测所有的协议并关注所有的行为报警,这样的报警很大一部分都是一些没有用的。

安全域的划分:安全域划分的目的是将一组安全等级相同的计算机换分到同一个安全域,对安全域内的计算机设置相同的网络边界,在网络边界上以最小权限开放对其他安全域的NACL,使得安全域内这组计算机暴露的风险最小化,在发生攻击等安全事件的时候能够将威胁最大化隔离,减小域外对域内的影响。我们接下来要讨论的是几种常见的安全域划分原则。

传统安全域划分:其实传统的安全域划分原则就是把企业网络划分成两部分,外部网络(DMZ区域)和内部网络(企业网络),中间使用防火墙建立边界。正常的主机请求是首先先回通过防火墙然后才能去访问,如果要访问内网的话,还是需要通过一个防火墙来进入内部网络。在这个时候,DMZ区域和企业内网区域就是两个安全级别不同的安全域。

Web服务:Web服务是一个层级结构,包括接入层、应用层、数据层等结构,安全域和访问控制其实有一个比较好的模型就是EC2的安全组模型。

EC2的安全组规则可控制允许到达与安全组相关联的实例的入站流量以及允许离开实例的出站流量。Web层直接暴露给用户,但是应用层则不需要,实际上应用层只需要接受web层的访问请求,并且能访问更靠后一层的数据层,数据层则只需要接收来自于应用层的请求,同时I/O来自于EBS卷。如果使用默认安全组,则只能接受管理员的SSH连接,但是管理员是不允许直接通过互联网接入方式连接服务器,而是通过堡垒机来发起来凝结,然后在发起到其它层的连接。这样每层只对外开放最少的端口除了必要协议外全部阻断。安全域划分其实不一定要按照VLAN进行划分,基于L3和L4防火墙、NAT、FPM都可以起到隔离的作用,基于VLAN的话,只是能够增加可靠性。关于EC2的安全组划分可以参考

Linux 实例的 Amazon EC2 个安全组

大型系统划分:这里一般就是上规模的系统了,但是由于我们目前的信息安全工作还打不到这个体量,所以我们先暂时放下。Openstack的安全组模型就是一个大型安全域划分的案例。


生产网络和办公网络划分:生产网络和办公网络划分主要是为了防御域渗透。试想一下,如果攻击者渗透完生产网络然后拿到了一些域账户和密码,然后利用社会工程学手段漫游域,之后走人,那么可能所有的机密全都被别人拿走了。我们可以采取一下的手段来加强生产与办公网络的隔离:

  • 生产网络的SSH端口在前端防火墙和交换机上默认不允许访问
  • 远程访问需要通过VPN或者专线才能连接到生产网络
  • 通过生产网络的网段要做好隔离,阻止来自于外网服务器的连接可以访问OA、HR等与内部运营相关的系统
  • 办公网中的运维系统、发布源和其他的系统在L2层次上隔离
  • 运维网段和办公网段接入的链路互相独立
  • 运维专线要采取ISP热备份,防止ISP故障导致无法访问
  • 堡垒机和跳板机要有全流量审计

系统安全加固:

操作系统的加固是一个安全基本操作手段,笔者这里不会涉及到很多细节,如果想要详细了解可以去看一下其他的书。

对于Linux系统来讲我们需要做以下几点:

  1. 禁用LKM:LKM是Linux内核为了扩展其功能所使用的可加载内核模块。LKM的优点:动态加载,无须重新实现整个内核。基于此特性,LKM常被用作特殊设备的驱动程序(或文件系统),如声卡的驱动程序等等。关闭LKM好处是可以规避一些LKM的Rootkit,关闭LKM的命令如下: root@elknot# echo 1 > /proc/sys/kernel/modules_disabled(sysctl -w kernel.modules_disable=1),但是这样做一旦重启计算机就会失效,所以我们要使用永久的方法来关闭LKM:首先先使用make config或者make menuconfig,在Loadable Module Support选项中的Enable Loadable Module Support(CONFIG_MODULES)选择N
  2. 限制/dev/mem:/dev/mem可以通过mmap可以将物理地址映射到用户空间的虚拟地址上,在用户空间完成对设备寄存器的操作。如果紧紧关闭LKM的话,依然可以通过读取/dev/mem或者/dev/kmem来在用户模式下实现内核rootkit,比如suckit。新版的系统中默认不使用/dev/kmem这个文件,我们需要查看/boot下的config文件来确定CONFIG_DEVKMEM设置为N并且CONFIG_STRICT_DEVMEM设置为Y。
  3. 开启ASLR:首先我们要开启全局ASLR,ASLR(Address space layout randomization)是一种针对缓冲区溢出的安全保护技术,通过对堆、栈、共享库映射等线性区布局的随机化,通过增加攻击者预测目的地址的难度,防止攻击者直接定位攻击代码位置,达到阻止溢出攻击的目的。据研究表明ASLR可以有效的降低缓冲区溢出攻击的成功率,如今Linux、FreeBSD、Windows等主流操作系统都已采用了该技术。开启ASLR的方法如下:root@elknot# echo 2>/proc/sys/kernel/randomize_va_space,首先先来说一下各个值的意思:
  4. 0:关闭ASLR。
  5. 1:mmap base、stack、vsdo page将随机化,也就是说.so文件将被加载到随机地址,并且连接时制定了-pie选项的可执行程序,代码加载地址也会随机化。配置内核时候如果指定了CONFIG_COMPAT_BRK,该值会默认为1。但是这个时候heap没有随机化。
  6. 2:heap随机化,如果配置内核的时候禁用了CONFIG_COMPAT_BRK,该值为2。
  7. 隐藏符号表:隐藏内核符号表的命令如下:root@elknot# echo 1 > /proc/sys/kernel/kptr_restrict
  8. 内存映射最小地址:配置命令如下:root@elknot# echo 65536 > /proc/sys/vm/mmap_min_addr
  9. 禁用NAT:攻击者在渗透内网是常用的一个技巧就是开启端口转发,这样可以用一个比较方便的方式突破边界访问内网服务器,我们需要通过以下命令来禁用IP转发:root@elknot# echo 0 > /proc/sys/net/ipv4/ip_forward,如果这个值变为1的话并且没有任何人出来说明的情况的话,那么就很有可能被人入侵了
  10. Bash日志:系统默认有一个文件.bash_history在用户目录下,为bashrc添加如下命令:
  • readonly HISTFILE
  • readonly HISTFILESIZE
  • readonly HISTSIZE
  • readonly HISTCMD
  • readonly HISTCONTROL
  • readonly HISTIGNORE
  • #为history添加时间戳
  • export HISTTIMEFORMAT=‘%F %T ’

使用source ~/.bashrc来让刚才的配置生效,并且使用chattr +a ~/.bash_history来设置history文件只能追加。这个时候最好把其他的shell禁用掉,比如ksh、rcsh、zsh等等。其实在配置这些可以过滤掉一些对Linux不熟练的攻击者、不能完全清理日志的自动化工具和一些Botnet程序。

  1. 其他的技巧:其实修改源代码来修改一些函数是一个不错的方法,比如libc中的execl()、execlp()、execle()、execv()、execvp()、execve(),其实前面五个函数都是调用的execve()。另外一个方法就是把shell里面的日志统一收集到一台服务器上进行操作,并且标出来敏感的危险操作。

应用配置加固:

  1. 目录权限:有句话说得好——可读目录不可写,可写目录不可读,这句话恰好说的就是用来对抗webshell攻击,大意为攻击者通过文件上传漏洞上传webshell或者通过应用层漏洞在目录下写入了一个webshell,因为没有执行权限无法通过webshell执行命令,或者当目录有解析执行权限的时候因为没有写权限无法生成webshell文件达到阻止渗透的目的。但是发展到现在来看,以后这个规则越用越小也说不定。可读目录不可写翻译成命令就是:root@elknot# chmod 755 webroot,如果部分子目录因为业务原因需要高权限的话,请更改目录拥有者为web进程:root@elknot# chown webserver: webroot。可写目录不可读在nginx的php配置就是:localtion ~* ^data/cgisvr/log/.*\.(php|php5) ${deny all;},如果要是Java的话,因为tomcat默认解析jspx格式文件,如果不需要的话可以去修改conf下面的web.xml注释掉<url-partten> *.jspx </url-pattern>。
  2. Web进程以非root权限运行:web进程以非root权限运行遵循最小权限原则,如果以root运行,则会导致exp攻击时直接拿到root权限或者当应用层代码出现问题时会直接以root权限执行webshell命令。检测方法是使用ps -ef来查看master进程和worker进程,master进程默认以root运行,而worker默认以nobody权限运行。

远程访问:这里注意的比较少,只需要把ssh版本设置成v2(修改ssh的配置文件中Protocol为2)并且仅用root远程登录(PermitRootLogin为No)即可

账号密码:这里很容易出现一个比较头疼的问题就是暴力破解,鉴于账号的特殊性,密码爆破成为了最常用的手段。对待暴力破解的方法通常是引入双因子认证,但是如果开启了账户登录失败锁定策略的话,很容易就把暴力破解演变成为DoS攻击,所以针对安全团队而言,平时应该去收集一些比较新的密码爆破数据库(这里要感谢360的王老师的热心提醒),同时也要周期性更新这个密码库,但凡出现在这个密码库里的密码,不管有多强的复杂度,都应该认定成为弱密码。

网络ACL:其实这里的话,系统级的NACL无论是粒度还是其他方面,用默认自带的iptables基本就够用了,只开放服务端口和管理端口,对于数据库而言只开放应用服务器的IP才能连接。但是在大规模IDC追求弹性运维的角度而言,需要在两个方面做补偿,一是资产权重划分要按照多维和细粒度去划分,二是但电视线较强的入侵检测和降维防御的能力,这一部分都是前面说到的L4、L5阶段该考虑的事情。

补丁集管理:安全团队需要考虑的是评估漏洞的危害和对自身的影响,这点依赖于很多的事情,比如资产和配置的管理、系统层和应用层的漏洞判定,甚至还有实际的攻击面和利用可能性等。从安全团队的角度出发,我们的补丁集管理应该做到大批量的打补丁并且尽量不去影响正常业务,同时要具备一定的容灾能力,同时提供hotfix热补丁,并且要同时针对单个漏洞进行快速扫描。

日志审计:这里需要分析的就是一些系统级日志,比如lastlog,syslog,sshlog,weblog等,可以接入ELK、Splunk这些数据分析平台。

编辑于 2017-04-27 12:58