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 (基础)
59 lines
4.5 KiB
JSON
59 lines
4.5 KiB
JSON
{
|
|
"topic": "secure-coding",
|
|
"type": "code_reading",
|
|
"schema_version": "1.0.0",
|
|
"generated": "2026-09-17T00:00:00+08:00",
|
|
"questions": [
|
|
{
|
|
"id": "cr-001",
|
|
"type": "code_reading",
|
|
"difficulty": 2,
|
|
"tags": [
|
|
"安全编程",
|
|
"整数溢出",
|
|
"内存安全"
|
|
],
|
|
"question": "阅读以下C代码,回答问题。",
|
|
"code": "#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n\nvoid process_input(const char *user_input) {\n unsigned int len = strlen(user_input);\n // 检查长度是否合理\n if (len > 1024) {\n printf(\"Input too long!\\n\");\n return;\n }\n // 分配缓冲区:len + 1 用于存放结尾的 '\\0'\n char *buffer = (char *)malloc(len + 1);\n if (buffer == NULL) {\n printf(\"Memory allocation failed!\\n\");\n return;\n }\n strcpy(buffer, user_input);\n printf(\"Processed: %s\\n\", buffer);\n free(buffer);\n}\n\nint main(int argc, char *argv[]) {\n if (argc < 2) {\n printf(\"Usage: %s <input>\\n\", argv[0]);\n return 1;\n }\n process_input(argv[1]);\n return 0;\n}",
|
|
"language": "c",
|
|
"sub_questions": [
|
|
{
|
|
"index": 1,
|
|
"type": "single_choice",
|
|
"question": "当 user_input 的 strlen 返回值恰好为 SIZE_MAX(即 (size_t)-1)时,len + 1 的结果是什么?",
|
|
"options": {
|
|
"A": "0,因为无符号整数溢出后回绕到 0",
|
|
"B": "SIZE_MAX + 1 = 一个更大的数",
|
|
"C": "程序会崩溃",
|
|
"D": "编译器会报错"
|
|
},
|
|
"answer": "A",
|
|
"explanation": "unsigned int 在 C 语言中发生溢出时会进行模 2^N 回绕(wrap around)。当 len 为 SIZE_MAX 时,len + 1 回绕为 0。此时 malloc(0) 的行为是实现定义的——可能返回 NULL 或一个可 free 的指针,但分配的大小为 0 字节。后续 strcpy 会写入远超分配空间的数据,导致堆缓冲区溢出。"
|
|
},
|
|
{
|
|
"index": 2,
|
|
"type": "single_choice",
|
|
"question": "这段代码在上述溢出场景下,strcpy(buffer, user_input) 会导致什么后果?",
|
|
"options": {
|
|
"A": "正常复制,程序正常运行",
|
|
"B": "堆缓冲区溢出(heap buffer overflow),可能执行任意代码",
|
|
"C": "栈溢出",
|
|
"D": "只会影响 buffer 变量,不会影响其他数据"
|
|
},
|
|
"answer": "B",
|
|
"explanation": "当 len + 1 回绕为 0 时,malloc(0) 可能分配一个极小的内存块(或返回一个有效指针但大小为 0),而 user_input 的实际长度远超分配空间。strcpy 会将整个 user_input 复制到这个过小的缓冲区中,造成堆缓冲区溢出,可能覆盖堆上的其他数据结构,攻击者可利用此漏洞执行任意代码。"
|
|
},
|
|
{
|
|
"index": 3,
|
|
"type": "short_answer",
|
|
"question": "请修改 process_input 函数,修复其中存在的所有安全问题(至少指出并修复 2 个问题)。",
|
|
"answer": "修复方案应包括:\n1. 将 strlen 返回值类型改为 size_t(而非 unsigned int),避免类型截截断;\n2. 在 len + 1 运算前检查 len 是否等于 SIZE_MAX(或使用安全的加法函数如 __builtin_add_overflow / SafeInt),防止整数溢出回绕;\n3. 使用 strncpy 或 memcpy 替代 strcpy,限制拷贝长度;\n4. 检查 malloc 返回值后,对 buffer 大小为 0 的情况进行防御;\n5. 考虑使用 calloc 或更安全的内存分配函数。\n\n示例修复代码:\nvoid process_input(const char *user_input) {\n size_t len = strlen(user_input);\n if (len > 1024) { printf(\"Input too long!\\n\"); return; }\n if (len == SIZE_MAX) { printf(\"Invalid input length!\\n\"); return; }\n char *buffer = (char *)malloc(len + 1);\n if (buffer == NULL || len + 1 == 0) { printf(\"Allocation failed!\\n\"); return; }\n memcpy(buffer, user_input, len);\n buffer[len] = '\\0';\n printf(\"Processed: %s\\n\", buffer);\n free(buffer);\n}",
|
|
"explanation": "修复涉及多个层面:类型安全(size_t)、整数溢出检查(SIZE_MAX 边界)、安全的内存复制(memcpy 替代 strcpy)。这些都是安全编码的基本实践。"
|
|
}
|
|
],
|
|
"explanation": "此代码阅读题考察学生对整数溢出导致缓冲区溢出的安全漏洞理解,以及修复安全漏洞的能力。",
|
|
"source": null,
|
|
"related": []
|
|
}
|
|
]
|
|
} |