Web安全——盾与矛

作为 Web 开发者,我们应当知道自己开发的系统有哪些风险漏洞可能会被攻击,这篇文章将讲述在 Web 中经常使用的攻击手段,以及相应的防御策略。

信息探测

第一步,我们需要踩点,搜集目标资料,找到哪些网站可能存在漏洞。

子域名收集

为什么要枚举子域名?

  • 子域名枚举可以再测试范围内发现更多的域,这将增大漏洞发现的机会。
  • 有些隐藏的、被忽略的子域上运行的应用程序可能帮助我们发现重大漏洞。

如何枚举?

  1. 利用搜索引擎,如 site:baidu.com ,但这样并不靠谱,可能前几页都是一个子域名。
  2. DNS信息收集,借助一些网站,如这是百度的子域收集结果:https://www.virustotal.com/gui/domain/baidu.com/relations
  3. 一些其他开源工具,如 https://github.com/shmilylty/OneForAll

更多工具详情,可参考 https://zhuanlan.zhihu.com/p/31334686

借助搜索搜索敏感信息

可以根据 Google 提供的语法进行信息查询。常用语法可以参考https://en.wikipedia.org/wiki/Google_hacking
如搜索存在敏感信息的网站:
image.png

使用Nmap

探测主机信息

Nmap是一个开源的网络连接端扫描软件,用于扫描计算机开放的网络连接端,确定哪些服务运行在哪些连接端,推断计算机运行的操作系统。

  1. 扫描指定 IP 所开放的端口(这里指定了端口范围是1-65535)
    nmap -sS -p 1-65535 -v 192.168.1.100
  2. 全面的系统检测,默认扫描主机1000个高危端口
    nmap -v -A www.xxser.com
  3. 扫描指定端口
    nmap -p 80,22,3306 www.xxser.com
  4. 穿透防火墙进行扫描(被禁用ping)
    nmap -Pn -A www.xxser.com

更多指令参数查看 -help

使用Nmap脚本

nmap还提供了强大的脚本功能,是最好的功能之一,可以利用脚本快速探测服务器

  1. 扫描Web敏感目录
    nmap -p 80 --script=http-enum.nse www.xxser.com
  2. 暴力破解mysql密码,只能欺负欺负弱密码
    ➜ nmap -p 3306 --script=mysql-brute 127.0.0.1
    更多脚本请查看https://nmap.org/nsedoc/

常见漏洞

SQL注入漏洞

原理

在用户登录时,可能会这样写SQL:select * from user where username = '${name}' and password = '${passwd}'; 。在一般情况下没有问题,但用户如果输入了这样一个“ ' or 1=1;--”特殊的用户名会如何?最终执行的sql将会变成 select * from user where username = '' or 1=1;--' and password = '';

这条SQL会将所有的用户都查询出来,后面的password判断彻底失效,因为已经被注释掉了,如果在 加个 limit 1,几乎可以登录任意一个用户的账号了,后果非常严重。

解决办法

检查数据类型和格式

如果sql语句是类似 where id = ${id},那么在执行前就应该确保 id 是数字类型。如果使用的 Java 这样的强类型语言,没抛异常就说明是没问题的了。

特殊字符串转义

除了检查类型,还应该检查入参中,是否包含一些特殊的字符,如系统的用户名如果不允许用 ‘-‘,就应该排除掉。对于这些特殊字符,如单引号、双引号、反斜杠、中横线,都应该根据业务考虑禁止,如果不可,那么只能对特殊字符串进行转义。

预编译语句

上面说的可能是比较low的方法,最佳方案是使用预编译语句来预防SQL注入。

使用预编译后注入的参数将不会再进行SQL编译。也就是说其后注入进来的参数系统将不会认为它会是一条SQL语句,而默认其是一个参数,参数中的or或者and 等就不是SQL语法保留字了。

数据库提供了预编译技术,Mybatis中打印SQL的话,会看见这种带问号的,如select * from users where name = ? ,? 就是填充符。

在Mysql中进行实验:

  1. 准备数据

    1
    2
    3
    4
    5
    6
    CREATE TABLE `user` (
    `username` varchar(20) DEFAULT NULL,
    `password` varchar(20) DEFAULT NULL
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8;

    insert into user values("a","a1");
  2. 对sql进行预编译

    1
    prepare sqltpl from 'select * from user where username = ? and password = ?';
  3. 设置参数

    1
    set @para1='a',@para2='a1';
  4. 使用该参数来执行预编译语句

    1
    execute sqltpl using @para1, @para2;

    image.png


写着写着突然发现这个网站… PeiQi WiKi-POC文库🐑,这篇文章基本太监了。