Python 安全编码的基本原则

eval() 和 exec() 在生产环境几乎总该禁用,因其会执行任意字符串代码,导致远程命令执行等严重风险;应改用 ast.literal_eval()、白名单映射或 json.loads() 配合严格校验。

为什么 eval()exec() 在生产环境几乎总该禁用

因为它们会直接执行任意字符串代码,只要输入可控(比如来自 HTTP 请求、配置文件、数据库字段),攻击者就能执行系统命令、读取敏感文件、甚至反向连接控制服务器。

常见错误现象:eval("os.system('id')") 看似无害,但一旦字符串含用户输入,就等同于把 shell 交出去;Django 或 Flask 中用 eval(request.args.get('expr')) 是高危模式。

  • 替代方案优先用 ast.literal_eval() —— 它只允许基本字面量(dictliststrint 等),拒绝函数调用和变量引用
  • 真需要动态逻辑,改用明确的白名单映射:比如把用户传的 "add" 映射到预定义的 lambda a,b: a+b 函数,而不是拼字符串再 eval
  • CI/CD 流程中可加静态检查:用 pygrepsemgrep 规则拦截 eval(exec(compile( 的调用

处理用户输入时,json.loads()eval() 安全,但仍有边界条件

json.loads() 不执行代码,是解析 JSON 字符串的标准方式,但它不等于“完全免疫”。问题出在解析后的数据怎么用。

使用场景:API 接收前端传来的 {"user_id": "123", "action": "delete"},你用 json.loads() 解析后,直接拿 data["user_id"] 去拼 SQL 查询?那就掉进注入坑了。

  • JSON 解析本身安全,但后续使用必须做类型校验:比如确认 user_idint 或符合 UUID 格式,不能是 "123; DROP TABLE users;"(虽然 JSON 语法不允许分号,但若你用错了格式或混用其他解析逻辑,风险仍在)
  • 避免把解析结果直接传给 subprocess.run()os.system() —— 即使值来自 JSON,也要过一遍 shlex.quote() 或改用参数化调用
  • 注意编码陷阱:如果请求头声明 Content-Type: application/json; charset=latin-1,而你用 UTF-8 解码,可能触发异常或绕过校验(虽少见,但在老旧网关或代理下真实存在)

sqlite3 时,为什么参数化查询不是可选项,而是唯一合法写法

因为 SQLite 的 execute() 方法支持两种参数风格:? 占位符(推荐)和 :name 命名占位符(也安全),但字符串格式化(%.format()、f-string)一律导致 SQL 注入。

网趣购物系统加强升级版

新版本程序更新主要体现在:完美整合BBS论坛程序,用户只须注册一个帐号,即可全站通用!采用目前流行的Flash滚动切换广告 变换形式多样,受人喜爱!在原有提供的5种在线支付基础上增加北京云网支付!对留言本重新进行编排,加入留言验证码,后台有留言审核开关对购物系统的前台进行了一处安全更新。在原有文字友情链接基础上,增加LOGO友情链接功能强大的6种在线支付方式可选,自由切换。对新闻列表进行了调整,

下载

错误示例:cursor.execute(f"SELECT * FROM users WHERE name = '{name}'") —— 只要 name"' OR 1=1 -- ",整张表就裸奔了。

  • 必须写成 cursor.execute("SELECT * FROM users WHERE name = ?", (name,)),注意元组单元素要加逗号
  • 不要试图“手动转义”:SQLite 没有通用的转义函数,sqlite3.escape_string() 不存在,自己写正则替换引号极易遗漏边界
  • 即使表名/列名需动态,也不能参数化(SQL 语法不允许),此时只能走白名单校验:if table_name not in ["users", "orders"]: raise ValueError

subprocess.run()shell=True 是什么情况下才敢开

几乎从不开。开 shell=True 意味着把整个字符串交给系统 shell 解析,所有 shell 特性(管道、重定向、变量展开、命令替换)全部激活 —— 用户输入哪怕一个 $PATH`whoami`,后果不可控。

典型踩坑:为了图方便写 subprocess.run(f"curl -s {url} | jq '.name'", shell=True),结果 url"https://api.com?x=`rm -rf /`"

  • 绝对安全写法:设 shell=False(默认值),把命令拆成列表:subprocess.run(["curl", "-s", url], capture_output=True)
  • 如果真要管道,用 Python 分步调用,或通过 subprocess.Popen 手动连接 stdoutstdin,不依赖 shell
  • 唯一可考虑 shell=True 的场景:脚本完全由运维写死、无任何外部输入、且运行在隔离容器内 —— 但这种需求本身就应该被质疑

最常被忽略的一点:安全不是某个函数的开关,而是数据流全程的约束。从 request body → JSON 解析 → 类型校验 → 数据库查询 → 外部命令调用,每一步的输出都可能是下一步的输入,任何一个环节松动,前面所有防御都归零。

相关推荐:

vivo浏览器怎么设置编码_vivo浏览器切换网页编码格式教程【详解】

vivo浏览器网页乱码需按顺序尝试五种方法:一、手动切换UTF-8/GBK/GB2312编码;二、清除缓存或数据;三、查看源码meta标签匹配声明编码;四、通过about:debug清空网站数据;五、用开发者工具执行document.charset='UTF-8'并刷新。 如果您在vivo浏览器中打开网页时发现文字显示为方块、问号或乱码字符,则很可能是浏览器当前采用的字符编码与网页实际使用的编码不...

Trae的Live Share实时协作编码功能和VS Code对比体验如何?

Trae与VS Code Live Share存在协议兼容性、同步模型、调试共享、加密机制及浏览器支持五方面差异:Trae或用私有代理、缺CRDT-OT混合同步、不共享调试状态、密钥分发非端到端、无浏览器协作能力。 ☞☞☞AI 智能聊天, 问答助手, AI 智能搜索, 多模态理解力帮你轻松跨越从0到1的创作门槛☜☜☜ 如果您在使用Trae编辑器时发现其Live Share实时协作功能与VS Cod...
· AI · 12464

UC浏览器怎么设置编码_UC浏览器设置网页字符编码教程【教程】

UC浏览器网页中文乱码应按五步解决:一、手动切换网页编码(UTF-8/GBK/GB2312);二、开启自动识别网页编码功能;三、清除缓存、历史及Cookies;四、关闭极速模式;五、检查并覆盖源码中错误的meta charset声明。 如果您在UC浏览器中打开网页时发现中文显示为方块、问号或乱码字符,则很可能是网页内容与浏览器当前识别的字符编码不匹配。以下是解决UC浏览器网页字符编码问题的具体操作...

Notepad++中文乱码怎么解决 Notepad++编码格式修改方法【技巧】

Notepad++中文乱码主因是编码不匹配,需先“以某编码”临时解析验证,再“转为UTF-8”真实转换,手动指定GBK等原始编码、命令行iconv批量处理、设置默认UTF-8编码可系统解决。 如果您在 Notepad++ 中打开文本文件时出现中文乱码、标点异常或符号显示为方块,通常是因为当前识别的编码与文件原始编码不匹配。以下是解决 Notepad++ 中文乱码问题的具体操作方法: 一、通过“以…...

如何在Python中为测试用例添加自定义标记_通过pytest.mark进行分类执行

pytest.mark 必须作为装饰器直接作用于测试函数或类,不可写在函数外部;可叠加多个标记,执行时用 -m "mark1 and mark2" 等布尔表达式筛选;未注册标记会触发警告,需在 pytest.ini 或 pyproject.toml 中声明以避免。 pytest.mark 能不能直接用在函数外面 不能。所有 pytest.mark 必须装饰在测试函数或类上,写在函数定义之外会报 S...
· Python · 183740

如何在Python中构建树状结构的递归生成器_使用yield from简化递归代码

yield from 在树遍历中省去了手动展开子生成器的繁琐与风险,自动处理委托调用、异常传播、StopIteration 捕获及协程方法转发,确保扁平化输出和行为一致性。 yield from 在树遍历中到底省了什么 直接说结论:yield from 不是语法糖,它把递归生成器的“委托调用”从手动循环 + yield 拆解成一条语句,避免了中间迭代器被提前耗尽、异常传播断裂、或 StopIter...
· Python · 183819

如何解决Python中的UnboundLocalError局部变量引用错误_使用global或nonlocal关键字声明

Python函数内同名变量报UnboundLocalError,因编译期将赋值变量标记为局部,读取在赋值前则出错;global用于模块级变量,nonlocal用于最近外层函数变量,二者不可混用且需提前声明。 为什么在函数里修改同名变量会报 UnboundLocalError Python 在编译函数时,只要看到某个变量在函数体内有赋值操作(哪怕只在 if 分支里),就会把它标记为局部变量。之后如果...
· Python · 115790

为什么Python脚本内存占用居高不下_使用objgraph与gc模块排查泄露

Python内存泄漏主因是对象被隐性持有而非未调gc.collect(),可用objgraph.show_growth()定位异常增长类型,再用gc.get_referrers()逆向追踪强引用源,并结合RSS监控与gc调试确认真实泄漏。 Python 脚本内存持续上涨,大概率不是“没调 gc.collect()”,而是对象根本没被识别为可回收——比如被全局容器悄悄持有、含 __del__ 的循环...
· Python · 1780