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 (基础)
83 lines
9.1 KiB
JSON
83 lines
9.1 KiB
JSON
{
|
||
"topic": "secure-coding",
|
||
"type": "short_answer",
|
||
"schema_version": "1.0.0",
|
||
"generated": "2026-09-17T00:00:00+08:00",
|
||
"questions": [
|
||
{
|
||
"id": "sa-001",
|
||
"type": "short_answer",
|
||
"difficulty": 1,
|
||
"tags": [
|
||
"安全编程",
|
||
"输入校验"
|
||
],
|
||
"question": "简述Web应用中输入校验的「双重校验」原则(客户端+服务端),以及各自的作用和局限性。",
|
||
"answer": "双重校验原则要求在客户端和服务端都对用户输入进行校验,两者缺一不可。\n\n1. 客户端校验:在浏览器/前端通过JavaScript等脚本对用户输入进行即时检查(如格式、长度、范围)。其作用是提升用户体验,减少无效请求,提供即时反馈。局限性在于客户端代码完全受用户控制,攻击者可以绕过(禁用JS、篡改请求、使用代理工具直接发送恶意请求),因此不能作为安全保障。\n\n2. 服务端校验:在后端对所有接收到的输入进行严格校验,是安全的最后一道防线。其作用是防止恶意数据进入系统,防御SQL注入、XSS、命令注入等攻击。局限性在于反馈延迟、增加服务端负担,且校验规则需要与业务逻辑紧密配合。\n\n核心原则:永远不要信任来自客户端的任何数据。客户端校验是便利性措施,服务端校验是安全性措施。",
|
||
"keywords": [
|
||
"客户端校验",
|
||
"服务端校验",
|
||
"输入验证",
|
||
"不可信输入",
|
||
"XSS",
|
||
"SQL注入",
|
||
"白名单"
|
||
],
|
||
"scoring_rubric": "满分标准:(1) 说明双重校验的概念,即客户端和服务端都需要校验(2分);(2) 正确描述客户端校验的作用:提升用户体验、即时反馈(2分);(3) 正确描述客户端校验的局限性:可被绕过、不可信赖(2分);(4) 正确描述服务端校验的作用:安全最后防线、防御注入攻击(2分);(5) 提出核心原则——不信任客户端数据(2分)。",
|
||
"explanation": "输入校验是Web安全的基础。OWASP Top 10中多次将注入类漏洞列为第一大安全风险。双重校验体现了纵深防御思想:客户端校验解决易用性问题,服务端校验解决安全性问题。很多初级开发者误以为客户端校验就够了,导致直接通过API发送未经校验的恶意数据,引发SQL注入、存储型XSS等严重漏洞。理解这一原则是安全编程的入门基础。",
|
||
"source": null,
|
||
"related": []
|
||
},
|
||
{
|
||
"id": "sa-002",
|
||
"type": "short_answer",
|
||
"difficulty": 2,
|
||
"tags": [
|
||
"安全编程",
|
||
"整数溢出"
|
||
],
|
||
"question": "解释整数溢出的原理,并给出至少两种防御方法。",
|
||
"answer": "整数溢出原理:计算机中整数以固定位数的二进制存储(如32位有符号整数范围为 -2^31 ~ 2^31-1)。当算术运算的结果超出该数据类型能表示的范围时,高位被截断,导致结果「回绕」(wrap around)。例如,32位无符号整数 0xFFFFFFFF + 1 = 0x00000000(回绕为0)。有符号整数溢出还可能导致正数变负数,这在C/C++中属于未定义行为(UB)。\n\n整数溢出在安全上的危害包括:(1) 缓冲区溢出——分配内存时计算出的大小因溢出变小,导致后续写入越界;(2) 绕过边界检查——索引或长度校验因溢出被绕过;(3) 逻辑错误——资金计算、权限判断等场景产生错误结果。\n\n防御方法(至少两种):\n1. 使用安全的整数运算库/内置函数:如 GCC 的 __builtin_add_overflow()、Clang 的 __builtin_*_overflow 系列函数,或 C23 标准的 <stdckdint.h> 中的 ckd_add/ckd_mul 等检查溢出宏。这些工具在发生溢出时返回溢出标志,程序可据此进行错误处理。\n\n2. 运算前进行边界检查(前置校验):在执行加减乘除之前,检查操作数是否会导致溢出。例如,乘法前检查 a > SIZE_MAX / b;加法前检查 a > MAX - b。若会溢出则拒绝操作。\n\n3. 使用更大位宽的数据类型:将计算临时提升到更大的类型(如用64位计算后再检查是否超出32位范围),但这只是权宜之计,不能根本解决问题。\n\n4. 使用支持安全算术的语言或编译选项:如 Rust 默认在 debug 模式下检测溢出,Java 的 Math.addExact() 会在溢出时抛出 ArithmeticException,或使用 -ftrapv 编译选项让C程序在有符号溢出时中止。",
|
||
"keywords": [
|
||
"整数溢出",
|
||
"回绕",
|
||
"缓冲区溢出",
|
||
"未定义行为",
|
||
"边界检查",
|
||
"安全算术",
|
||
"__builtin_add_overflow",
|
||
"前置校验"
|
||
],
|
||
"scoring_rubric": "满分标准:(1) 正确解释整数溢出原理——固定位数存储、结果超出范围导致回绕或截断(3分);(2) 说明溢出的安全危害,如缓冲区溢出、边界检查绕过等(2分);(3) 给出至少两种有效的防御方法并说明原理(各2分,共4分);(4) 表述准确,术语使用正确(1分)。若仅给出一种防御方法扣2分;若原理描述不完整扣1-2分。",
|
||
"explanation": "整数溢出是一种常见但容易被忽视的安全漏洞,尤其在C/C++等系统编程语言中。2014年OpenSSL的Heartbleed漏洞的根因之一就涉及整数溢出。在安全编程中,任何涉及内存分配大小、数组索引、循环计数的整数运算都必须考虑溢出可能。掌握溢出原理和防御方法是编写安全系统软件的基本功。",
|
||
"source": null,
|
||
"related": []
|
||
},
|
||
{
|
||
"id": "sa-003",
|
||
"type": "short_answer",
|
||
"difficulty": 2,
|
||
"tags": [
|
||
"安全编程",
|
||
"格式化字符串"
|
||
],
|
||
"question": "对比 sprintf/snprintf 和 printf/fprintf 在安全性上的差异,说明为什么格式化字符串漏洞是危险的。",
|
||
"answer": "函数分类与安全性差异:\n\n1. printf/fprintf 是输出到标准输出/文件流的格式化输出函数。它们的安全风险在于:如果格式字符串(format string)来自用户输入,攻击者可以在格式串中插入 %x(读取栈内容)、%n(向任意地址写入)、%s(读取指针指向的内容)等格式说明符,导致信息泄露或任意内存写入。\n\n2. sprintf/snprintf 是输出到缓冲区的格式化写入函数。除了与 printf 相同的格式化字符串漏洞外,sprintf 还有一个额外风险:没有长度限制,如果格式化后的字符串长度超过目标缓冲区大小,就会发生缓冲区溢出。snprintf 通过限制最大写入字节数(包括 NUL 终止符)来缓解这个问题,是 sprintf 的安全替代品。\n\n安全性对比:\n- sprintf vs snprintf:snprintf 通过 size 参数防止缓冲区溢出,应始终优先使用 snprintf 而非 sprintf。\n- printf 类 vs sprintf 类:printf 类将结果输出到标准流,不会直接造成缓冲区溢出;sprintf 类可能同时面临缓冲区溢出和格式化字符串漏洞的双重风险。\n\n格式化字符串漏洞为什么危险:\n1. 信息泄露:%x、%p 等可以读取栈上的敏感数据(密钥、地址、canary 值)。\n2. 任意地址写入:%n 可以将已输出的字符数写入任意内存地址,攻击者可以精确控制写入的值和地址,从而覆写函数返回地址、GOT 表项等,实现代码执行。\n3. 进程崩溃:%s 对栈上随机值的解引用大概率导致段错误,可造成拒绝服务。\n4. 组合利用:信息泄露 + 任意写入的组合使得这类漏洞几乎总能转化为完整的代码执行利用。\n\n防御方法:始终将格式字符串硬编码为字面量(如 printf(\"%s\", user_input) 而非 printf(user_input)),对 sprintf 使用 snprintf 并正确计算缓冲区大小。",
|
||
"keywords": [
|
||
"格式化字符串",
|
||
"sprintf",
|
||
"snprintf",
|
||
"printf",
|
||
"缓冲区溢出",
|
||
"%n",
|
||
"任意写入",
|
||
"信息泄露",
|
||
"GOT覆写"
|
||
],
|
||
"scoring_rubric": "满分标准:(1) 正确区分 printf/fprintf 和 sprintf/snprintf 的功能差异(2分);(2) 说明 snprintf 相比 sprintf 的安全优势——防止缓冲区溢出(2分);(3) 解释格式化字符串漏洞的原理——用户可控的格式串中的 %x、%n 等(2分);(4) 说明危害性:信息泄露、任意地址写入、可能实现代码执行(3分);(5) 提出正确的防御方法——硬编码格式字符串、使用 snprintf(1分)。若未说明 %n 的写入能力扣2分;若未区分 sprintf/snprintf 扣1分。",
|
||
"explanation": "格式化字符串漏洞是经典的C/C++安全问题,常见于将用户输入直接作为 printf 系列函数的第一个参数。虽然现代编译器(如 GCC 的 -Wformat-security)会对此发出警告,但该漏洞在遗留代码中仍然广泛存在。snprintf 是 sprintf 的安全替代,但 snprintf 本身不能防御格式化字符串攻击——它只防止缓冲区溢出。理解这些函数族的安全特性差异对于编写安全的C程序至关重要。",
|
||
"source": null,
|
||
"related": []
|
||
}
|
||
]
|
||
} |