70e368e235
Deploy Examination / deploy (push) Successful in 7s
New topic group: 网络安全专题 (cybersecurity) Subtopics: - web-security: Web 安全基础 (34 questions) - crypto-basics: 密码学基础 (34 questions) - buffer-overflow: 缓冲区溢出与漏洞利用 (34 questions) - os-security: 操作系统安全 (34 questions) - network-attack: 网络攻防 (34 questions) - secure-coding: 安全编程实践 (34 questions) Question types per subtopic: - single_choice × 20 - true_false × 10 - short_answer × 3 - code_reading × 1 Difficulty range: 1-3 (基础)
148 lines
8.8 KiB
JSON
148 lines
8.8 KiB
JSON
{
|
||
"topic": "secure-coding",
|
||
"type": "true_false",
|
||
"schema_version": "1.0.0",
|
||
"generated": "2026-09-17T00:00:00+08:00",
|
||
"questions": [
|
||
{
|
||
"id": "tf-001",
|
||
"type": "true_false",
|
||
"difficulty": 1,
|
||
"tags": [
|
||
"安全编程",
|
||
"输入校验"
|
||
],
|
||
"question": "在输入校验中,黑名单校验比白名单校验更安全。",
|
||
"answer": false,
|
||
"explanation": "白名单校验比黑名单校验更安全。黑名单(拒绝已知的恶意输入)容易遗漏未知攻击向量,攻击者只需找到一个绕过方式即可成功。白名单(只允许已知合法的输入格式)默认拒绝一切未明确允许的输入,安全边界更紧。例如,白名单只允许字母数字字符,就自然阻止了所有注入类攻击,而黑名单很难穷举所有可能的恶意字符组合。",
|
||
"source": null,
|
||
"related": []
|
||
},
|
||
{
|
||
"id": "tf-002",
|
||
"type": "true_false",
|
||
"difficulty": 2,
|
||
"tags": [
|
||
"安全编程",
|
||
"格式化字符串"
|
||
],
|
||
"question": "在C语言中,使用 printf(str) 而非 printf(\"%s\", str) 存在格式化字符串漏洞风险。",
|
||
"answer": true,
|
||
"explanation": "当 str 由用户控制时,printf(str) 存在严重的格式化字符串漏洞。攻击者可以在 str 中嵌入 %x、%n 等格式说明符:%x 可以泄露栈上的敏感数据(栈信息泄露),%n 可以向任意地址写入数据(任意写)。正确做法是使用 printf(\"%s\", str) 将用户输入作为纯数据输出,而非格式化字符串的一部分。类似的危险函数还包括 fprintf、sprintf、snprintf 等——只要格式化参数来自不可信输入,都存在同类风险。",
|
||
"source": null,
|
||
"related": []
|
||
},
|
||
{
|
||
"id": "tf-003",
|
||
"type": "true_false",
|
||
"difficulty": 2,
|
||
"tags": [
|
||
"安全编程",
|
||
"整数溢出"
|
||
],
|
||
"question": "在C语言中,有符号整数溢出属于未定义行为(Undefined Behavior)。",
|
||
"answer": true,
|
||
"explanation": "根据C语言标准(C99/C11 §6.5/5),有符号整数溢出是未定义行为(UB),编译器可以做任何假设,包括直接优化掉溢出检查。这与无符号整数不同——无符号整数溢出是定义良好的(模 2^n 回绕)。因此,在安全编程中,对有符号整数做溢出检查时,不能依赖溢出后的值来判断,而应在运算前检测是否会溢出(例如检查 a > INT_MAX - b 再做 a + b)。",
|
||
"source": null,
|
||
"related": []
|
||
},
|
||
{
|
||
"id": "tf-004",
|
||
"type": "true_false",
|
||
"difficulty": 2,
|
||
"tags": [
|
||
"安全编程",
|
||
"内存安全"
|
||
],
|
||
"question": "strncpy 一定比 strcpy 更安全。",
|
||
"answer": false,
|
||
"explanation": "strncpy 并不总是更安全。strncpy 存在以下陷阱:(1) 如果源字符串长度 >= n,目标缓冲区不会以 null 结尾,后续字符串操作可能越界读取;(2) 如果源字符串远短于 n,strncpy 会用零字节填充剩余空间,造成不必要的性能开销;(3) 开发者仍需手动确保 n 不超过目标缓冲区大小。更安全的替代方案是使用 strlcpy(BSD 扩展)或 snprintf(buf, sizeof(buf), \"%s\", src),它们保证目标始终 null 结尾。",
|
||
"source": null,
|
||
"related": []
|
||
},
|
||
{
|
||
"id": "tf-005",
|
||
"type": "true_false",
|
||
"difficulty": 1,
|
||
"tags": [
|
||
"安全编程",
|
||
"输入校验"
|
||
],
|
||
"question": "使用参数化查询(Prepared Statements)可以有效防止SQL注入攻击。",
|
||
"answer": true,
|
||
"explanation": "参数化查询通过将SQL语句结构与数据严格分离来防止注入。数据库驱动会将参数值作为纯数据传输,不会被解释为SQL代码。例如,SELECT * FROM users WHERE id = ? 中,即使参数值包含 ' OR 1=1 -- 等注入载荷,数据库也只会将其视为普通字符串进行匹配,而非SQL逻辑。这是防御SQL注入的首选方案,比手动转义或存储过程更可靠。注意:如果动态拼接表名、列名或ORDER BY等SQL结构部分,参数化查询无法覆盖,仍需白名单校验。",
|
||
"source": null,
|
||
"related": []
|
||
},
|
||
{
|
||
"id": "tf-006",
|
||
"type": "true_false",
|
||
"difficulty": 1,
|
||
"tags": [
|
||
"安全编程",
|
||
"内存安全"
|
||
],
|
||
"question": "C11标准已将 gets() 函数标记为废弃(deprecated)并推荐使用更安全的替代方案。",
|
||
"answer": true,
|
||
"explanation": "gets() 在 C11 标准(ISO/IEC 9899:2011 Annex K)中已被正式移除。gets() 不接受长度参数,无法限制读取的字符数,是经典的缓冲区溢出漏洞来源(例如1988年Morris蠕虫就利用了 gets() 的缺陷)。C11 推荐使用 fgets(buf, size, stdin) 替代,fgets 允许指定最大读取长度,但需注意它会保留换行符。微软的 gets_s() 是另一个安全替代,但它是平台特定扩展,不具有跨平台可移植性。",
|
||
"source": null,
|
||
"related": []
|
||
},
|
||
{
|
||
"id": "tf-007",
|
||
"type": "true_false",
|
||
"difficulty": 2,
|
||
"tags": [
|
||
"安全编程",
|
||
"整数溢出"
|
||
],
|
||
"question": "无符号整数相减永远不会出现安全问题,因为无符号数没有负数。",
|
||
"answer": false,
|
||
"explanation": "无符号整数相减确实不会产生负数——但当被减数小于减数时,会发生无符号下溢(underflow),结果回绕到一个极大的正数。例如,(unsigned)3 - 5 在32位系统下等于 4294967294(即 2^32 - 2),而非 -2。这在安全场景中非常危险:如果用作内存分配大小、数组索引或循环边界,会导致分配过大的内存、越界访问或无限循环。正确做法是在减法前检查操作数关系,确保被减数 >= 减数。",
|
||
"source": null,
|
||
"related": []
|
||
},
|
||
{
|
||
"id": "tf-008",
|
||
"type": "true_false",
|
||
"difficulty": 3,
|
||
"tags": [
|
||
"安全编程",
|
||
"输入校验"
|
||
],
|
||
"question": "部署内容安全策略(CSP)可以完全阻止所有XSS攻击。",
|
||
"answer": false,
|
||
"explanation": "CSP是防御XSS的重要辅助手段,但无法完全阻止所有XSS。CSP的局限性包括:(1) 如果页面本身存在内联脚本且无法迁移到外部文件,需要使用 unsafe-inline,这削弱了CSP防护;(2) 已知的DOM型XSS(如通过innerHTML注入事件处理器)在某些CSP配置下仍可利用;(3) 如果CDN或第三方库被攻破,允许的脚本源可能成为攻击载体;(4) CSP无法阻止基于CSS或HTML属性的某些信息泄露攻击。XSS防御应采用纵深策略:输出编码 + CSP + 输入校验 + HttpOnly Cookie + 子资源完整性(SRI)。",
|
||
"source": null,
|
||
"related": []
|
||
},
|
||
{
|
||
"id": "tf-009",
|
||
"type": "true_false",
|
||
"difficulty": 2,
|
||
"tags": [
|
||
"安全编程",
|
||
"内存安全"
|
||
],
|
||
"question": "地址空间布局随机化(ASLR)是一种有效的内存安全防御技术,可以增加攻击者利用内存漏洞的难度。",
|
||
"answer": true,
|
||
"explanation": "ASLR通过在每次程序运行时随机化关键内存区域(栈、堆、共享库、可执行文件基址)的位置,使攻击者无法预测目标地址,从而大幅增加利用难度。例如,ROP攻击需要知道 gadget 的精确地址,ASLR使这些地址在每次运行时都不同。但ASLR并非万能:(1) 信息泄露漏洞可以泄露内存地址,绕过ASLR;(2) 32位系统的熵不足,暴力破解可能成功;(3) 部分实现(如旧版Windows ASLR)不覆盖所有区域。ASLR应与DEP/NX、Stack Canary、CFI等技术配合使用,构成完整的纵深防御体系。",
|
||
"source": null,
|
||
"related": []
|
||
},
|
||
{
|
||
"id": "tf-010",
|
||
"type": "true_false",
|
||
"difficulty": 1,
|
||
"tags": [
|
||
"安全编程",
|
||
"输入校验"
|
||
],
|
||
"question": "在Web应用中,只要服务端进行了充分的输入校验,客户端就不需要做任何输入校验。",
|
||
"answer": false,
|
||
"explanation": "服务端校验是安全的最后防线,必须执行,但客户端校验同样有价值:(1) 用户体验——即时反馈比提交后再报错体验更好,减少不必要的网络请求;(2) 服务端负载——客户端预过滤可以减少无效请求对服务端的压力;(3) 辅助防御——增加攻击者篡改请求的成本。但客户端校验绝不能替代服务端校验,因为客户端代码(JavaScript、HTML属性)可被用户完全绕过(禁用JS、修改DOM、直接发送HTTP请求)。正确的做法是:客户端校验用于提升体验,服务端校验用于保障安全,两者并行。",
|
||
"source": null,
|
||
"related": []
|
||
}
|
||
]
|
||
} |