研发应用安全规范

研发应用安全规范
**1.**目的

确保在软件开发过程中应用了恰当的安全措施,以降低潜在的安全风险和漏洞。此规范为开发团队提供了一系列的标准和最佳实践,以确保在设计、编码和测试时充分考虑了安全性。

**2.**适用对象及范围

适用于各种类型的软件开发项目

**3.**安全准则

安全准则由三个总体目标来描述:

  • 秘密性(也被称为秘密),计算系统的内容只能被授权对象访问;
  • 完整性,内容只能被授权对象以被授权的方式所修改;
  • 可用性,内容可以被授权对象使用。该目标经常提到的反义词就是拒绝服务。

**4.**应用安全规范

为了加强对程序开发应用安全问题的控制,下述列举了几个方面的应用安全措施、原则和规范,是各种编程语言均要遵守的安全准则,也作为系统设计、各类评审、程序开发、安全核查、测试案例编写的依据。

4.1设计安全规范

  • 最小化原则。仅提供完成业务所需要的最少资源,包括功能、权限等;
  • 接入层和DB的物理环境必须分离。运行web的物理机器上不得同时安装存储数据DB;
  • 接入层不能直接访问DB,接入层不涉及业务逻辑,业务逻辑以中间层/逻辑层原子操作方式提供;
  • 敏感信息的通信协议建议采用加密协议(敏感信息:用户名/密码,短信内容,邮件内容等,防止被轻易破解);
  • COOKIE存放尽量少的信息,且存储非敏感信息,仅仅作为客户端的缓存作用。
  • 系统消息做频率限制、流量控制等措施 (内部系统之间,系统内部模块之间的消息通知);
  • 手机消息做频率限制、流量控制等措施 (下发消息到用户手机);
  • 频率限制要求至少对单个ID(手机号码等)、单个IP(用户外网IP)做一定时间内的访问次数限制,具体限制指标根据业务需要进行设定;
  • 站点登录管理界面不能对外公布;
  • web站点目录下的读写目录做好统一规划并分开,便于做统一权限和安全管理,控制黑客限制上传文件的目录,以及完全控制黑客获取webshell权限。

4.2编码安全

  • 登录和重要操作必须使用验证码(图片验证码或短信验证码) (登陆,自写短信,彩信,传真发送等);
  • 对于绑定外网IP的server需要做安全防御措施:
  • IP访问频率限制;
  • 用户访问频率限制;
  • 过载保护,拒绝超过服务器允许的连接上限阀值的请求;
  • 重要系统需要防止“connect后立即close”攻击;
  • 防止“connect后客户端不发包长期占用连接”攻击;
  • 防止“connect后客户端慢速发包长期占用连接”攻击;
  • 安全措施必须在网络接入层实现,及早发现,及时拦截和处理。避免攻击传播到server的业务逻辑层。(分层设计思想,异步处理思路);
  • 对于来自第三方的平台请求,服务端必须有身份认证机制(IP信赖、IP和密码约定);
  • 除非提供对外服务,server不能绑定外网IP;
  • 数据库侦听地址必须显式绑定在内部IP,无外网接口,也需要显式绑定;
  • 不允许没有校验用户登录状态就能执行用户私有请求的操作;
  • 不能信任从其它网元获取的参数,对于不能让用户修改的数据(如当前登陆的手机号码),需要使用Session机制进行安全控制;
  • 验证用户登录态(session期内)时,除了SSO调整外,还要验证用户IP是否变化,以防止URL被传播后在其它机器上重复执行;
  • 需要校验登录态的地方必须使用公司统一的session server接口进行session id的校验;
  • 对于从其它系统跳转而来的URL(例如SSO跳转URL)请求,必须对该URL参数进行全签名,保证服务器获取的信息未被篡改。URL的参数里也必须包含时间戳,服务端检查该URL是否超时;
  • 如果程序要求留有后门,必须在部门级评估、备案,且必须绑定内网IP。严禁为了方便测试或者活动在代码中直接写死手机号码,如果确实无法避免,必须经部门级评估,备案;
  • 防止SQL攻击,必须使用Escape函数过滤字符串Value值。严禁将底层错误直接显示给用户,造成表结构泄漏等危害 (错误提示重定向设计);
  • 程序严禁使用外部输入的数字、字符串做文件名、路径名、环境变量的一部分(无论读写) (外界输入不可控;太长内存溢出;本地程序无错误,后端处理系统溢出之类的风险);
  • 不得将外界用户输入串直接加入html文件、js脚本、xml文件、配置文件、模板文件;如因业务需要,必须在部门级评估、备案;
  • 后台程序必须对javascript语句进行过滤或转换;
  • 对于web页面的输入域,必须对输入的内容进行过滤处理,防止XSS跨站漏洞的产生;
  • 对于用户提交的字符内容,要做内容过滤,例如敏感字、不雅内容等(从必要性考虑政治,色情,暴力);
  • 开源软件的引入必须由引进人经过详细的安全风险评估,并明确告知应用范围,经部门室经理、总监审批同意后才可应用。开源代码请注意清理无效文件、危险文件,不要使用默认代码目录,否则很容易被暴力猜解获取URL登录地址。

4.3参数处理

使用其它系统传来的参数前,必须对参数值进行合法性检验,不能依赖于客户端的检查:

  • 对数据类型进行合法性检查,如仅能包含数字;仅能包含A-Z,a-z的字母;仅能包含数字与字母的组合;
  • 对数据长度合法性进行检查,接收到的参数值的长度是否超出了预期的范围,如:手机号码长度是否等于13(长度检查要注意中英文的单双字节的影响);
  • 参数的校验必须在服务端程序中进行,不能完全依赖客户端脚本检查;
  • 处理字符串协议时,对数值型参数必须校验合法性(是否为数字字符)后再进行转化(如atoi),校验转换后的数值必须判断在允许范围。

4.4客户端异常提示

  • 程序出错时专门打印错误页面。打印专门的错误页面时不得在错误页面中打印任何与程序结构、逻辑、数据、环境等有关的任何信息,如:不能直接将调用函数失败时返回的错误提示打印在错误页面上;
  • 打印错误页面时仅尽可能少的提示信息。在不影响业务,不影响用户体验感的前提下,打印尽可能少的错误提示信息,如果业务允许可以仅打印一个“系统繁忙,请稍后再试”的简单页面;
  • 对于用户恶意攻击,直接断开连接,或者以界面不友好方式迷惑攻击者,不留下被对方用于分析的线索。

4.5日志信息

  • 重要操作信息必须记录完整,能够完全重现用户操作,至少包含如下关键信息:时间(精确到毫秒)、流水号、用户编号(手机号码等)、用户操作IP、前端服务器IP、操作内容;
  • 运营环境严禁在日志中明文记录敏感信息。(个人敏感信息、系统敏感信息、业务敏感信息等;
  • 日志文件必须定期进行抽样检查和脱敏处理;
  • 控制日志文件的大小。必须采用滚动日志或其他方式保证日志文件不超过规定的大小(1-100M,建议值10M),日志需要定期归档、备份,防止日志文件夹过度膨胀影响性能;
  • 在保证准确的情况下尽量保证日志对于业务处理逻辑的完备性。记录了完备的交易和上下游(第三方接口)的信息,供系统查询和恢复数据以及用于异常跟踪和定位;
  • 异常造成的业务失败,必须单独按照固定格式记录,便于故障恢复和投诉处理;
  • 应用服务器如IIS、Tomcat自己产生的日志,这些日志要注意调整日志输出级别,避免输出过多信息,生产环境应保持在INFO级别以上,同时,有些应用服务器的日志是不会自动滚动的,如Tomcat的stdout.log,要避免拖慢服务器,需要用crontab设定计划任务进行按日分割;
  • 日志必须记录在专有的外网不能访问的目录,绝对不能放在能被外界List到的目录下,如Htdocs等。对于调试日志,建议如无特殊需要,应在生产环境中去掉,避免因此造成的信息泄漏,以及服务器性能下降等问题。

4.6密码与加密

  • 严禁在自己系统处理用户Login,必须采用公司统一的认证系统(session server)。如有特殊需要,需报部门技术总监审批备案后,方可实施;
  • 系统是否由于特殊性,没有采用Login进行登录,而是自行验证密码的。如有,必须增加频率限制和监控,必须有附加码校验等频率控制措施,且报部门技术总监审批备案后,方可实施;
  • 用户资料修改、校验密码、密码设置等敏感的地方必须有附加码校验;
  • 操作系统密码、数据库密码、后台管理密码不得明显包含用户帐户名或用户全名的一部分;长度至少为六个字符;包含来自以下四个类别中的三个的字符:英文大写字母、英文小写字母、10 个基本数字、非字母字符(!、$、#、%);
  • 动态原则。安全策略必须动态变化的,比如加密过程中使用的密钥,不能在所有的过程或者相当长的一段过程中使用同样的密钥,必须动态改变;
  • 签名、KEY的算法必须采用MD5等标准算法,不得自己臆造算法,加密密钥必须是同时包含数字、字母、特殊字符,8位以上的字符串。

4.7核心数据和重要数据

  • 用户数据、定购关系、业务数据等核心数据必须做备份,对于重要的数据必须做双机热备;
  • 对于用户隐私数据显示,如手机号码、身份证号码,应该采取部分信息用替代等方式,建议方式为后4位采用(业务有硬性要求除外)。

4.8客户端打包和插件升级

  • 安装包必须保证没有病毒、木马;
  • 开源服务器,如apache、lighttpd、memcached、tomcat、mysql、jboss等必须使用经运维裁剪和安全配置的安装包;
  • 需使用开源的开发库时,要从官网下载稳定的版本,并在部门级备案。(使用stable版,不要使用release版)。

4.9接口协议安全

参见《接口协议标准》

4.10数据库应用安全

  • 使用绑定变量的方式访问数据库;
  • 资源释放要配套,连接句柄,会话的打开和关闭要配套;
  • 数据库中存放的用户隐私数据需要脱敏处理;
  • 数据库中存放的密码,密钥等信息需要进行加密码,且符合相关安全标准;
  • 数据库需要定期升级,应使用不存在严重安全漏洞的安全版本;
  • 数据库所在的系统环境需要定期升级,以保证数据库环境安全。

4.11jsonp跨域安全

  • jsonp跨域访问的接口,必须针对接口进行合法性校验,如增加token校验、referer校验等;
  • 内网环境不建议使用jsonp跨域访问,建议设置反向代理实现访问;
  • 公网使用jsonp跨域访问,必须针对访问来源IP进行白名单校验。

4.12http跨域安全

  • http跨域访问的接口,必须针对接口进行合法性校验,如增加token校验、referer校验等;
  • 内网环境不建议使用http跨域访问,建议设置反向代理实现访问;
  • 公网使用跨域访问,必须针对访问来源进行白名单校验,如Access-Control-Allow-Origin指定白名单域名,不能设置为*。

**5.**应用系统开发安全

5.1安全原则

  • 保护最薄弱的环节原则:保护最易受攻击影响的部分;
  • 纵深防御原则:不同层面、不同角度之间需要相互配合;
  • 最小权限原则:只授予执行操作所需的最小权限;
  • 最小共享原则:使共享文件资源尽可能少;
  • 权限分离原则:授予不同用户所需的最小权限,并在它们之间形成相互制约的关系。

5.2需求管理阶段

  • 根据业务目标分析并制定系统安全目标;
  • 确认安全需求规格说明。

5.3系统设计阶段

  • 根据安全目标执行威胁建模,识别威胁和风险;
  • 根据威胁建模制定对应开发安全任务:
  • 确定安全体系架构,设计安全协议和安全接口;
  • 确定访问控制与身份鉴别机制,定义主体角色和权限;
  • 信息输入的安全过滤,信息输出的校验和控制;
  • 数据结构安全设计,选择加密方法和算法;
  • 确定敏感数据保护方法;
  • 内部处理逻辑安全设计;
  • 评估内部通信机制,确定完整性机制。

5.4系统实现阶段

  • 开发环境安全管理要求:
  • 软件系统开发、测试禁止在生产环境中进行;
  • 开发环境中的开发用机应进行统一安全配置及时进行系统补丁升级和漏洞修复;
  • 编码安全要求(后面会有详细讲解):
  • 遵循代码编写安全规范,根据代码编写安全规范以及安全设计方案进行系统开发;
  • 遵循通用安全编程准则,包括输入验证、缓存溢出、安全调用组件和程序编译等;
  • 遵循机密性要求,保护用户访问信息的机密性,严禁在客户端存放敏感数据;
  • 避免内存溢出,严格检查和验证输入输出信息等;
  • 遵循结构化异常处理机制,捕捉并处理程序异常,防止系统信息泄露
  • 遵循代码脆弱性防范要求,包括缓冲区溢出、SQL注入、跨站脚本攻击、XML注入攻击、HTTP HEAD注入等。
  • 开发流程安全要求:
  • 开发过程中应对阶段性开发成果进行有效管理;
  • 开发过程中应定期进行代码静态分析,使用代码审核工具对源代码进行检测,并报告源代码中存在的安全弱点;
  • 开发人员不得超越其规定权限进行开发,不得在程序中设置后门或恶意代码程序;
  • 开发过程中应阶段性对敏感数据的加密传输、加密存储、对外提供或展示前进行脱敏处理
  • 第三方组件/库安全版本审计要求:
  • 开发过程中应对开发依赖库、框架、组件、容器进行安全版本审计;
  • 使用依赖库审计工具OWASP-dependency-check辅助进行审计,按漏洞等级修复。“高危"及以上必须修复(不能升级修复的需要说明原因),优先级由高到低依次为:CRITICAL是“严重”,HIGH"高危”,MEDIUM"中危",LOW“低危”。 同级漏洞先修复存在远程执行漏洞的或对业务影响较小的组件;
  • 输出组件安全检查表,提交质量部(QA),QA人员对组件安全检查表进行审计,无“高”风险以上组件确认为符合安全求,特殊情况存在“高”风险以上组件的,需提供合理原因说明,并进行备案,定期组织相关人员对如上组件进行评审,评审不通过的需要及时更新升级。

5.5系统测试阶段

  • 测试内容应包括代码的安全测试和安全功能测试;
  • 代码的安全测试是指使用代码测试工具或渗透测试来识别代码的安全脆弱性,并应按照其提供的修复建议进行修复;
  • 安全功能测试主要包括身份认证和访问控制的功能测试;
  • 测试系统环境应尽可能模拟生产环境并与生产环境进行安全隔离;
  • 真实数据不得直接在测试环境中使用,须进行适当修改或屏蔽,在测试完成之后须立即从测试应用系统清除运行信息;
  • 测试人员编制安全测试方案,构造安全测试用例;
  • 验收测试不得由开发人员兼岗。

5.6系统上线阶段

  • 系统上线须在内部验收通过后进行;
  • 需进行上线前试运行,确认应用系统是否符合上线要求;
  • 上线成功后,记录上线的日期和内容;
  • 系统上线后需全面梳理与清理暴露面资产,按照最小化原则收敛暴露资产,消除 “无管理、无使用、无防护、无必要”四无暴露面资产。
  • 全面梳理清理防火墙策略,做好公网策略最小化管理;应确保每条策略落实到人,用途清晰,策略合规(如无维护端口开放公网、禁止any to any策略等);
  • 加强短板系统安全管理,对防护短板系统重点梳理;
  • 全面清理应用资产,对内外网所有应用资产,按APP、SDK、公众号、单页面、应用接口、WEB网站等类型进行梳理,摸清IP端口、URL链接、中间件、开发框架等信息,全面清理已下线、过期、无效、测试页面等,确保每条资产责任到人;
  • 重点关注已下线但未清理设备、无人防护小系统、支撑系统开放公网、历史旧系统问题;
  • 全面清理网站目录文件,做好访问权限控制。严禁在网站目录下存放网站源码、日志、账号密码、测试代码、项目资料等敏感信息文件,对于网站目录应按照最小化原则进行访问权限控制;
  • 开展数据安全风险排查整改:
  • 各部门需强化业务数据安全管理,按要求对敏感数据进行分类分级管理,确保业务数据安全可控。同时加强对涉敏人员的管理,提高涉敏人员的安全防护意识,强化对涉敏人员的操作审计工作,定期审计涉敏人员的数据访问记录;
  • 各部门应加强数据库安全防护,采取有效措施防范对数据库的攻击(如数据库密码设置为强口令、网站配置文件中禁止明文存储数据库账号密码信息、加强数据库异常登录请求的分析、发现疑似注入行为时应及时告警并添加记录备查) 。
  • 完成主机及应用系统账号全面梳理认领与清理,加强账号与敏感数据操作审计;
  • 完成主机账号梳理认领与清理工作,对全量账号进行梳理,对无用账号进行清理,确保主机账号100%责任到人。
  • 全面梳理应用系统账号,清除历史无用账号及离职人员账号,确保所有账号归属在职人员。
  • 严禁绕行4A行为,加强账号与敏感数据操作审计。
  • 禁止在GitHub、百度文库、公网邮箱、在线笔记等公网系统上存储工作相关信息及帐号密码,开展全面清查(可在搜索引擎查询邮箱、电话、系统名称等关键字),消除上述渠道中存储的工作信息;
  • 口令安全教育与监督检查,组织全员开展个人账号(邮箱、即时通讯、网盘)弱口令自查,提高口令强度,避免被盗号后获取个人信息,用于开展社会工程学攻击;上线强口令策略,建议全体员工修改统一认证及内部生产系统密码,避免与外部系统个人账号相同或相似。

5.7文档管理

  • 源代码的变更和版本发布进行统一控制,对程序资源库的任何修改、更新和发布都需代码管理员授权和批准;
  • 应指定专人妥善保管程序源代码及相关技术文档。

**6.**基本/特定语言安全规范

每种编程语言均有自己的语法和特色,以下列出了Java、C/C++、C#的特有安全规范。

6.1基本代码安全要求

6.1.1****输入验证

对函数入口参数的合法性和准确性进行检查,具体如下:

  • 在B/S环境下,应进行服务端的验证而不仅仅是客户端的验证(例如基于Javascript的验证)。通过在客户端和服务器之间放置一个代理服务器,可以很容易绕过客户端验证。有了代理服务器,攻击者可以在数据被客户端“验证”后修改数据(与“中间人”攻击类似);
  • 在实际的校验中,输入校验首先定义一个有效(可接受)的字符集,然后检查每个数据的字符是否在有效范围内。如果输入中包含无效的字符,应用程序应该返回错误页面并说明输入中包含无效字符。这样进行验证的原因是定义无效的字符集比较困难,并且一些不应该有效的字符通常不会被指出;
  • 另外,边界检查(例如字符串的最大长度)应该在字符有效性检查以前进行,边界分析可以防止大多数缓冲区溢出漏洞;
  • 从环境变量获得的数据也需要进行验证,同时避免在环境变量中存放敏感数据(例如密码)。

6.1.2****SQL语句

如果应用程序需要连接后端数据库,使用存储过程而不能在代码中使用SQL

语句,使用程序以外的嵌入在代码中的SQL语句调用特别危险,难以防止攻击者使用输入或者配置文件(由应用程序载入)来执行嵌入式的SQL攻击。当然,输入验证有助于缓解这种风险。

6.1.3****注释代码

当应用程序在实际环境中开始应用时,应该删除所有的注释代码。注释代码

是用来调试或者测试的,它们不是最终应用程序的一部分。无论如何应该在实际的环境中删除它们以避免意外的执行(一般注释标识被删除后就无法激活休眠的代码,但还是存在可能性的,所以强烈建议执行这项工作)。

6.1.4****错误消息

所有为用户显示的错误信息都不应该暴露任何关于系统、网络或应用程序的

敏感信息,应给用户提供统一包装过的错误提示。

6.1.5****URL内容

对于Web应用,不能在URL上暴露任何重要信息,例如密码、服务器名称、IP地址或者文件系统路径(暴露了Web服务器的目录结构),这些信息可以在攻击时被使用。

6.1.6****防止源代码泄露

代码、文档里面包含各种敏感信息(用户名、密码、数据库信息、内网IP等),员工入职时都签订了保密协议,明确说明员工工作过程中创造的代码、文档等属于公司财产,禁止任何人员非授权对外公开,如上传到github、网盘及私自拷贝到个人U盘等;公司安全规范中也明确禁止开发人员通过任何方式外传公司代码,上传到开源平台或社区,如github、开源中国等。

对于违规外泄公司源码的人员,参考相关处罚机制,严重者予以开除并追究法律责任。

6.1.7****弱密码管理

密码是用户身份鉴权的一种常见方式, 对于系统中的普通注册用户,应在密码设置界面上提供密码强度提示功能,建议用户设置强度较高的密码(如字母加数字组合),根据实际业务需求可以对用户的密码强度做强制性要求。

对于系统中的高权限用户,如后台管理员、内容发布管理员、系统配置人员等,应当启用强制密码策略,不允许此类用户设置简单密码。 强制密码策略的具体要求如下:

  • 密码长度大于或等于 8 位;
  • 密码包含大写字母、小写字母、数字和特殊字符中的 3 种及以上;
  • 每 90 天修改一次密码,修改后的密码不得与最近两次使用的密码相同。

6.1.8****设置PATH变量

设置PATH为一个已知的值,而不是仅仅使用启动时的缺省值。攻击者可

以在攻击应用程序时使用PATH变量,例如试图执行一个任意的程序,这些可

以应用于大多数其他的语言。

6.2Web编程安全基本要求

6.2.1****输入检查安全

  • 限制用户输入HTML和Script(JavaScript、VBScript)代码。输入恶意HTML或Script(JavaScript、VBScript)代码可能会对其他浏览者造成混淆、欺骗或恶意破坏的结果;
  • 检查用户输入数据的长度。输入超出限定长度的数据,可能造成服务器端程序溢出;
  • 防止用户输入特殊字符改变SQL语义。输入含特殊字符的字串,篡改SQL语句的语义,可能造成SQL查询执行不该执行的操作,以此绕过身份认证获取非法权限、甚至对数据进行破坏;
  • 限制用户能够访问的最顶层目录。编写对服务器端文件、目录操作的程序时应该注意限定此类程序能够访问的最顶层目录,防止用户构造输入字串借助程序功能访问服务器关键文件导致泄漏服务器敏感信息;
  • 对所有类型的用户输入都要做检查,并严格限定什么是合法的用户输入,限定一个合法输入的范围,同时过滤有可能造成危险的特殊字符;
  • 对不可信任域发送到可信任域的数据一定要进行检查;
  • 尽可能在服务器端完成用户输入检查,不能轻易相信客户端脚本的检查结果。虽然客户端的Script脚本能完成一部分的用户输入检查功能,但这种检查的结果是不可信任的,攻击者可以自己制作表单程序绕过客户端脚本验证,将非法数据提交到服务器;
  • 在输入变为输出时,也要对特殊字符做检查和转换。

6.2.2****敏感数据的存放和传递安全

  • 敏感数据不能存放在Web页中;
  • 不能把敏感的数据存储在cookie、隐藏字段或者潜在地可能会被用户修改的地方;
  • 客户端向服务器端提交敏感数据应该经过加密(例如使用SSL),尽量不能明文传输;
  • 密码等敏感信息存放在数据库中应该加密,并采用健壮的加密算法;
  • 防止数据库被攻破后泄漏用户密码;
  • 敏感数据需要脱敏显示。

6.2.3****缓冲区溢出安全

  • 所有的输入都必须进行正确的有效性检测;
  • 必须保证数组没有越界,增加数组操作函数的边界检查;
  • 安全地使用字符串处理函数,慎用有安全隐患的字符串处理函数;
  • 使用Format字符串的时候特别注意Unicode和ANSI的大小不一致的情

况;

  • 注意字符串结束符的保护;
  • 仔细研究库函数内部的缓冲区分配,明确其限制。不能使用realpath();
  • 等函数,如果功能需要必须使用时,一定要检查试图规范化的路径的长度,确保其不长于MAXPATHLEN;
  • 时刻进行边界检查。建议使用一些检查工具:Purify、Stackguard等检查代码,保证没有缓冲区溢出的问题。

6.2.4****格式化字符串安全

  • 使用固定的格式化字符串,或者来自可信源的格式化字符串;
  • 要检查并限定locale的请求为合法值;
  • 不能将用户输入直接作为格式化字符传给格式化函数。

6.2.5****整数溢出安全

  • 对于涉及到内存分配大小的计算,要进行仔细检查,确保计算不会产生溢出;
  • 对于涉及到数组索引的计算,要进行仔细检查,确保计算不会产生溢出;
  • 要使用无符号整数表示数组偏移和内存分配大小。

6.2.6****SQL注入代码安全

  • 要检查输入的有效性和可信度;
  • 要使用参数化的查询、占位符、或者参数绑定来构造SQL语句;
  • 要在程序之外存储数据库的连接信息,比如经过保护的配置文件或者Windows注册表;
  • 即使使用的是存储过程,也不能使用字符串连接来构造SQL语句;
  • 不能在存储过程内部使用字符串连接来构造SQL语句;
  • 不能在存储过程内部执行不可信的参数;
  • 不能简单地双写单引号或者双引号;
  • 不能使用高权限账号连接数据库,比如sa或者root;
  • 不能在程序或者连接字符串中存储登录口令;
  • 不能在Web根目录下存储数据库配置信息;
  • 应从数据库中删除对所有用户自定义表的访问权限,同时只对存储过程授权,然后使用存储过程以及参数化的查询来构造查询字符串。

6.2.7****命令注入代码安全

  • 在输入命令传递给命令处理程序之前要进行验证;
  • 如果输入验证失败,要安全地处理失败信息;
  • 不能向任何命令解释器传递未验证的输入信息,即使这些输入仅仅是数据信息;
  • 避免使用正则表达式来进行输入验证,应手工去写一些简单而又清晰的验证代码。

6.2.8****异常处理代码安全

  • 要检测每个安全相关函数的返回值;
  • 对于每一个更改用户设定或者及其设定的函数,都要检查其返回值;
  • 要有从错误条件中进行恢复的考虑,避免拒绝服务攻击;
  • 不能一次性处理所有的异常,要将异常情况进行分类处理,避免在异常处理代码中的漏洞发生。

6.2.9****跨站脚本代码安全

要对所有基于Web的输入进行输入验证和可信度验证;

在没有验证合法性之前,不能对基于Web的输入进行回显;

不能在cookie中存储敏感数据。

6.2.10** 保护网络流量的代码安全**

要使用强大的初始认证机制;

对应用程序所产生的所有网络流量都要执行过程中消息认证;

尽可能使用SSL/TLS进行网络加密传输。

6.2.11** 应用中的弱口令代码安全**

确保口令在网络上认证时不被窃听;

要在登录失败时给出错误提示,并记录失败口令尝试;

尽可能使用基于hash强壮的单向加密函数进行口令存储;

为用户更改口令提供安全的机制;

不得使用默认账号和默认口令,若使用,必须在首次登录后进行修改;

不得在程序、后台存储明文的口令;

口令要有一定的强度,应当满足系统的账号口令策略要求。

6.2.12****SOCKET网络编程安全基本要求

在socket函数调用时,明确参数中绑定的端口、IP地址和网卡接。Windows环境下,在遇到多个网卡的情况时,需要通过注册表来获得网卡接口和IP地址的信息;

判断连接的合法身份。即,为防止恶意的连接以及可能是无效的连接,建议在socket连接期间,判断连接的对端是否是合法的真正的连接;

对于UDP连接,可以获得连接对方的IP地址和端口,从而可以判断对方的有效性和合法性;对于TCP连接,由于每次连接需要三次握手,而且还有超时机制,存在两种方式来控制;

对于TCP连接,需要尽量在三次握手完成前完成判断,同时防止端口扫描的攻击;

尽可能确保socket应用能通过合理设置的防火墙;

在可能的情况下,尽量减少socket连接数目;

尽量采用有连接状态的协议,例如TCP协议。由于防火墙一般采取禁止一切的策略,对于UDP协议比较难以设置;

在一个应用程序中,尽量使用同一种协议,不能使用多种协议;

尽量将客户端和服务器端的端口做成可以配置,不能硬编码在程序中。

6.3JAVA安全开发要求

JAVA语言安全规范参考OWASPTOP10要求,以下列举了常见的JAVA开发安全要求。

6.3.1****防范跨站脚本(XSS)

跨站脚本是最普遍的Web应用安全漏洞。当应用程序在发送给浏览器的页面中包含用户提供的数据,但没有经过适当验证或转译,就容易导致跨站脚本漏洞。

攻击者能在受害者浏览器中执行脚本以劫持用户会话、危害网站、插入恶意内容和重定向用户等。

已知三种著名跨站漏洞是:1)存储式;2)反射式;3)基于DOM。

反射式跨站脚本通过测试或代码分析很容易找到。

防范措施:

  • 验证输入

检查每个输入的有效性,主要检查输入类型和数据的长度;

  • 编码输出

对验证输入的另一面就是编码输出。编码输出是指确保字符被视为数据,而不是作为HTML元字符被浏览器解析。这些技术定义一些特殊的“转义”字符,没有正确转义的数据它仍然会在浏览器中正确解析。编码输出只是让浏览器知道数据是不是要被解析,达到攻击无法实现的目的。需要编码的部分:HTML实体、HTML属性、JavaScript、CSS、URL。

6.3.2****防范SQL注入

简单来说,注入往往是应用程序缺少对输入进行安全性检查所引起的,攻击者把一些包含指令的数据发送给解释器,解释器把收到的数据转换成指令执行。注入漏洞十分普遍,通常能在SQL查询、LDAP查询、Xpath查询、OS命令、程序参数等中出现。

注入能导致数据丢失或数据破坏、缺乏可审计性或是拒绝服务,注入漏洞有时甚至能导致完全接管主机。

SQL注入包含了SQL注入、XPATH注入、LDAP注入、OS命令注入等。

6.3.3****防范恶意文件执行

恶意文件执行是一种能够威胁任何网站形式的漏洞,只要攻击者在具有引入(include)功能程式的参数中修改参数内容,Web服务器便会引入恶意程序从而受到恶意文件执行漏洞攻击。

攻击者可利用恶意文件执行漏洞进行攻击取得Web服务器控制权,进行不法利益或获取经济利益。

6.3.4****不安全的直接对象引用

所谓“不安全的对象直接引用”,即Insecure direct object references,意指一个已经授权的用户,通过更改访问时的一个参数,从而访问到原本其并没有得到授权的对象。Web应用往往在生成Web页面时会用它的真实名字,且并不会对所有的目标对象访问时检查用户权限,所以这就造成了不安全的对象直接引用的漏洞。以下是不安全的对象直接引用示例:

  • 攻击者发现他自己的参数是6065,即?acct=6065;
  • 他可以直接更改参数为6066,即?acct=6066;
  • 这样他就可以直接看到6066用户的账户信息了;
  • 这种漏洞能损害参数所引用的所有数据。除非名字空间很稀疏,否则攻击者很容易访问该类型的所有数据。

6.3.5****防范跨站请求伪造

跨站请求伪造,也被称成为“one-click attack”或者session riding,通常缩写为CSRF或者XSRF,是一种对网站的恶意利用。它与XSS非常不同,并且攻击方式几乎相左。XSS利用站点内的信任用户,而CSRF则通过伪装来自受信任用户的请求来利用受信任的网站。与XSS攻击相比,CSRF攻击往往不太流行(因此对其进行防范的资源也相当稀少)和难以防范,所以被认为比XSS更具危险性。

攻击者能让受害用户修改可以修改的任何数据,或者是执行允许使用的任何功能。

6.3.6****信息泄露和错误处理不当

应用程序常常产生错误信息并显示给使用者。很多时候,这些错误信息非常有用,因为它们揭示实施细则或有用的开发信息。泄露太多的细节(如错误堆栈跟踪信息、SQL语句等等);

l 登录失败后,通知用户是否用户ID或密码出错——登录失败可能是由于ID或密码错误造成的。这为一个对关键资产发动蛮力攻击的攻击者提供重要信息。

6.3.7****残缺的认证和会话管理

与认证和会话管理相关的应用程序功能往往得不到正确实施,这就导致攻击者破坏密码、密钥、会话令牌或利用实施漏洞冒充其他用户身份。

这些漏洞可能导致部分甚至全部账号遭受攻击。一旦攻击成功,攻击者能执行合法用户的任何操作,因此特权账号会造成更大的破坏。

编程要求:

  • 使用内置的会话管理功能;
  • 通过认证的问候;
  • 使用单一的入口点;
  • 确保在一开始登录SSL保护的网页;
  • 获取注销的权利;
  • 添加超时;
  • 确保你使用的是安全相关的功能;
  • 使用强大的认证;
  • 不进行默认身份验证。

6.3.8****不安全的加密存储

保护敏感数据已经成为网络应用的最重要的组成部分,加密的敏感数据已是非常常见安全保护手段。不加密的应用程序、设计不当或者使用不恰当的密码技术等可能导致披露敏感数据。

  • 攻击者能够取得或是篡改机密的或是私有的信息;
  • 攻击者通过机密秘密的窃取从而进行进一步的攻击;
  • 造成企业形象破损,用户满意度下降,甚至面临法律诉讼等。
  • 编程要求;
  • 验证你的结构;
  • 识别所有的敏感数据;
  • 识别敏感数据存放的所有位置;
  • 确保所应用的威胁模型能够应付这些攻击;
  • 使用加密手段来应对威胁;
  • 使用一定的机制来进行保护;
  • 文件加密;
  • 数据库加密;
  • 数据元素加密;
  • 正确的使用这些机制;
  • 使用标准的强算法;
  • 合理的生成,分发和保护密钥;
  • 准备密钥的变更;
  • 验证实现方法;
  • 确保所有的证书、密钥和密码都得到了安全的存放;
  • 有一个安全的密钥分发和应急处理的方案。

6.3.9****不安全的通信

对于不加密的应用程序的网络信息传输,需要保护敏感的通信。加密(通常SSL)必须用于所有身份验证的连接,特别是通过Internet访问的网页,以及后端的连接。否则,应用程序将暴露身份验证或会话令牌。

  • 攻击者能够取得或是篡改机密的或是私有的信息;
  • 攻击者通过这些秘密的窃取从而进行进一步的攻击;
  • 造成企业形象破损,用户满意度下降,甚至面临法律诉讼等;
  • 编程要求;
  • 提供合理的保护机制;
  • 对于敏感数据的传输,对所有连接都要使用TLS;
  • 在传输前对单个数据都要进行加密;(如XML-Encryption);
  • 在传输前对信息进行签名;(如XML-Signature);
  • 正确的使用这些机制;
  • 使用标准的强算法;
  • 合理管理密钥和证书;
  • 在使用前验证SSL证书。

6.3.10** 限制URL访问失效**

这个漏洞事实上也是与认证相关的,与我们前面提到的不安全的直接对象引用也是类似的,不同在于这个漏洞是指系统已经对URL的访问做了限制,但这种限制却实际并没有生效。常见的错误是,我们在用户认证后只显示给用户认证过的页面和菜单选项,而实际上这些仅仅是表示层的访问控制而不能真正生效,攻击者能够很容易伪造请求直接访问未被授权的页面。

编程要求:

  • 如果URL不是公开的,那么必须限制能够访问的授权用户;
  • 加强基于用户或角色的访问控制;
  • 完全禁止访问未被授权的页面类型(如配置文件、日志文件、源文件等);
  • 验证你的构架;
  • 在每一个层次都使用简单肯定的模型;
  • 确保每一层都有一个访问机制;
  • 验证你的实现;
  • 不能使用自动化的分析工具;
  • 确保每个URL都被外部过滤器或其他机制保护;
  • 确保服务器的配置不允许对非授权页面的访问。

6.3.11****文件上传漏洞

如果对文件上传路径变量过滤不严,并且对用户上传的文件后缀以及文件类型限制不严,攻击者可通过 Web 访问的目录上传任意文件,包括网站后门文件(webshell),进而远程控制网站服务器。

在开发网站及应用程序过程中,需严格限制和校验上传的文件,禁止上传恶意代码的文件,限制相关目录的执行权限,防范 webshell 攻击。

防范要求:

  • 服务器配置不当:

重新配置好服务器。服务器PUT方法配置不当。

  • 设置文件上传的目录设置为不可执行

只要web容器无法解析该目录下面的文件,即使攻击者上传了脚本文件,服务器本身也不会受到影响,因此这一点至关重要。

  • 判断文件类型

在判断文件类型时,可以结合使用MIME Type、后缀检查等方式。在文件类型检查中,强烈推荐白名单方式,黑名单的方式已经无数次被证明是不可靠的。此外,对于图片的处理,可以使用压缩函数或者 resize 函数,在处理图片的同时破坏图片中可能包含的HTML代码。

  • 使用随机数改写文件名和文件路径

文件上传如果要执行代码,则需要用户能够访问到这个文件。在某些环境中,用户能上传,但不能访问。如果应用了随机数改写了文件名和路径,将极大地增加攻击的成本。再来就是像 shell.php.rar.rar 和 crossdomain.xml 这种文件,都将因为重命名而无法攻击。

  • 单独设置文件服务器的域名

由于浏览器同源策略的关系,一系列客户端攻击将失效,比如上传 crossdomain.xml、上传包含 Javascript 的 XSS 利用等问题将得到解决。

6.3.12****路径操纵

通过用户输入控制file System操作所用的路径,借此攻击者可以访问或修改其他受保护的系统资源。

编程要求:

防止“路径操纵”的最佳方法是采用一些间接手段:例如创建一份合法资源名的列表,并且规定用户只能选择其中的文件名。通过这种方法,用户就不能直接由自己来指定资源的名称了。

但在某些情况下,这种方法并不可行,因为这样一份合法资源名的列表过于庞大、难以跟踪。因此,程序员通常在这种情况下采用黑名单的方法。在输入之前,黑名单会有选择地拒绝或者避免潜在的危险字符。但是,任何这样一份黑名单都不可能是完整的,而且将随着时间的推移而过时。

更好的方法是创建一份白名单,允许其中的字符出现在资源名称中,且只接受完全由这些被认可的字符组成的输入。

6.3.13****硬编码密钥

软件代码中包含硬编码的密钥,这种处理方式一方面不易于程序维护,在代码投入使用后,除非对软件进行修补,否则无法修改密钥。严重的是如果攻击者能够访问应用程序的字节码,利用一些反编译工具就能阅读到代码,可以轻易获得密钥。

编程要求:

加密密钥永远不应该被硬编码,并且应该在外部源中进行混淆和管理。

6.3.14****硬编码密码

软件代码中包含硬编码的明文密码,这种处理方式一方面不易于程序维护,在代码投入使用后,除非对软件进行修补,否则无法修改密码。另一方面会削弱系统安全性,硬编码密码意味着拥有代码权限的人都可以查看到,可以使用密码访问一些不具有权限的系统,更严重的是如果攻击者能够访问应用程序的字节码,利用一些反编译工具就能阅读到代码,可以轻易获得密码。

编程要求:密码永远不应该被硬编码,并且通常应该在外部源中进行混淆和管理。在存储密码之前对其进行加密处理。

6.3.15****暴力破解漏洞

暴力破解攻击是指攻击者通过系统地组合所有可能性(例如登录时用到的账户名、密码),尝试所有的可能性破解用户的账户名、密码等敏感信息,经常是使用自动化脚本组合出正确的用户名和密码

总的来说是在系统中没有防御措施或措施不合理都会导致漏洞的存在,主要有以下几点原因:

  • 没有要求用户设置复杂密码,比如数字+字母+特殊字符
  • 在使用了验证码的时候,没有使用了安全的验证码
  • 没有对用户的登录行为进行检测和限制,如连续5次输入错误后锁定账户一段时间
  • 在必要情况下,没有使用双因素认证

编程要求:

1、程序要求用户设置复杂密码,比如数字+字母+特殊字符,并要求一定的长度。

2、使用了安全的验证码

3、当用户连续多次提交错误后,具有灵活的锁定机制。

4、使用双因素认证

6.4PHP安全开发要求

6.4.1****变量滥用

PHP-4.1.0发布的时候建议关闭register_globals,并提供了7个特殊的数组变量来使用各种变量。对于从GET、POST、COOKIE等来的变量并不会直接注册成变量,必需通过数组变量来存取。PHP-4.2.0发布的时候,php.ini默认配置就是register_globals=Off。这使得程序使用PHP自身初始化的默认值,一般为0,避免了攻击者控制判断变量。通过以下解决方法实现:

配置文件php.ini设置register_globals=Off。

要求程序员对作为判断的变量在程序最开始初始化一个值。

6.4.2****文件打开

如非特殊需要,把php的文件操作限制在Web目录里面。以下是修改apache配置文件httpd.conf的一个例子:

<Directory/usr/local/apache/htdocs>php_admin_valueopen_basedir/usr/local/apache/htdocs

重启apache后,/usr/local/apache/htdocs目录下的PHP脚本就只能操作它自己目录下的文件了,否则PHP就会报错:

Warning:open_basedirrestrictionineffect.Fileisinwrongdirectoryinxxxonlinexx.

使用safe_mode模式也能避免这种问题,前面已经讨论过。

6.4.3****文件包含

要求程序员包含文件里的参数尽量不能使用变量,如果使用变量,就一定要严格检查要包含的文件名,绝对不能由用户任意指定。如前面文件打开中限PHP操作路径是一个必要的选项。另外,如非特殊需要,一定要关闭PHP的远程文件打开功能。修改php.ini文件:

allow_url_fopen=Off

重启apache。

6.4.4****文件上传

PHP-4.0.3以后提供了is_uploaded_file和move_uploaded_file函数,可以检查操作的文件是否是用户上传的文件,从而避免把系统文件拷贝到Web目录。

使用 H T T P _ P O S T _ F I L E S 或 HTTP\_POST\_FILES或 HTTP_POST_FILES_FILES数组来读取用户上传的文件变量。严格检查上传变量。比如不允许是php脚本文件。把PHP脚本操作限制在Web目录可以避免程序员使用copy函数把系统文件拷贝到Web目录。move_uploaded_file不受open_basedir的限制,所以不必修改php.ini里upload_tmp_dir的值。把PHP脚本用phpencode进行加密,避免由于copy操作泄漏源码。严格配置文件和目录的权限,只允许上传的目录能够让nobody用户可写。

对于上传目录去掉PHP解释功能,可以通过修改httpd.conf实现:

<Directory/usr/local/apache/htdocs/upload>php_flagengineoff

#如果是php3换成php3_engineoff

重启apache,upload目录的php文件就不能被apache解释了,即使上传了php文件也没有问题,只能直接显示源码。

6.4.5****命令执行

解决方法:

要求程序员使用escapeshellcmd()函数过滤用户输入的shell命令。启用safe_mode可以杜绝很多执行命令的问题,不过要注意PHP的版本一定要是最新的,小于PHP-4.2.2的都可能绕过safe_mode的限制去执行命令。

变量类型缺陷逻辑比较时注意变量类型。

必要的时候使用"===",那么连变量类型一起比较。

6.4.6****警告及错误信息

修改php.ini中关于Errorhandlingandlogging部分内容:

error_reporting=E_ALLdisplay_errors=Offlog_errors=Onerror_log=/usr/local/apache/logs/php_error.log

然后重启apache,注意文件/usr/local/apache/logs/php_error.log,必需可

以让nobody用户可写。

6.4.7****PHP与MySQL组合的SQL注入

解决方法:

要求程序员对所有用户提交的要放到SQL语句的变量进行过滤。

即使是数字类型的字段,变量也要用单引号扩起来,MySQL自己会把字串处理成数字。

在MySQL里不能给PHP程序高级别权限的用户,只允许对自己的库进行操作。

6.4.8****跨站脚本

解决方法:

输入校验,输出实体编码。

strip_tags()

htmlspecialchars()

清除危险的插入点。

6.4.9****禁用无用的函数

如果觉得有些函数还有威胁,可以设置php.ini里的disable_functions(这个选项不能在httpd.conf里设置),比如:disable_functions=phpinfo,get_cfg_var

可以指定多个函数,用逗号分开。重启apache后,phpinfo,get_cfg_var函数都被禁止了。建议关闭函数phpinfo,get_cfg_var,这两个函数容易泄漏服务器信息,而且没有实际用处。

6.4.10****禁用某些类

这个选项是从PHP-4.3.2开始才有的,它可以禁用某些类,如果有多个用逗号分隔类名。disable_classes也不能在httpd.conf里设置,只能在php.ini配置文件里修改。

6.4.11****限制脚本操作路径

前面分析例程的时候也多次提到用open_basedir对脚本操作路径进行限制,这里再介绍一下它的特性。用open_basedir指定的限制实际上是前缀,不是目录名。也就是说"open_basedir=/dir/incl"也会允许访问"/dir/include"和"/dir/incls",如果它们存在的话。如果要将访问限制在仅为指定的目录,用斜线结束路径名。例如:“open_basedir=/dir/incl/”。

可以设置多个目录,在Windows中,用分号分隔目录。在任何其它系统中用冒号分隔目录。作为Apache模块时,父目录中的open_basedir路径自动被继承。

6.4.12****其他安全配置

取消其它用户对常用、重要系统命令的读写执行权限:

一般管理员维护只需一个普通用户和管理用户,除了这两个用户,给其它用户能够执行和访问的东西应该越少越好,所以取消其它用户对常用、重要系统命令的读写执行权限能在程序或者服务出现漏洞的时候给攻击者带来很大的迷惑。记住一定要连读的权限也去掉,否则在linux下可以用/lib/ld-linux.so.2/bin/ls这种方式来执行。

如果要取消程序如果是在chroot环境里,这个工作比较容易实现,否则,这项工作还是有些挑战的。因为取消一些程序的执行权限会导致一些服务运行不正常。PHP的mail函数需要/bin/sh去调用sendmail发信,所以/bin/bash的执行权限不能去掉。

去掉apache日志其它用户的读权限:

apache的access-log给一些出现本地包含漏洞的程序提供了方便之门。通过提交包含PHP代码的URL,可以使access-log包含PHP代码,那么把包含文件指向access-log就可以执行那些PHP代码,从而获得本地访问权限;

如果有其它虚拟主机,也应该相应去掉该日志文件其它用户的读权限;

当然,如果你按照前面介绍的配置PHP那么一般已经是无法读取日志文件了。

保持运行环境干净:

不能在Web目录放测试文件。

6.5C/C++安全开发要求

C本质上是不安全的编程语言。例如如果不谨慎使用的话,其大多数标准的字符串库函数有可能被用来进行缓冲区攻击或者格式字符串攻击。但是,由于其灵活性、快速和相对容易掌握,它是一个广泛使用的编程语言。下面是针对开发安全的C语言程序的一些规范。

6.5.1****缓冲区溢出

避免使用不执行边界检查的字符串函数,因为它们可能被用来进行缓冲区溢出攻击。下面是应该避免使用的函数。同时,也列出了每个函数相应的比较安全的替换方式。

l不使用strcpy(),使用strncpy();

l不使用strcat(),使用strncat();

l不使用sprintf(),使用snprintf();

l不使用gets(),使用fgets()。

在上面的前三个中函数中,每个替代函数的“n”表示了使用的缓冲区的大小。最后一个函数的“f”,表示格式,它允许用户指定期望的输入的格式。这些替换方程强制程序员定义使用的缓冲区的尺寸以及确定输入的类型。

6.5.2****格式化字符串攻击

该类攻击往往与缓冲区溢出相关,因为它们主要利用了某些函数的假设,例如sprintf()和vsprintf()假设缓冲区的长度是无限的。然而即使使用snprintf()替换sprintf()也无法完全保护程序不受格式化字符串的攻击。这些攻击通过直接将格式说明符(formatspecifiers)(%d,%s,%n等)传递到输出函数接收缓冲区来进行。

例如,以下的代码就是不安全的snprintf(buffer,sizeof(buffer),string)这种情况下,可以在字符串中插入格式说明符来操纵内存的栈,来写入攻击者的数据(这些数据中包含小的程序代码,并可由处理器接着执行)。对以上的例子建议使用下面的代码。

snprintf(buffer,sizeof(buffer),“%s”,string)进行格式字符串攻击不太容易。首先攻击者必须能获得内存栈的内容情况(或者从应用导出或者使用调试器),然后必须知道如何精确访问特定的内存空间来操纵栈中的变量。

执行外部程序推荐使用exec()函数而不是system()函数来执行外部程序。这是因为system()接收整个命令行的随机的缓冲区来执行程序。

snprintf(buffer,sizeof(buffer),“emacs%s”,filename);

system(buffer);

在以上的例子中,可以通过使用分号利用文件名变量在sehll中插入额外的命令(例如文件名可以是/etc/hosts;rm*,这将在显示/etc/hosts目录文件的同时,删除目录中的所有文件)。而exec()函数只保证第一个参数被执行:

execl(“usr/bin/emacs”,“usr/bin/emacs”,filename,NULL);

上面的例子保证文件名仅仅作为一个参数输入Emacs工具,同样它在Emacs命令中使用完全的路径而不是使用可以被攻击者利用的PATH环境变量。

6.5.3****竞争条件

进程需要访问资源时(无论是磁盘、内存或是文件)通常需要执行两个步骤:

1、首先测试资源是否空闲可用;

2、如果可用,就访问该资源,否则它等到资源不再使用为止再去访问它。当另一个进程在步骤1和2之间想要访问同一个资源时就出现问题了。

这会导致不可预测的结果。进程可能会被锁定,或者一个进程劫持获得了另一个进程的较大的权限而导致安全问题。攻击主要集中在有较大权限的程序上(称为setuid程序)。竞争条件攻击通常利用程序执行时可以访问到的资源。另外权限低的程序也存在安全风险,因为攻击者可能会等待有较高权限的用户执行那个程序(例如root),然后进行攻击。

下面的建议有助于缓解竞争条件(racecondition)攻击:

在进行文件操作时,利用那些使用文件描述符的函数而不能使用那些使用文件路径的函数(例如使用fdopen()而不能使用fopen())。文件描述符使得恶意的用户在文件打开时或是在原始的进程对文件进行操作前,无法使用文件连接(符号式的或是物理的)来改变文件。

在写文件甚至在读文件时使用fcntl()和flock()函数来对文件加锁,这样它们就不能被其他进程访问。它几乎可以建立原子级的操作。

谨慎操纵临时文件,因为它往往会导致竞争条件。

6.5.4****检验有效的返回值

检验有效的返回值非常重要。一个例子是旧的/bin/login的实现中不检验错误的返回值,导致当它找不到/etc/passwd文件时返回root的访问权限。如果该文件损坏了,那么这种情况是合理的,但如果该文件存在只是无法访问,那么这就是一个大问题。

6.6Perl安全开发要求

多年以来,Perl已经成为用于系统管理和WebCGI开发的功能最强的编程语言之一(几乎可以使用Perl做任何功能的程序)。但其扩展应用,即作为Internet上CGI的开发工具,使得它经常成为Web服务器上的攻击目标。

另外,大多数CGI脚本有着比一般用户更高的权限,导致它更容易受攻击。下面列举了一些开发者(特别是CGI程序员)可以使用的主动的预防性的措施来增强Perl代码的整体安全性(请注意:这不是Web服务器CGI脚本安全性的指导原则)。

6.6.1****Taint验证

Perl版本5.x包含一个叫做TaintChecking的数据验证措施。如果起用该功能,将不允许通过用户输入(任何程序外的输入)来操纵其他的外部程序(例如通过管道将数据导入另一个程序执行))。一般而言,程序员不能信任输入脚本和程序的数据(叫做Tainted数据),因为无法保证它不会产生危害(有意或者无意的)。Taint验证可以通过在命令行参数加入“-T”来开启。

例如:你可以在Perl脚本的第一行这样加入“-T”:

#!usr/bin/perl5-T

Tainted数据包括命令行参数、环境变量和来自文件的数据。引用tainted

数据的变量也称为tainted数据。如果脚本试图通过不安全的方式来使用tainted数据会产生一个致命错误(对这种情况称为“不安全的依赖”(Insecuredependency)或者其他的说法)。启用tainted验证在有些情况下会导致脚本停止运行,常常是由于Perl解释器要求所有脚本引用的外部程序的完全路径必须在PATH环境变量中列出,同时PATH中包含的每个目录除了目录的所有者及相应的所有者用户组外无法修改。Taint验证对于环境比较敏感,但是只要可能的话,应该使用taint验证,特别是代码执行其他程序功能时(例如在CGI脚本的情况下)。

6.6.2****安全模块

如果不但输入数据不可信而且实际的代码也不可信,例如用户从网站上下载了一个ActiveX控件,而它实际是一个特洛伊木马(Trojanhorse)。这种情况下taint验证就不起作用。安全模块让程序员可以在Perl脚本中将不同的代码模块与安全对象联系。每个安全对象对于运行的每块代码建立了一个限制的环境。这与chroot在一个进程中只能在整体目录结构的一个子目录中运行类似。而saft对象限制perl代码只能在perl包结构的某些特定包中运行。如何使用安全模式超出了本文的范围,但是程序员应该在任何时候尽量使用这一功能。

6.6.3****警告参数

使用-w参数可以在Perl解释脚本时显示所有的警告信息。警告可以在以下情况产生:只使用了一次的变量或者完全没有使用过得变量,未定义的文件句柄,未关闭的文件句柄,或者将非数值变量传递到数据变量。该功能不是针对安全处理的,但是可以有助于调试直接或者间接对安全有危害的错误。一般推荐总是使用-w参数。可以在taint验证时在第一行这样使用-w参数:

#!usr/bin/perl5-Tw

北京研发中心-刘洋赞了它

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

写评论…

添加评论

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值