ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

安全开发工程师校招笔试:从漏洞修复到安全编码全解析

2026/8/31 18:55:42 拓冰建站 浏览量
安全开发工程师校招笔试:从漏洞修复到安全编码全解析 2018年秋季我投了美丽联合的信息安全开发工程师岗位笔试完走出考场的时候我最大的感受是这不是一份传统意义上的渗透测试卷子更像一份“带着安全意识的开发真题”。当时我对安全岗位的想象还停留在“挖洞、打CTF、写exp”但真正坐到考场里打开试卷之后才发现这份试卷考的东西跟我想象的完全不一样它不要求你掌握多冷门的利用链也不考花式的渗透技巧反而把大量分值放在HTTP协议、编码习惯、漏洞的修复方案甚至还有一道“修复我给你的有漏洞代码”的编程题。后来我顺利进入了安全开发的方向回头看这份试卷其实它非常清晰地画出了这个岗位的能力画像首先是工程师然后才是安全工程师。这篇文章就结合这份试卷的考点分布、典型题目和我的备考、失分经历聊聊安全开发工程师校招笔试到底在考什么。1. 从试卷结构看安全开发岗位的定位1.1 安全开发岗和渗透测试岗的试卷差异我先说一个很多人容易误解的点安全开发工程师笔试和渗透测试工程师笔试是完全两套出题逻辑。渗透测试岗更喜欢考信息收集、漏洞利用、内网横向、权限维持题型里大量出现“这个漏洞怎么打”“给出利用方式”。而安全开发岗的试卷更像“软件工程师试卷安全基础知识”它默认你首先能写代码其次再谈安全。美丽联合这份试卷整体给我留下的印象是客观题大概占50%简答/分析题占30%编程题占20%但即使是客观题也多数在问“下列哪种写法能防御XX攻击”而不是“下列哪个工具有XX功能”。这个出题逻辑背后是岗位的日常工作。安全开发工程师通常要做SDL、安全中间件、风控系统、代码审计平台、加解密服务也可能要写业务安全接口比如登录保护、短信防刷、内容安全过滤。你不是一个只在项目上线前做一次渗透的“外挂”而是要和业务研发并行把安全能力嵌入到每一行代码里。所以笔试必须首先筛选出代码功底扎实的人然后再看你有没有安全直觉。我当时最大的教训是用了大量时间刷CTF Web题但对HTTPS握手过程、对称加密和非对称加密的适用场景这类基础题却模棱两可。结果试卷前面一大块基础题做得并不顺畅。后来才明白安全开发笔试考察的是“稳定输出”而不是“某个瞬间的灵感”。1.2 为什么试卷里有一半题目在考开发基础考完复盘时我数了一下这份试卷里纯安全知识题大概只占一半剩下的是编程语言基础、数据结构、操作系统、网络协议这些常规开发岗题。很多人不理解安全开发为什么要考链表反转为什么要考进程和线程区别我在笔试时也嘀咕过。工作一段时间之后才想明白安全开发工程师日常要做代码审计你必须足够熟悉常见语言的特性和坑才能发现别人代码里的安全隐患而做安全应急响应时你要能快速定位到进程、端口、日志文件离不开操作系统和网络基础。从招聘方角度也很好理解。美丽联合这类电商公司安全团队要支撑的业务链路很长从用户注册、登录、下单、支付到营销活动每一个环节都有安全风险。如果只招一个只会打流行的洞而不会写生产代码的人进来之后既读不懂业务代码又没法跟研发有效协作会非常痛苦。所以试卷宁可把标准定在“合格的开发有安全意识”也不希望招一个“精通利用但完全没有工程能力”的人。除此之外安全开发岗的同学还要经常跟运维打交道处理线上告警、加固服务器、排查入侵痕迹。这些工作对Linux命令、网络协议、数据库操作的熟练度要求非常高。试卷里考Linux端口查看和日志查找其实就是在提前筛查你有没有真实接触过服务器而不是只会在本地虚拟机里跑跑工具。2. 基础题安全开发工程师必须“秒答”的知识点2.1 HTTP与Web基础几乎每年必考这份试卷开头就是一批Web基础选择题覆盖了HTTP请求方法、状态码含义、Cookie和Session区别、同源策略、常见的请求头Referer、Origin、X-Forwarded-For等。这些内容看起来简单但却是安全开发的基石。比如同源策略它决定了跨域请求能不能携带Cookie很多CSRF和CORS配置问题能不能利用都跟同源策略的边界理解有关。再比如X-Forwarded-For后端如果直接用这个头来获取客户端IP做风控那攻击者完全可以自己伪造请求头绕过这类问题在我后面做风控系统时几乎每周都能遇到。我建议准备这类题目不要死记硬背而是把每个知识点串成一条线一次完整的HTTP请求从客户端发出到服务端处理完毕经过了哪些节点哪些东西可以被用户控制哪些头是代理服务器加的哪些头可以用代码伪造。这种理解方式不仅应对选择题后面做漏洞分析题也很有帮助。我整理了一个自己复习时反复看的表格分享出来给大家参考考点常见考查方式需要掌握的深度HTTP方法GET/POST/PUT/DELETE幂等性知道方法语义能判断哪些请求可能被滥用状态码301/302/401/403/502等能快速定位问题知道哪些状态码会绕过安全逻辑Cookie属性HttpOnly、Secure、SameSite能说明每个属性在什么攻击下起作用同源策略协议、域名、端口三者都相同能解释CORS和跨域请求的边界请求头伪造X-Forwarded-For、Referer、Origin知道哪些头可被客户端控制不能直接信任到这里要特别强调一个笔试高频坑Referer和Origin在CSRF防护里经常被提到但Referer有时会因为隐私策略被浏览器去掉所以严谨的方案通常会两者结合或者直接使用CSRF Token。如果你能在答案里提到这一层阅卷人会认为你真正遇到过线上问题。2.2 密码学常识不是让你实现算法而是知道怎么用密码学在安全开发笔试中占比很稳定。那次考试里我印象很深的一道题是对比对称加密、非对称加密和哈希算法的区别并给出一个实际使用场景。这道题表面在考概念实际上刷掉了很多只知道AES、RSA名词但不知道选型的人。安全开发工程师不是密码学专家但要能判断什么场景该用AES-GCM而不是ECB什么时候该用RSA加密而不是直接用SHA-256保存用户密码以及JWT用HS256和RS256分别意味着什么。这里展开说一下实际工作中最常用的几个判断用户密码存储绝不能存明文或简单的MD5应该用加盐的慢哈希算法比如bcrypt、scrypt或argon2。加盐的目的在于避免相同密码产生相同哈希值防止彩虹表直接命中。数据完整性校验用HMAC而不是普通哈希。HMAC带有一个密钥能防止攻击者在不知道密钥的情况下篡改数据和重算校验值。接口传输加密实际项目通常不会单纯用RSA加密整段数据因为非对称加密慢且有长度限制。常见做法是用RSA或ECDH交换对称密钥随后用AES-GCM这类对称加密算法传输数据这就是混合加密体系。笔试如果考到“如何设计一个安全的登录接口”一般都会涉及密码哈希和会话管理。我建议在答案里不要只写“用bcrypt”还要提到破解防护比如限制登录失败次数、加入验证码、对异常IP做风控。这些点组合起来才能体现你是从工程角度思考而不是单纯背了一个算法名。2.3 Linux与网络基础别在送分题上丢分第三块基础题是Linux命令和网络常识。常见的有查看端口监听用什么命令、如何查找占用8080端口的进程、iptables规则如何写、如何查看系统日志网络方面则会考TCP三次握手、常见的端口号22、80、443、3306、6379等、DNS解析过程。这类题对做过实际部署的人非常简单但对只刷题库的人来说容易记混。安全开发工程师写一个加固脚本、排查一个入侵痕迹、定位一个服务异常都会用到这些命令。比如日志审计你要去/var/log下找nginx的access.log、mysql的慢查询日志还要通过journalctl查看systemd服务的输出这些操作如果只靠背命令但不知道日志文件放哪里实际工作中也会卡壳。所以笔试出现这种题本质上是在确认你有没有真实接触过服务器。我个人的建议是备考时一定要亲自动手搭一个Linux虚拟机把Nginx、MySQL、Redis装一遍然后模拟部署一个Web应用。期间练习几个核心命令netstat -tlnp看端口、ps aux看进程、ss -tlnp替代netstat、lsof -i:8080查端口占用、tail -f看实时日志、grep过滤关键词。这些命令不复杂但能确保你在笔试中写答案时不会卡壳也能给面试官留下“可落地”的印象。3. 应用安全题考察的不是POC而是漏洞修复能力3.1 SQL注入的修复思路从拼接参数到预编译应用安全题是这份试卷的重头戏。其中SQL注入是必考项。但它的考法不是让你提交一个payload而是给你一段JDBC或MyBatis的代码问你是否存在注入风险如果存在怎么改。我当时看到这种题还挺意外因为平时练的都是“构造注入语句拿到数据库内容”很少去想在业务代码里怎么修。正确的修复思路无外乎三种预编译PreparedStatement、参数化查询、对动态拼接做严格白名单校验。笔试里最稳妥的答案是首选预编译。比如在Java中使用?占位符绑定参数而不是用字符串拼接SQL。下面我用一段简化的伪代码说明// 有问题直接拼接用户输入 String sql SELECT * FROM users WHERE username username ; // 修复后使用PreparedStatement String sql SELECT * FROM users WHERE username?; PreparedStatement pstmt conn.prepareStatement(sql); pstmt.setString(1, username); ResultSet rs pstmt.executeQuery();在MyBatis里则要警惕${}的使用因为${}是直接拼进SQL的很容易产生注入通常情况下应该用#{}。如果确实需要动态表名、排序字段那也一定要做白名单映射而不是直接引用前端传来的字段名。比如排序字段只允许asc或desc表名只能从枚举中取值。很多人在笔试时还会纠结“是不是还要对输入做特殊字符过滤”。我的建议是预编译已经能解决绝大多数SQL注入问题再加一层过滤属于纵深防御但如果只是简单替换单引号反而可能破坏业务数据的正确性。所以答案里可以把过滤作为辅助措施但核心必须落在参数化查询上。3.2 XSS与CSRF一个讲输出转义一个讲请求校验XSS和CSRF往往放在一起考但很多人在笔试时会把两者搞混。XSS的核心是攻击者往页面里注入了脚本所以防御重点在输出编码和输入过滤CSRF的核心是浏览器自动携带身份凭证让服务端以为请求来自用户本人所以防御重点在请求来源校验、CSRF Token、SameSite Cookie。我建议大家写答案时先写清楚区别再各自展开这样阅卷人会觉得你是真的理解而不是背模板。实际笔试中XSS可能会给你一段前端模板让你找问题。比如用innerHTML拼接用户输入或者给某个URL参数直接赋值到href属性。修复时要注意上下文在HTML标签内、属性内、JavaScript字符串内、CSS内编码方式各不相同。这里有一个容易被忽略的点富文本场景下你不能直接转义所有HTML而应该用白名单过滤标签和属性比如允许b、a但去掉onclick、javascript:等危险内容。CSRF的修复则经常要你分析一个请求的防护方案比如转账接口。修复思路包括验证Referer是否来自本站、校验请求中是否携带随机Token、给关键Cookie加SameSite属性。如果再进阶一点可以提一下在Java Spring Security中CSRF过滤器是怎么工作的。它的核心机制是在渲染表单时注入一个隐藏的_csrf字段表单提交时后端会比较Session中的值。对AJAX请求则需要在请求头中携带Token。笔试时如果你能把这些细节写出来会比只写“加Token”专业很多。3.3 越权与SSRF开发者最容易忽略的边界除了Web三大经典这份试卷还考了越权和SSRF。越权题通常会给你一个订单详情接口/api/order?id123然后问你能怎么攻击怎么修。水平越权的修复核心是服务端重新判断资源归属不能只信任请求参数里的订单ID而要从登录态中获取当前用户ID再校验该订单是否属于当前用户。垂直越权的修复则依赖权限控制框架和接口级别的鉴权注解比如Spring Security中的PreAuthorize。越权漏洞经常被开发同学忽略是因为很多人在编码时默认“前端看不到删除按钮用户就不会操作”但攻击者完全可以直接构造请求。所以笔试时你要特别强调前端控制只是体验优化真正的权限判断必须在后端完成。SSRF的考点主要是URL可以被攻击者控制时服务端会去请求任意内网地址导致内网探测和攻击。修复思路包括过滤IP拒绝私网地址和环回地址、限制请求的协议和端口、使用统一的HTTP客户端的SSRF防护组件。很多公司会在代码里实现一个安全请求库底层做掉这些限制。笔试如果让你写修复方案能把“校验目标地址是否合法、禁止重定向后再次请求内网地址、用白名单域名”这几点写上就能拿大部分分。这里还要提醒一个进阶点DNS解析也可能被用作绕过比如一个域名解析到内网IP而不是直接在URL里写127.0.0.1。因此完善的SSRF防护通常需要二次解析校验甚至在建立连接后再次验证对端IP。能在笔试中写出这一点说明你确实踩过坑。4. 编码题笔试里最常见的“给漏洞代码修bug”模式4.1 一段有问题的登录代码长什么样编程题是安全开发笔试里最直接拉开差距的部分。美丽联合这份试卷我记得有一道登录接口的代码分析代码片段大致是一个POST接口接收username和password然后从MySQL查询用户信息并校验密码整体逻辑看起来没有任何报错但至少有三个安全隐患SQL注入、明文密码校验、登录错误提示信息泄露了用户是否存在。这种题非常贴近实际因为登录接口是所有业务系统最核心的入口也是最容易成为攻击目标的地方。下面我用Python Flask写一个简化版本方便大家理解我当时看到的代码结构app.route(/api/login, methods[POST]) def login(): username request.json.get(username) password request.json.get(password) sql SELECT * FROM users WHERE username%s AND password%s % (username, password) user db.execute(sql).fetchone() if user: return login success else: return username or password error这段代码在笔试中出现频率极高。它的问题一眼就能看出来SQL语句直接拼接了用户输入密码以明文存储并直接比对返回信息区分了“用户不存在”和“密码错误”相当于把系统的用户枚举漏洞直接暴露给攻击者。笔试要求你修复本质上就是在考察你有没有真实写过安全的后端接口。4.2 修复思路与评分点修复版本应该至少做到使用参数化查询避免SQL注入、对密码做哈希后与数据库中的密文比对、统一登录错误提示、增加登录频率限制。如果题目还要求返回一个会话标识那还要考虑Session的固定攻击防护和Cookie安全属性。阅卷时通常是按点给分每个安全点都能拿到对应分数写清楚比堆代码更有效。我给大家一个相对完整的修复代码示例app.route(/api/login, methods[POST]) def login(): username request.json.get(username) password request.json.get(password) user db.execute( SELECT id, username, password_hash FROM users WHERE username?, (username,) ).fetchone() if user and check_password_hash(user.password_hash, password): session[user_id] user.id session.permanent True return login success # 统一错误信息避免用户枚举 return invalid username or password需要注意几个细节第一查询只根据username定位用户密码校验放在应用层第二使用check_password_hash底层是加盐哈希第三错误信息统一定为“invalid username or password”不存在用户名和密码错误分开提示。再加上登录次数限制这个接口的安全强度就高很多了。在回答这类题时我建议把“发现问题、分析原因、给出修复代码、补充测试场景”四步走结构写清楚。你不需要把整个接口写得完美无缺但一定要让阅卷人看到你有系统性的安全思考。比如修复SQL注入时不仅改这一行还要在数据访问层统一使用预编译修复密码明文时不仅加个哈希函数还要提到加盐和选择合适的哈希算法。4.3 安全编码习惯如何在笔试中体现这道题反映出的其实是一个优秀安全开发工程师的日常看到任何一段代码时先下意识找数据流入口和信任边界对用户输入完全不信任对输出和存储都按不安全场景处理。这种习惯在笔试中会体现在你的答案注释里。比如修复代码时你可以用注释写清楚“这里原本可被SQL注入已改为参数化查询”这既是给自己梳理思路也是让阅卷人看到你的判断过程。编程语言上安全开发笔试大部分时候不会限制语言但Java和Python是出现频率最高的。建议备考时把这两种语言最常见的Web开发框架的写安全问题都过一遍比如Java的Spring Boot、Python的Flask/Django。知道它们默认的防注入机制是什么、默认的Session存储方式是什么、默认的CSRF保护是否开启这些细节往往就是笔试里拉开差距的关键。我后来在带校招生时也会做类似的测试发现能写出“先分析风险点再给出修复代码”的同学往往在实际工作中也更擅长代码审计和上下线安全评审。因为这背后体现的是结构性思维而不只是会背某个漏洞的利用方式。所以在笔试复习阶段建议养成一个习惯每看到一个漏洞都问自己一句“如果我在代码里遇到了我会怎么改”。5. 拉开差距的附加题安全方案设计与逻辑漏洞挖掘5.1 给一个电商订单系统设计安全方案这份试卷的最后一题是一道综合设计题大概意思是有一个类似美丽联合的电商平台用户下单支付全流程请设计一套安全方案。这种开放式问题没有标准答案但恰恰是最能体现工程能力的一道题。只答“加个验证码、做数据加密”肯定不够要分层去设计。我当时是按照“客户端→网关/接入层→应用层→数据库层”的链路来写后来工作后复盘这个思路是对的。接入层要做HTTPS强制、WAF策略、IP风控、频率限制应用层要做参数校验、权限校验、业务防重、支付回调签名数据层要做敏感字段加密、数据库审计、备份恢复。同时还要考虑安全运维比如日志要留够、异常要有告警、密钥要统一管理。如果能画一条完整的链路再在每个节点标出具体的安全措施这道题基本就稳了。为了更直观我列了一个简化版的安全设计表层次面临的主要威胁对应安全措施接入层恶意扫描、CC攻击、爬虫WAF、IP频率限制、行为验证码应用层越权、逻辑漏洞、注入参数校验、鉴权、防重幂等业务层优惠券套利、短信轰炸风控规则、配额限制、异步审核数据层数据泄露、弱口令敏感字段加密、最小权限、审计日志这里的关键不是把所有方案堆上去而是每写一个安全措施都要说清楚它对应什么威胁。比如“支付回调接口必须验证签名并且校验订单金额和回调金额是否一致”这就比“做好支付安全”具体得多。阅卷人看到这种答案会觉得你真的理解电商系统的风险在哪里。5.2 逻辑漏洞案例分析优惠券、越权、验证码除了安全方案很多公司还会出一两道逻辑漏洞题。电商业务最容易出问题的链路就是营销和支付优惠券是否可以重复领取是否可以叠加使用下单数量是否可以超卖支付回调是否可以重复通知订单状态是否可以跳步更新。这些逻辑漏洞没有统一的规则但笔试考核的是“如果我要攻击这个系统我会从哪个环节下手”的思维。举个例子一个优惠券接口用户点击领取后只判断“是否已领取”但同一个用户可以通过并发请求绕过前端置灰状态产生大量同时到达的领取请求。修复方案往往不是单纯加锁而是用数据库唯一约束或者Redis的SETNX做幂等。再比如重置密码短信验证码如果不绑定会话且不限次数攻击者可以直接遍历。这类题的答案重点在于能不能想到并发和幂等。我在笔试时遇到过一道具体的逻辑漏洞题支付成功后返回success但系统在更新订单状态之前先发送了通知消息。如果消息队列重复投递订单状态被更新两次就可能出现“一单多扣”或“多发一次货”。修复方案是在消费端做幂等用订单号加一个去重表重复消息直接丢弃。这个场景在校招笔试里出现其实是在考察你有没有分布式系统的基础认知。5.3 如何组织答案才能拿到高分综合设计题的回答一定要有结构。我建议用“威胁模型对应控制措施”的方式先列可能存在的威胁再针对威胁写控制方案。威胁可以从外部攻击者、内部恶意用户、数据泄露、业务异常等角度列举控制措施要落到具体技术比如“为了防止短信轰炸用Redis记录手机号维度每分钟发送次数上限5次”。这种回答方式比泛泛而谈“我们要做好安全”要专业得多。另外开放式问题要敢于写自己熟悉的东西不要什么都写但写不深。阅卷人通常能看出你到底有没有实操经验。如果真的做过某个安全组件哪怕是很小的功能也可以多展开比如“我在学校项目里实现过登录防爆破模块用的是滑动窗口计数器”这比背十种安全产品效果更好。还要注意时间分配。综合设计题放在最后分值不一定是最高但一定不能空着。哪怕时间只剩15分钟也要先写一个分层的框架把最容易得分的安全措施填进去比如HTTPS、参数校验、越权校验、日志审计这四个点可以快速写完然后有余力再扩展。千万不要小看这些“常识性”答案它至少证明你有完整的工程视野。6. 基于这套试卷的备考路线与避坑指南6.1 三个月备考路线基础、刷题、实践把这份试卷研究明白后我的备考路线大致分成了三个阶段。第一个月补基础重点看HTTP协议、计算机网络、操作系统、数据库原理和常用开发框架目标是能把一个请求从浏览器到数据库的完整流程讲清楚而且在每个环节都能指出哪里可能被攻击。第二个月刷安全专项包括OWASP Top 10、常见漏洞的原理和防御、密码学基础以及大量笔试题不只是背答案而是自己要能写修复代码。第三个月做综合练习找一些开源项目做代码审计尝试提交漏洞报告同时每天花一小时做算法题保持手感。关于参考书和资料我当年用到的有《Web安全深度剖析》《白帽子讲Web安全》、OWASP官方文档和各类安全公众号的笔试题解析。这里要特别提醒现在网上能搜到的“安全开发工程师笔试”资源其实不多更有效的方式是直接拿一些开源电商项目做代码审计比如找一个小型Java或Python项目用IDE搜索SQL拼接、文件上传、反序列化等风险点然后尝试修复。这个过程既能锻炼代码阅读能力又能积累真实案例面试时还能当项目经历讲。6.2 笔试现场的答题策略这里分享一些我自己的考场经验。首先发下试卷后先浏览一遍全卷把会做的题目先做掉不会的标记出来不要在选择题上纠结太久。其次编程题不要一上来就写代码先把思路写在草稿纸上包括要修哪几个点每修一个点对应的漏洞是什么。最后开放题一定要写满哪怕思路不成熟有结构、有层次的回答也比空白好得多因为安全方案设计题考的就是思路不是标准答案。另外做题时要有“按点得分”的意识。比如让你解释CSRF的防御方案至少写出Token校验、同源校验、SameSite Cookie三个点每个点都能得分。如果只写一个“用Token”即使方向对了也可能因为覆盖不全丢分。宁可多列几个措施也不要只写一个“标准答案”因为安全本来就不是单点防御。还要注意字体和时间管理。有些同学在编程题上写了一大堆思路但代码淹没在文字里阅卷人很难快速找到关键点。我建议代码单独放在一个块里前面用一句话说清楚改了什么比如“修复点参数化查询防止SQL注入”这样阅卷效率会高很多。6.3 我自己当年失分的地方希望你别再踩我在那次笔试中失分最多的不是最后的方案设计反而是最前面的密码学选择题和程序员容易忽略的Cookie属性。原因是我当时把大量时间花在CTF的题目上觉得“这才是安全”忽略了对基础概念的准确掌握。后来做面试复盘时我才意识到安全开发岗位的笔试从来不是为了筛选“最会PWN的人”而是为了筛选“最能让业务代码安全落地的人”。如果你现在也在准备类似的校招笔试希望你能把一半的精力放在工程基础上多写代码、多看开源框架的源码对任何漏洞的认识都落到修复本身。这个思路在后来的工作中也一直帮到我也希望对你有所帮助。最后再分享一个小技巧笔试结束后不管感觉好坏都把题目回忆一遍尤其是那些你不确定的知识点回来立刻查资料补上。这套试卷本身就是一份免费的复习提纲把它吃透比刷十套同类题都有用。我当时就是把错题整理成一个文档后来面试时还遇到好几个类似的问题直接就把答案顺出来了。如果你也在准备信息安全开发方向的校招不妨用这个思路来对待每一次笔试会有意想不到的收获。