尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

奇安信安全开发笔试复盘:安全思维与编程实战全解析

奇安信安全开发笔试复盘:安全思维与编程实战全解析 2019年春招那阵子我把大部分精力都花在刷安全类公司的笔试题上。奇安信的这套卷子给我留下的印象格外深——不是说它有多难而是出题思路和普通互联网公司差异很明显算法题之外它更看重你有没有“安全思维”这根弦。这套卷子我顺利过了笔试后来进入面试多年来陆陆续续有学弟学妹来问干脆整理成一篇完整的复盘。准备投安全研发、安全运营方向的同学可以把它当成一份“模拟卷解析”来用。这套题总共六个模块单选、多选、简答、编程、以及一道附加的综合设计题。我按实际作答顺序从第一节开始拆解把每道题的考察意图、解题思路和现场踩过的坑都写出来。题目细节凭记忆复述个别数字可能有出入但考察点绝对是当年真实考过的。1. 这套卷子的整体布局岗位与题型的直接对应1.1 我投的方向和收到卷子的第一感觉我当年投的是奇安信的安全开发工程师方向笔试邮件里写明了岗位名称打开考试链接的瞬间其实心里有个预期一定会出现大量跟安全基础相关的内容同时编程题也会占不小比重。事实证明这个判断是对的。整张卷子没有一股脑堆算法题而是把安全基础、编码能力、综合分析混在一起考。我印象最深的是一道关于日志分析的附加题它不要求你写一行代码却比很多编程题更能筛掉人。这说明安全公司的笔试并不只是看你会不会写代码而是看你遇到真实安全场景时能不能理出分析链路。1.2 题型分布与分值权重凭我记忆这套题的卷面结构和分值占比大致是下面这样模块题量分值占比考察方向单选题15题20%网络协议、操作系统、Web安全基础多选题10题20%加密算法、Linux命令、日志分析简答题4题30%漏洞原理与防御、安全编码规范编程题3题30%字符串处理、滑动窗口、二叉树综合设计题1题加分项安全日志分析、攻击链梳理这个分布给我一个很直接的信号单选和多选只是门槛真正拉开差距的是简答题和编程题。事实也如此很多人在多选题上纠结太久最后编程题来不及做。1.3 时间分配上的失误与建议我当时的失误在于多选部分。多选题的计分规则是“选错不得分少选得一半分”所以最稳妥的策略是“不确定的选项坚决不选”。但我一开始过于追求全对在几个模糊的选项上反复拉扯白白耗了十几分钟导致后面编程题时间紧张。如果你要参加类似笔试我建议时间这样切单选加多选控制在30分钟以内简答30分钟编程题60分钟最后留至少10到20分钟给附加题。附加题虽然写不完整但只要有一定程度的分析过程就比直接交白卷好得多。面试官后来告诉我阅卷时附加题并不是按标准答案判分的他们看的就是思维链路有没有形。2. 安全基础题不是背答案而是看底层逻辑2.1 Session和Cookie那道经典题卷子里有一道关于用户身份保持的单选题题目大概意思是一个Web系统在用户登录后用Session保持会话状态下面哪种说法是正确的。选项里混着不少经典的干扰项比如“Session是保存在客户端的信息”、“服务端可以直接从Cookie中读取用户密码”、“Cookie一旦被窃取攻击者就能伪造用户身份”。这道题表面上考Cookie和Session的区别本质考的是信任边界。Session状态必须保存在服务端客户端只保存一个Session ID。而Session ID一旦被窃取确实存在被伪造身份的风险所以需要配合有效期、HttpOnly、Secure等机制。我当时选的就是“Cookie中保存Session ID且该ID可以被窃取”这个判断是安全的。这里想提醒一下安全公司的选择题很少考“名词解释式记忆”而是把概念放进一个具体的漏洞或业务场景里让你判断哪种做法是安全的。如果只背“Session是服务端的Cookie是客户端的”遇到这种题目还是容易翻车。2.2 对称加密与非对称加密的对比多选题里有一道关于加密算法的题要求选出“正确的说法”。备选里涉及AES、DES、RSA、ECC以及“混合加密”的概念。这类题本身不难但特别容易混淆两个点第一对称加密加密速度快但密钥分发困难第二非对称加密可以解决密钥分发问题但性能开销大所以实际系统经常用混合加密——用RSA或ECC协商出会话密钥再用AES加密业务数据。还有一个高频混淆点数字证书。很多人会把“用CA公钥验签”和“用私钥加密”搞混。证书颁发时CA用自己的私钥对证书内容签名浏览器验证时用CA公钥验签。如果私钥被泄露等于整个信任链崩塌。安全检查里这也是一个常问的知识点。2.3 文件上传功能如何安全设计简答题里有一道“文件上传功能如何做好安全防护”的题目特别经典。我当时按自己的理解答了五六条后来看答案才发现漏了两个非常关键的点。一个完整的安全设计思路大概是扩展名白名单校验不要只靠前端JS一定要后端校验校验Content-Type和文件内容Magic Number防止改了扩展名就直接绕过限制文件大小避免超大文件拖垮存储随机化文件名和存储路径防止路径穿越上传目录禁止执行脚本这是阻断Webshell落地后执行的重要手段对图片类文件做二次渲染破坏可能夹在图像文件中的恶意载荷上传记录完整审计日志包括IP、文件名、上传时间尽量放在独立静态域和业务服务器隔离。我漏掉的就是“图片二次渲染”和“独立静态域”。这两个点都属于“实战中踩过坑才想得到”的类型书本上不一定有。3. 编程题实录字符串循环右移k位为什么我调了二十分钟3.1 原题描述与考察意图“给定一个字符串s和一个非负整数k将字符串循环右移k位。例如sabcdek2输出deabc。”这道题放在安全开发岗的卷子里并不突兀因为字符串处理是“协议解析、路径处理、加密数据封包”的底层能力。比如解析HTTP请求时经常需要把URL分段处理类似的移位、切片操作可以说无处不在。3.2 三种解法演进我现场写的是Python第一反应是切片。Python里字符串切片一行就能做到s[-k:] s[:-k]。但问题在于k如果大于字符串长度直接切就会出错必须先取模。如果不借助Python内置切片常见解法有两个。第一个是真模拟每次把最后一个字符移到最前面循环k次时间复杂度O(n*k)空间O(1)思路简单但效率低。第二个是三次反转先把整串反转再反转前k个字符再反转后面n-k个字符时间复杂度O(n)空间O(1)。以sabcdek2为例三次反转的过程是整体反转得到“edcba”反转前两个字符得到“decba”反转后三个字符得到“deabc”。这个思路我现场没有第一时间想到还是事后复盘才补上的。笔试现场最稳的还是切片加取模。3.3 边界条件k大于len(s)时怎么处理我当时在牛客的在线编译器上跑测试用例前两个例子都过了第三个例子就挂了。原因很简单sabcdek7正确结果是右移7位等价于右移2位输出“deabc”。我当时只处理了k刚好等于len(s)的情况没有处理k大于len(s)的情况。正确的处理方式很简单先判断字符串是否为空然后k % len(s)。如果不做取模字符串长度是5k是7s[-7:]在Python里不会报错但结果完全不对。还有一个隐藏边界k等于0时直接返回原字符串。有些写法没考虑这个在后续代码里会出现问题。3.4 现场代码和完整测试用例我后来整理出的标准写法def shift_right(s: str, k: int) - str: if not s: return s n len(s) k % n if k 0: return s return s[-k:] s[:-k]测试用例我用一个表格列出来笔试时不会要求写测试但你自己心里要有这个表输入输出说明sabcde, k2deabc常规右移sabcde, k5abcde右移一位字符数回到原串sabcde, k7deabc7 % 5 2sabcde, k0abcde不移动s, k3空串特殊处理sx, k100x单字符任意移位都相同这道题我为什么调了二十分钟原因很蠢我一开始把取模直接写成了判断if k len(s): k k - len(s)只减了一次。k是7时减去5得到2没问题但如果k是12减一次得到7还是大于5照样错。取模和“减一次”并不等价。这种低级失误平时刷题时很少遇到因为测试数据通常不会给那么极端的值但笔试环境下一紧张就暴露了。4. 算法题最长不重复子串从暴力到滑窗的推导4.1 题目和第一反应这道题就是LeetCode第3题的变体“给定字符串找出其中不含有重复字符的最长子串的长度。示例abcabcbb输出3bbbbb输出1pwwkew输出3。”放到安全笔试里考这道题我猜主要是因为滑动窗口思想在日常开发中很常用比如流量窗口统计、日志去重、协议字段解析等场景。它考的不仅仅是算法还有编码的严谨程度。我看到题目的第一反应就是暴力枚举因为这是最不容易出错、最容易写出正确答案的思路。先把所有子串枚举出来再去判断子串里是否有重复字符取最长长度。4.2 暴力法到底亏不亏我在笔试中一般不排斥先写暴力解因为能确保有产出。暴力法实现简单但问题也大枚举所有子串是O(n^2)每个子串判断是否有重复字符需要O(n)总复杂度O(n^3)。笔试给出的字符串长度如果到了10^5级别这种写法肯定超时。但暴力解可以作为“兜底方案”。在时间不够的情况下写出暴力解能拿一大半分比空着不写强得多。4.3 滑动窗口优化维护“当前窗口内字符的位置”优化思路很直观用一个左指针left和一个右指针right维护一个窗口窗口内所有字符都不重复。右指针不停向右扩展如果新字符在窗口内已经出现过就把左指针移动到那个重复字符的下一个位置。这里有个容易写错的地方用一个字典pos记录每个字符最近一次出现的下标。判断重复时不能只判断字符在不在字典里还必须判断它的位置是否在当前窗口内。也就是说如果这个字符上次出现的位置已经小于left说明它已经被移出窗口了不算重复。def length_of_longest_substring(s: str) - int: pos {} left 0 ans 0 for right, ch in enumerate(s): if ch in pos and pos[ch] left: left pos[ch] 1 pos[ch] right ans max(ans, right - left 1) return ans这段代码的精髓就是pos[ch] left这个判断。如果漏掉这个判断遇到字符重复出现但重复位置已经不在窗口内时left会被错误地拉回“旧位置”结果直接错掉。4.4 在线编译器里容易犯的错我现场写这道题时犯过两个错。第一个是忘记在更新字符位置时更新字典里的旧值导致后续判断永远读到旧位置。第二个是计算窗口长度时写成了right - left漏了加1——窗口包含left和right两个端点长度应该是right - left 1。还有同学喜欢用set实现滑动窗口每次移动left时从set里删除一个字符。这种写法逻辑上虽然正确但在删除时容易把顺序搞错比如重复字符并不在最左端时还需要循环删除直到把重复的那个字符删掉。相比之下用dict记录位置的方式更简洁也不容易出错。如果面试官现场追问“能不能输出最长子串本身”可以在循环里记录最终答案对应的left和right下标然后在最后切片返回。不要把路径处理埋进循环里容易把主逻辑搞乱。5. 密码学与编码题RSA手动计算的几个易错点5.1 一道很典型的RSA手算题简答题里有一道“给定两个大质数p7、q17取公钥e5求私钥d并计算明文m8加密后的密文c。”这道题放在安全笔试里一点都不突兀RSA是公钥密码体系的基石。它考察的是你对数论基础是否真正理解而不是能不能背出公式。5.2 完整的计算过程第一步计算n p * q 7 * 17 119。第二步计算欧拉函数phi(n) (p - 1) * (q - 1) 6 * 16 96。第三步选择e 5需要满足gcd(e, phi(n)) 1。5和96互质满足条件。第四步求d使d * e ≡ 1 (mod phi(n))也就是d * 5 ≡ 1 (mod 96)。可以用扩展欧几里得求解得到d 77。因为5 * 77 385385 mod 96 1。第五步加密c m^e mod n 8^5 mod 119。8^5 3276832768除以119等于275余43所以c 43。5.3 这些地方最容易算错第一个易错点是把“模反元素”算成负数。扩展欧几里得得到的第一步结果可能是负数要把它转换成模phi(n)范围内的正整数。第二个易错点是把phi(n)和n弄混。RSA的解密指数是基于phi(n)求模的不是基于n求模。第三个易错点是计算大幂次时硬算。日常笔试不会让真算几百位的RSA但手算8^5已经需要用一些技巧。更通用的办法是“模重复平方”把指数拆成二进制逐步平方并取模。这个方法在现场手算时特别好用。5.4 编码和加密的真正区别这张卷子还有一道关于编码的判断题“Base64是加密算法吗”答案当然是否定的。Base64、URL编码、Hex编码都只是“数据表示方式”它们不提供机密性只要拿到编码后的数据解码就能还原原文没有任何密钥参与。我当时还遇到一道Base64计算题字符串“abc123”经过Base64编码后是什么。要回答这个问题需要了解Base64的分组规则每3个字节一组转成4个Base64字符。如果字节数不是3的倍数末尾补等号。“abc123”刚好6个字符、两组编码结果是“YWJjMTIz”。这个知识点在安全场景里非常常见比如攻击流量里的编码payload、JWT结构、邮件附件编码都会用到Base64。不能识别编码和加密的区别在日志分析里很容易被表面现象带偏。6. 综合设计题给一份日志找出异常上传行为6.1 题目描述卷子最后有一道附加题场景是“某公司的Web服务器出现安全告警怀疑被上传了Webshell。现在提供一天内所有Nginx访问日志以及网站上传目录的记录请给出分析思路并输出可疑IP、可疑文件和攻击时间线。”这道题不要求写代码要求写分析报告。我现场写了一个多小时现在回想很多思路已经变成日常安全运营工作的基本操作了。6.2 我的分析链路我的第一步是粗筛。先用状态码过滤出200的POST请求因为上传通常是POST。然后从URL中筛选出上传接口关键字比如upload、file、filedata、attach等。第二步是看文件扩展名。把上传日志里后缀名列出来重点看.php、.jsp、.asp、.aspx、.ashx这类脚本文件。当然也要留意扩展名混淆比如大小写混合、双写后缀、在文件名里加空格或换行这些都是常见规避手法。第三步是看IP。按IP聚合统计同一个IP在短时间内的上传次数要是某个IP在十分钟内上传了十几个脚本文件基本可以直接标红。第四步是看User-Agent。普通浏览器的UA长度和格式相对稳定而很多自动化工具的UA要么是空值要么使用非常规的标识。这种“不同寻常的UA上传脚本接口”的组合可疑程度会直线上升。6.3 面试官点醒我的一个关键点我当时在报告里写了上面的分析链路自认为已经很全了。结果面试官问了一句“如果攻击者先上传一个图片文件图片里藏了脚本代码然后通过解析漏洞让这个图片被当作脚本执行你会怎么从日志里发现它”这个问题问得非常刁钻。它意味着不能只看“上传了脚本后缀”这种明显特征还要看“上传后的请求序列”上传一个.jpg文件随后短时间内又发起一个请求去访问这个.jpg并且这个访问返回了200同时响应时间明显变长这就非常可疑可能是在触发图片马解析。这类攻击的日志特征不是一个孤立请求而是多条日志组成的“序列”上传请求、触发解析请求、执行请求。分析员的任务是把这个序列从海量日志里“拼”出来。只看单条日志、只盯着Script后缀都会漏掉这类攻击。6.4 用脚本代替Excel手工筛选线上环境的访问日志动辄几个G不可能用Excel打开手工筛选。我自己的做法是写一个Python脚本先用awk把需要的字段拆出来再用Python做聚合统计。比如快速统计Top N的IP和Top N的上传路径import re from collections import Counter log_file access.log upload_counter Counter() ip_counter Counter() with open(log_file, r, encodingutf-8, errorsignore) as f: for line in f: parts line.split() if len(parts) 7: continue ip parts[0] method parts[5].strip() path parts[6] status parts[8] if len(parts) 8 else if method POST and upload in path.lower(): ip_counter[ip] 1 upload_counter[path] 1 print(Top 10 上传IP) for ip, cnt in ip_counter.most_common(10): print(f{ip} - {cnt}) print(Top 10 上传路径) for path, cnt in upload_counter.most_common(10): print(f{path} - {cnt})这段脚本的核心目的不是把问题彻底解决而是缩小可疑范围。真正的研判还是需要把缩小后的日志片段拉出来一条一条看时间线。这种分析思路在笔试附加题里非常加分因为它向阅卷人传递了一个信号你有真实环境的操作经验。7. 备考复盘安全公司笔试到底在挑什么人7.1 三个印象深刻的教训这套卷子做完我有三个特别明显的教训。第一个是多选题“宁少选不多选”。我记得有一道题问Linux日志分析的常用命令我特别确定grep和tail是对的但不确定awk算不算高频果断没有选awk。事后看答案awk确实也是正确答案之一但这种“不确定就不选”的策略保住了大部分分数。第二个是编程题先写暴力解再优化。我一开始直接想“最优解”在刚开考时浪费了不少时间。后来发现先写完暴力解存到编译器里即使后续优化失败也至少能保证有一版正确的代码可以提交。第三个是综合设计题一定要写“时间线”。面试时我看过一份高分样例他把攻击行为从“扫描探测”到“上传”到“执行”到“外连”拆成四个阶段每个阶段对应日志里的关键字。这比单纯列“可疑IP有哪些”要高级很多因为这说明他理解了攻击链。7.2 给准备参加安全类笔试的同学一份自查清单结合这套卷子的考察范围我列了一份“出门前自查”清单HTTP状态码的语义尤其是2xx、3xx、4xx、5xx以及什么场景下会出现302跳转常见请求头Cookie、Referer、Origin的作用以及CSRF和CORS的区别Session和Cookie的存储边界Token和JWT的区别对称加密和非对称加密的适用场景RSA流程能手动推导Base64、URL编码、Hex编码能快速识别Linux常用命令grep、awk、tail、sort、uniq能做日志聚合能画出文件上传攻击的完整时间线而不是只答“检查扩展名”编程题至少练熟字符串类、滑动窗口、链表反转、二叉树层序遍历。如果你发现自己有哪一项是空白笔试前一定要补上。安全类笔试的特点是“知识点不偏但组合很灵活”它更考验你把几个基础概念连成一条链的能力。7.3 一段写在最后的话这套题给我最大的影响不是让我拿到了面试机会而是让我重新理解了安全研发岗的日常你真的需要懂Web原理才能写出安全的接口真的需要懂日志分析才能定位线上问题真的需要懂RSA和编码才能解读协议数据。笔试不是背题目而是提前体验这个岗位每天都在做什么。标题既然挂了“一”说明这套卷子后面还有不少值得展开的内容如果大家需要我会继续把多选题里的加密算法题、二叉树层序遍历变体以及SQL注入攻击链设计的复盘整理出来。
返回列表