Web常见漏洞篇——Web 安全之基本原则(补充节点1)


当你的才华

还撑不起你的野心时

那你就应该静下心来学习


目录

Web 安全之基本原则(补充节点1)

0x01 Web部署原则

0x02 身份认证原则

0x03 会话管理原则

0x04 权限管理原则

0x05 敏感数据保护原则

0x06 安全日志原则

0x07 输入校验原则

0x08 输出编码原则

0x09 其他原则


 

Web 安全之基本原则(补充节点1)

      安全应该是系统开发之初就考虑的问题。换句话说,安全是一个成熟系统的必备特性。在项目说明中不谈安全,并非因为不需要,而是因为安全都是隐藏的。

      安全性设计中的关键问题是挖掘出系统存在的安全漏洞。在这我们可以采用黑盒测试或者安全检测工具来进行。在开发过程中,遵守一些web安全原则,是提高安全很好的措施.

0x01 Web部署原则

  1. 如果Web应用对Internet开放,Web服务器应当置于DMZ区,在Web服务器与Internet之间,Web服务器与内网之间应当有防火墙隔离,并设置合理的策略。
  2. 如果Web应用对Internet开放,Web服务器应该部署在其专用的服务器上,应避免将数据库服务器或其他核心应用与Web服务器部署在同一台主机上(Web服务器比较容易被攻击,如果数据库或核心应用与Web服务器部署在同一台主机,一旦Web服务器被攻陷,那么数据库和核心应用也就被攻击者掌控了)。
  3. Web站点的根目录必须安装在非系统卷中,(Web站点根目录安装在非系统卷,如单独创建一个目录/home/Web作为Web站点根目录,能够防止攻击者使用目录遍历攻击访问系统工具和可执行文件)。
  4. 部署时应使用最低的系统权限:应保证应用程序工作在低于普通权限的条件下,在运行Web程序时使用高等权限是种错误的做法。Web程序是攻击者目标,成功之后,攻击者获得了相应的系统权限。故不应使用Administrator或者System权限。若应用程序需要高权限运行,可以将其分离出去并运行在限定了通信信道的进程中,然后提高权限。
  5. Web服务器与应用服务器需物理分离(即安装在不同的主机上),以提高应用的安全性。
  6. 如果Web应用系统存在不同的访问等级(如个人帐号使用、客户服务、管理),那么应该通过不同的Web服务器来处理来自不同访问等级的请求,而且Web应用应该鉴别请求是否来自正确的Web服务器(这样便于通过防火墙的访问控制策略和Web应用来控制不同访问等级的访问,比如通过防火墙策略控制,只允许内网访问管理Portal)。
  7. 对于“客户服务”和“管理”类的访问,除了普通的认证,还应该增加额外的访问限制,(额外的访问限制,可以限制请求来自企业内网,可以建立VPN,或采用双向认证的SSL;或采用更简单的办法,通过IP地址白名单对客户端的IP地址进行过滤判断)。
  8. 首选系统默认安全措施:少的和核心的功能保证稳定并减少了攻击面。

0x02 身份认证原则

  1. 对用户的最终认证处理过程必须放到应用服务器进行(不允许仅仅通过脚本或其他形式在客户端进行验证,必须在应用服务器进行最终认证处理(如果采用集中认证,那么对用户的最终认证就是放在集中认证服务器进行))。
  2. 认证模块必须采用防暴力破解机制,例如:验证码或者多次连续尝试登录失败后锁定帐号或IP:如采用多次连续尝试登录失败后锁定帐号或IP的方式,需支持连续登录失败锁定策略的“允许连续失败的次数”可配置,支持在锁定时间超时后自动解锁。(使用验证码的目的是为了阻止攻击者使用自动登录工具连续尝试登录,从而降低被暴力破解的可能。如果觉得验证码影响用户体验,那么可以在前3次登录尝试中不使用验证码,3次登录失败后必须使用验证码。验证码在设计上必须要考虑到一些安全因素,以免能被轻易地破解,对于嵌入式系统,如果实现验证码比较困难,可以通过多次认证失败锁定客户端IP的方式来防止暴力破解)。
  3. 用户产生的数据必须在服务端进行校验;数据在输出到客户端前必须先进行HTML编码,以防止执行恶意代码、跨站脚本攻击。对于不可信的数据,输出到客户端前必须先进行HTML编码。
  4. 用户名、密码和验证码必须在同一个请求中提交给服务器,必须先判断验证码是否正确,只有当验证码检验通过后才进行用户名和密码的检验,否则直接提示验证码错误(如果验证码和用户名、密码分开提交,攻击者就可以绕过验证码校验(如:先手工提交正确的验证码,再通过程序暴力破解),验证码就形同虚设,攻击者依然可以暴力破解用户名及口令)。
  5. 所有登录页面的认证处理模块必须统一(可以存在多个登录页面,但是不允许存在多个可用于处理登录认证请求的模块,防止不一致的认证方式);认证处理模块必须对提交的参数进行合法性检查。
  6. 所有针对其他第三方开放接口的认证处理模块必须统一。
  7. 认证失败后,不能提示给用户详细以及明确的错误原因,只能给出一般性的提示。(可以提示:“用户名或者口令错误,登录失败”;不能提示:“用户名不存在”、“口令必须是6位”等等)。
  8. 最终用户portal和管理portal分离,防止相互影响,防止来自用户面的攻击影响管理面。(将最终用户portal和管理portal分别部署在不同的物理服务器;如果为了解决成本合设(部署在同一台物理服务器上),那么,必须做到端口分离(通过不同的端口提供Web服务),一般的Web容器(如tomcat)支持为不同的Web应用创建不同的端口)。
  9. 禁止在系统中预留任何的后门帐号或特殊的访问机制。
  10. 对于重要的管理事务或重要的交易事务要进行重新认证,以防范会话劫持和跨站请求伪造给用户带来损失。(重要的管理事务,比如重新启动业务模块;重要的交易事务,比如转账、余额转移、充值等。重新认证,比如让用户重新输入口令)。
  11. 管理页面建议实施强身份认证。(如双因素认证、SSL双向证书认证、生物认证等;还可以通过应用程序限制只允许某些特定的IP地址访问管理页面,并且这些特定的IP地址可配置)。
  12. 同一客户端在多次连续尝试登录失败后,服务端需要进行用户帐号或者是客户端所在机器的IP地址的锁定策略,且该锁定策略必须设置解锁时长,超时后自动解锁。(应用程序的超级用户帐号不能被锁定,只能锁定操作的客户端所在的IP,这是为了防止系统不可用,锁定用户帐户的策略也存在缺陷,当攻击者不断尝试某帐户的口令,就给该帐户带来拒绝服务攻击,使该帐户不可用)。
  13. 对于每一个需要授权访问的页面或servlet的请求都必须核实用户的会话标识是否合法、用户是否被授权执行这个操作,以防止URL越权:防止用户通过直接输入URL,进行URL越权,请求并执行一些页面或servlet;建议通过过滤器实现。
  14. 验证码内容不能与客户端提交的任何信息相关联(在使用验证码生成模块时不允许接收来自客户端的任何参数,例如:禁止通过getcode.jsp?code=1234的URL请求,将1234作为验证码随机数)。
  15. 验证码模块生成的随机数不能在客户端的静态页面中的网页源代码里出现。

            说明:在客户端网页上点击鼠标右键、选择“查看源文件”时,必须看不到验证码模块生成的随机数。

   16. 验证码字符串要求是随机生成,生成的随机数必须是安全的。(对于java语言可以使用类java.security.SecureRandom来生成安全的随机数)。

   17. 验证码要求有背景干扰,背景干扰元素的颜色、位置、数量要求随机变化。

   18. 验证码在一次使用后要求立即失效,新的请求需要重新生成验证码。
说明:进行验证码校验后,立即将会话中的验证码信息清空,而不是等到生成新的验证码时再去覆盖旧的验证码,防止验证码多次有效;注意:当客户端提交的验证码为空,验证不通过。

   19. 验证码必须是单一图片,且只能采用JPEG、PNG或GIF格式。验证码不能使用文本格式,不允许多图片组合(如用四个图片拼成的验证码)。

   20. 用户名和密码认证通过后,须更换会话标识,以防止会话固定(session fixation)漏洞。


0x03 会话管理原则


   1. 当用户退出时,必须清除该用户的会话信息。(防止遗留在内存中的会话信息被窃取,减少内存占用)。对于JSP或java语言使用如下语句:request.getSession().invalidate();

   2. 使用会话cookie维持会话,目前主流的Web容器通过以下几种方式维持会话:隐藏域、URL重写、持久性cookie、会话cookie,但通过隐藏域、URL重写或持久性cookie方式维持的会话容易被窃取,所以要求使用会话cookie维持会话。如果条件限制必须通过持久性cookie维持会话的话,那么cookie信息中的重要数据部分如身份信息、计费信息等都必须进行加密。(cookie有两种:会话cookie和持久性cookie;会话cookie,也就是非持久性cookie,不设置过期时间,其生命期为浏览器会话期间,只要关闭浏览器窗口,cookie就消失了;会话cookie一般不存储在硬盘上而是保存在内存里。持久性cookie,设置了过期时间,被浏览器保存到硬盘上,关闭后再次打开浏览器,持久性cookie仍然有效直到超过设定的过期时间)。

   3. 会话过程中不允许修改的信息,必须作为会话状态的一部分在服务器端存储和维护。(会话过程中不允许修改的信息,例如,当用户通过认证后,其用户标识在整个会话过程中不能被篡改。禁止通过隐藏域或URL重写等不安全的方式存储和维护。对JSP语言,就是应该通过session对象进行存储和维护)。

   4. 禁止使用客户端提交的未经审核的信息来给会话信息赋值。(防止会话信息被篡改,如恶意用户通过URL篡改手机号码等)。

   5. 当Web应用跟踪到非法会话,则必须记录日志、清除会话并返回到认证界面。非法会话的概念就是通过一系列的服务端合法性检测(包括访问未授权资源,缺少必要参数等情况),最终发现的不是正常请求产生的会话。

   6. 必须设置会话超时机制,在超时过后必须要清除该会话信息。(建议默认会话超时时间为10分钟(备注:对于嵌入式系统中的Web,建议默认超时时间为5分钟,以减少系统资源占用)。如果没有特殊需求,禁止使用自动发起请求的机制来阻止session超时)。

   7. ​​​​​​​在服务器端对业务流程进行必要的流程安全控制,保证流程衔接正确,防止关键鉴别步骤被绕过、重复、乱序。(客户端流程控制很容易被旁路(绕过),因此流程控制必须在服务器端实现。可以通过在session对象中创建一个表示流程当前状态的标识位,用0、1、2、3、…、N分别表示不同的处理步骤,标识位的初始值为0,当接收到步骤N的处理请求时,判断该标识位是否为N-1,如果不为N-1,则表示步骤被绕过(或重复或乱序),拒绝受理,否则受理,受理完成后更改标识位为N)。

   8. ​​​​​​​所有登录后才能访问的页面都必须有明显的“注销(或退出)”的按钮或菜单,如果该按钮或菜单被点击,则必须使对应的会话立即失效。(这样做是为了让用户能够方便地、安全地注销或退出,减小会话劫持的风险)。


0x04 权限管理原则

   1. ​​​​​​​对于每一个需要授权访问的页面或servlet的请求都必须核实用户的会话标识是否合法、用户是否被授权执行这个操作。(防止用户通过直接输入URL,越权请求并执行一些页面或servlet;建议通过过滤器实现)。

   2. ​​​​​​​授权和用户角色数据必须存放在服务器端,不能存放在客户端,鉴权处理也必须在服务器端完成。(禁止将授权和角色数据存放在客户端中(比如cookie或隐藏域中),以防止被篡改)。

   3. ​​​​​​​一个帐号只能拥有必需的角色和必需的权限。一个组只能拥有必需的角色和必需的权限。一个角色只能拥有必需的权限。做到权限最小化和职责分离(职责分离就是分清帐号角色,系统管理帐号只用于系统管理,审计帐号只用于审计,操作员帐号只用于业务维护操作,普通用户帐号只能使用业务)。这样即使帐号被攻击者盗取,也能把安全损失控制在最小的限度。

   4. ​​​​​​​对于运行应用程序的操作系统帐号,不应使用“root”、“administrator”、“supervisor”等特权帐号或高级别权限帐号,应该尽可能地使用低级别权限的操作系统帐号。

   5. ​​​​​​​对于应用程序连接数据库服务器的数据库帐号,在满足业务需求的前提下,必须使用最低级别权限的数据库帐号。(根据业务系统要求,创建相应的数据库帐号,并授予必需的数据库权限。不能使用“sa”、“sysman”等管理帐号或高级别权限帐号)。

   6. ​​​​​​​严格限制导出功能的权限,对导出功能的使用必须有日志记录。


0x05 敏感数据保护原则

   1. ​​​​​​​口令不允许明文存储在系统中,应该加密保护。在不需要还原口令的场景,必须使用不可逆算法加密。对银行账号等敏感数据的访问要有认证、授权和加密机制。口令文件必须设置访问权限控制,普通用户不能读取或拷贝加密的内容。如果帐户文件/数据中含有口令又必须所有用户可访问,则需将帐户文件/数据与口令文件/数据分开。

   2. ​​​​​​​在非信任网络之间进行敏感数据(包括口令,银行帐号,批量个人数据等)的传输须采用安全传输通道或者加密后传输,有标准协议规定除外。

   3. ​​​​​​​禁止使用私有加密算法,必须使用公开、安全的标准加密算法。

   4. ​​​​​​​用于敏感数据传输加密的密钥,不能硬编码在代码中。在敏感数据的安全传输上,优先使用业界的标准安全协议(如SSH v2/TLS1.0/SSL3.0/IPSec/SFTP/HTTPS等),并确保密钥可配置;如果是由产品自身实现安全传输过程,则优先使用Diffie-Hellman密钥交换算法,如果使用预置共享密钥等其他方法,也必须保证该密钥可配置和可替换。

   5. ​​​​​​​禁止在日志、话单等文件中记录口令、银行账号、通信内容等敏感数据;避免不安全的本地存储。

   6. ​​​​​​​涉及个人数据的采集/处理的功能须提供安全保护机制(如认证、权限控制、日志记录等),并通过产品资料向客户公开。

   7. ​​​​​​​尽量避免在日志、话单中记录个人数据,如果必须记录个人数据,则所有数据必须进行结构化存储或适合于进行匿名化提取。

   8. ​​​​​​​加密不能确保安全:加密是单纯的概念,单纯的加密不能保证系统的任何安全。加密需要与算法、密钥生成算法、密码传送等一系列机制结合才能保证安全。安全是相对的,没有绝对安全。

   9. ​​​​​​​禁止在代码中存储敏感数据。(禁止在代码中存储如数据库连接字符串、口令和密钥之类的敏感数据,这样容易导致泄密。用于加密密钥的密钥可以硬编码在代码中)。

   10. ​​​​​​​禁止密钥或帐号的口令以明文形式存储在数据库或文件中(密钥或帐号的口令必须经过加密存储。例外情况,如果Web容器的配置文件中只能以明文方式配置连接数据库的用户名和口令,则不用强制遵循该规则,将该配置文件的属性改为只有属主可读写)。

   11. ​​​​​​​禁止在cookie中以明文形式存储敏感数据。(cookie信息容易被窃取,尽量不要在cookie中存储敏感数据;如果条件限制必须使用cookie存储敏感信息时,必须先对敏感信息加密再存储到cookie)。

   12. ​​​​​​​禁止带有敏感数据的Web页面缓存。(带有敏感数据的Web页面都应该禁止缓存,以防止敏感信息泄漏或通过代理服务器上网的用户数据互窜问题)。

   13. ​​​​​​​带有敏感数据的表单必须使用HTTP-POST方法提交。(禁止使用HTTP-GET方法提交带有敏感数据的表单(form),因为该方法使用查询字符串传递表单数据,易被查看、篡改。如果是使用servlet处理提交的表单数据,那么不在doGet方法中处理,只在doPost方法处理)。

   14. ​​​​​​​在客户端和服务器间传递明文的敏感数据时,必须使用带服务器端证书的SSL(如果在客户端和服务器间传递如帐号、口令等明文的敏感数据,必须使用带服务器端证书的SSL。由于SSL对服务端的CPU资源消耗很大,实施时必须考虑服务器的承受能力)。

   15. ​​​​​​​禁止在URL中携带会话标识(如jsessionid)。(由于浏览器会保存URL历史记录,如果URL中携带会话标识,则在多人共用的PC上会话标识容易被其他人看到,一旦该会话标识还在其生命有效期,则恶意用户可以冒充受害用户访问Web应用系统)。

   16. ​​​​​​​数据库口令禁止使用数据库厂商的缺省口令,且口令复杂度需满足“口令安全要求”。数据库若存在多个默认帐号,须将不使用的帐号禁用或删除。

   17. ​​​​​​​使用单独的操作系统帐号来运行数据库;数据库中的敏感文件(如:Oracle数据库的init.ora、listener.ora等)需要严格控制访问权限,只能被数据库进程运行帐户和DBA帐户读写;对数据库帐户授予的权限进行严格清晰的划分,所有数据库帐户只能具备执行其任务的最小权限;对于有监听器功能的数据库(如Oracle的listener.ora)需要设置监听器密码或者设置为本地操作系统验证。


0x06 安全日志原则

   1. ​​​​​​​应用服务器必须对安全事件及操作事件进行日志记录。(安全事件包括登录、注销、添加、删除、修改用户、授权、取消权限、鉴权、修改用户口令等;操作事件包括对业务系统配置参数的修改,对重要业务数据的创建、删除、修改、查询等;对于上述事件的结果,不管是成功还是失败,都需要记录日志)。

   2. ​​​​​​​安全日志必须包括但不限于如下内容:事件发生的时间、事件类型、客户端IP、客户端机器名、当前用户的标识、受影响的个体(数据、资源)、成功或失败标识、启动该事件的进程标识以及对该事件的详细描述。

   3. ​​​​​​​严格限制对安全日志的访问。(只有Web应用程序的管理员才能查询数据库表形式或文件形式的安全日志;除数据库超级管理员外,只有应用程序连接数据库的帐号可以查询(select)及插入(insert)安全日志表;除操作系统超级管理员外,只有应用程序的运行帐户才能读、写文件形式的安全日志(但不允许删除)。确保日志的安全,限制对日志的访问,这加大了攻击者篡改日志文件以掩饰其攻击行为的难度)。

   4. ​​​​​​​对日志模块占用资源必须有相应的限制机制(限制日志模块占用的资源,以防止如自动的恶意登陆尝试导致的资源枯竭类DOS攻击;比如限制日志记录占用的磁盘空间)。

   5. ​​​​​​​禁止日志文件和操作系统存储在同一个分区中,同时,应使用转储、滚动、轮循机制,来防止存储日志的分区写满。(所需空间和具体业务、局点容量、日志保存周期相关,要根据实际情况估算)。

   6. ​​​​​​​安全日志应该有备份及清理机制。(备份及清理机制包括定期备份及清理安全日志和监控用于存放安全日志的磁盘空间的使用情况。可以配置定期备份及清理的时间,可以配置以用于存放安全日志的磁盘空间使用率达到多少时进行备份及清理)。

   7. ​​​​​​​通过网络形式保存安全日志。(在生成安全日志时,即时将日志保存到网络上其他主机,而且生成安全日志的应用程序不能再访问存放在其他主机的日志)。


0x07 输入校验原则

   1. ​​​​​​​必须对所有用户产生的输入进行校验,一旦数据不合法,应该告知用户输入非法并且建议用户纠正输入。(用户产生的输入是指来自text、password、textareas或file表单域的数据;必须假定所有用户产生的输入都是不可信的,并对它们进行合法性校验)。

   2. ​​​​​​​必须对所有服务器产生的输入进行校验,一旦数据不合法,必须使会话失效,并记录告警日志。(服务器产生的输入是指除用户产生的输入以外的输入,例如来自hidden fields、selection boxes、check boxes、radio buttons、cookies、HTTP headers、热点链接包含的URL参数的数据或客户端脚本等;必须假定所有服务器产生的输入都是被篡改过的、恶意的,并对它们进行合法性校验,如果不合法,说明有人恶意篡改数据。举例:假如用户资料填写表单中的“性别”为必填项,用radio button(‘男’和‘女’对应实际值分别为‘1’和‘0’)来限制用户的输入,如果应用程序收到的“性别”值为‘2’,那么可以断定有人恶意篡改数据)。

   3. ​​​​​​​禁止将HTTP标题头中的任何未加密信息作为安全决策依据。(HTTP标题头是在HTTP请求和HTTP响应的开始阶段发送的。Web应用程序必须确保不以HTTP标题头中的任何未加密信息作为安全决策依据,因为攻击者要操作这一标题头是很容易的。例如,标题头中的referer字段包含来自请求源端的Web页面的URL。不要根据referer字段的值做出任何安全决策(如检查请求是否来源于Web应用程序生成的页面),因为该字段是很容易被伪造的)。

   4. ​​​​​​​不能依赖于客户端校验,必须使用服务端代码对输入数据进行最终校验。(客户端的校验只能作为辅助手段,减少客户端和服务端的信息交互次数)。

   5. ​​​​​​​对于在客户端已经做了输入校验,在服务器端再次以相同的规则进行校验时,一旦数据不合法,必须使会话失效,并记录告警日志。(肯定存在攻击行为,攻击者绕过了客户端的输入校验,因此必须使会话失效,并记入告警日志)。

   6. ​​​​​​​如果输入为数字参数则必须进行数字型判断。(这里的数字参数指的是完全由数字组成的数据)。

   7. ​​​​​​​如果输入只允许包含某些特定的字符或字符的组合,则使用白名单进行输入校验。(对于一些有规则可循的输入,如email地址、日期、小数等,使用正则表达式进行白名单校验,这样比使用黑名单进行校验更有效)。

   8. ​​​​​​​如果输入为字符串参数则必须进行字符型合法性判断。可定义一个合法字符集。

   9. ​​​​​​​校验输入数据的长度。如果输入数据是字符串,必须校验字符串的长度是否符合要求,长度校验会加大攻击者实施攻击的难度。

   10. ​​​​​​​校验输入数据的范围。如果输入数据是数值,必须校验数值的范围是否正确,如年龄应该为0~150之间的正整数。

   11. ​​​​​​​禁止通过字符串串联直接使用用户输入构造可执行SQL语句。(禁止通过字符串串联直接使用用户输入构造可执行SQL语句,如:string sql = “select status from Users where UserName=’” + txtUserName.Text + “’”;这样很容易被SQL注入攻击)。

   12. ​​​​​​​对于java/JSP语言,使用预编译语句PreparedStatement代替直接的语句执行Statement。(使用预编译语句PreparedStatement,类型化SQL参数将检查输入的类型,确保输入值在数据库中当作字符串、数字、日期或boolean等值而不是可执行代码进行处理,从而防止SQL注入攻击。而且,由于PreparedStatement对象已预编译过,所以其执行速度要快于Statement对象。因此,多次执行的SQL语句经常创建为PreparedStatement对象,还可以提高效率)。

   13. ​​​​​​​禁止动态构建XPath语句。和动态构建SQL一样,动态构建XPath语句也会导致注入漏洞(XPath注入)。动态构建XPath语句的例子:

public boolean doLogin(String loginID, String password){
	......
		XPathExpression expr = xpath.compile("//users/user[loginID/text()='"+loginID+"' and password/text()='"+password+"' ]/firstname/text()");
	......
}


   14. ​​​​​​​在JavaBean中禁止使用property="“进行参数赋值。(property=”"这表明用户在可见的JSP页面中输入的,或是直接通过Query String提交的参数值,将存储到与参数名相匹配的bean属性中。例如,网上购物程序,一般,用户是这样提交请求的:http://www.somesite.com/addToBasket.jsp?newItem=ITEM0105342,如果用户提交:http://www.somesite.com/addToBasket.jsp?newItem=ITEM0105342&balance=0,这样,balance=0的信息就被在存储到了JavaBean中了,而balance是整个会话中用来存储总费用的,当他们这时点击“chekout”结账的时候,费用就全免了)。

   15. ​​​​​​​用于重定向的输入参数不能包含回车和换行字符,以防止HTTP响应拆分攻击。(注意,“回车”字符有多种表示方式(CR = %0d = \r),“换行”字符有多种表示方式(LF = %0a = \n)。)

   16. ​​​​​​​如果服务端代码执行操作系统命令,禁止从客户端获取命令。(如果服务端代码中使用Runtime.getRuntime().exec(cmd)或ProcessBuilder等执行操作系统命令,那么禁止从客户端获取命令;而且最好不要从客户端获取命令的参数,如果必须从客户获取命令的参数,那么必须采用正则表达式对命令参数进行严格的校验,以防止命令注入(因为,一旦从客户端获取命令或参数,通过;&|<>符号,非常容易构造命令注入,危害系统)。)


0x08 输出编码原则

   1. ​​​​​​​对于不可信的数据,输出到客户端前必须先进行HTML编码(不可信的数据(也就是其他业务系统生成的未经本应用程序验证的表数据或文件数据),通过对输出到客户端的数据进行编码,可以防止浏览器将HTML视为可执行脚本,从而防止跨站脚本攻击)。

   2. ​​​​​​​必须在服务器端采用白名单方式对上传或下载的文件类型、大小进行严格的限制。

   3. ​​​​​​​禁止以用户提交的数据作为读/写/上传/下载文件的路径或文件名,以防止目录跨越和不安全直接对象引用攻击。(建议对写/上传文件的路径或文件名采用随机方式生成,或将写/上传文件放置在有适当访问许可的专门目录。对读/下载文件采用映射表(例如,用户提交的读文件参数为1,则读取file1,参数为2,则读取file2)。防止恶意用户构造路径和文件名,实施目录跨越和不安全直接对象引用攻击)。

   4. ​​​​​​​禁止将敏感文件(如日志文件、配置文件、数据库文件等)存放在Web内容目录下。Web内容目录指的是:通过Web可以直接浏览、访问的目录,存放在Web内容目录下的文件容易被攻击者直接下载。


0x09 其他原则

   1. ​​​​​​​应用程序出现异常时,禁止向客户端暴露不必要的信息,只能向客户端返回一般性的错误提示消息。(应用程序出现异常时,禁止将数据库版本、数据库结构、操作系统版本、堆栈跟踪、文件名和路径信息、SQL查询字符串等对攻击者有用的信息返回给客户端。建议重定向到一个统一、默认的错误提示页面,进行信息过滤)。

   2. ​​​​​​​应用程序捕获异常,并在日志中记录详细的错误信息。记录详细的错误消息,可供入侵检测及问题定位。

   3. ​​​​​​​在注释信息中禁止包含物理路径信息、数据库连接信息、SQL语句信息、源代码信息。

   4. ​​​​​​​对于动态页面不使用普通注释,只使用隐藏注释。动态页面包括ASP、PHP、JSP、CGI等由动态语言生成的页面。通过浏览器查看源码的功能,能够查看动态页面中的普通注释信息,但看不到隐藏注释(隐藏注释不会发送给客户端)。因此,为了减少信息泄漏,建议只使用隐藏注释。

   5. ​​​​​​​版本归档时,必须删除开发过程(包括现场定制)中的临时文件、备份文件、无用目录等。(恶意用户可以通过URL请求诸如.bak之类的文件,Web服务器会将这些文件以文本方式呈现给恶意用户,造成代码的泄漏,严重威胁Web应用的安全)。

   6. ​​​​​​​归档的页面程序文件的扩展名必须使用小写字母。(很多Webserver对大小写是敏感的,但对后缀的大小写映像并没有做正确的处理。攻击者只要在URL中将JSP文件后缀从小写变成大写,Web服务器就不能正确处理这个文件后缀,而将其当作纯文本显示。攻击者可以通过查看源码获得这些程序的源代码。因此,归档的页面程序文件的扩展名必须使用小写字母,如jsp、html、htm、asp等页面程序文件的扩展名分别为jsp、html、htm、asp)。

   7. ​​​​​​​归档的程序文件中禁止保留调试用的代码。(这里的“调试用的代码”是指开发过程中进行临时调试所用的、在Web应用运行过程中不需要使用到的Web页面代码或servlet代码。例如:在代码开发过程中为了测试一个添加帐号的功能,开发人员临时编写了一个JSP页面进行测试,那么在归档时,该JSP页面必须删除,以免被攻击者利用)。

   8. ​​​​​​​对于JSP语言,所有servlet必须进行静态映射,不允许通过绝对路径访问。
说明:在web.xml文件中为servlet配置URI映射,使用servlet时,引用它的URI映射,而不允许通过绝对路径访问。

   9. ​​​​​​​对客户端提交的表单请求进行合法性校验,防止跨站请求伪造攻击。

   10. ​​​​​​​使用.innerHtml时,如果只是要显示文本内容,必须在innerHTML取得内容后,再用正则表达式去除HTML标签,以预防跨站脚本。使用.innerHtml会将内容以HTML显示,容易被利用,导致跨站脚本。

   11. ​​​​​​​禁止使用eval()函数来处理用户提交的字符串。eval()函数存在安全隐患,该函数可以把输入的字符串当作JavaScript表达式执行,容易被恶意用户利用。

   12. ​​​​​​​关闭登录窗体表单中的自动填充功能,以防止浏览器记录用户名和口令。(浏览器都具有自动保存用户输入数据和自动填充数据的能力。为了保障用户名和口令的安全,必须关闭自动填充选项,指示浏览器不要存储登录窗口中用户名、口令等敏感信息)。

   13. ​​​​​​​防止网页被框架盗链或者点击劫持。框架盗链和点击劫持(ClickJacking)都利用到框架技术。

   14. ​​​​​​​禁止使用phpinfo()。phpinfo()函数提供了详细的服务器PHP环境配置信息,是PHP提供的一个比较方便的排错工具。但是往往因为开发人员的一时疏忽,把带有phpinfo()的页面部署到生产环境上,造成严重的信息泄露,给潜在攻击者提供了很大的便利。因此在生产环境中应禁止使用phpinfo()函数,以避免不必要的安全隐患。

   15. ​​​​​​​PHP中禁止使用exec()、passthru()、popen()、proc_open()、system()、shell_exec()、pcntl_exec(),如非得使用,必须对输入参数进行严格的输入校验(如:长度、范围、类型校验),并使用escapeshellcmd()、escapeshellarg()函数对其参数进行转义处理。
说明:这些是PHP用于调用底层系统命令的函数,如对其参数过滤不严,将容易导致“系统命令执行”漏洞,使黑客轻易地执行系统命令并获得服务器的shell权限。另外所谓的webshell会通过这些函数跟底层系统进行交互,因此关闭这些函数可有效地降低webshell的安全威胁。

   16. ​​​​​​​PHP中在使用include()、include_once()、require()、require_once()、show_source()、highlight_file()、readfile()、file_get_contents()、fopen()、file()等文件读取函数时,应对参数进行严格的合规性检查,避免直接使用客户端输入作为参数,必要时应进行白名单限制。对这些函数的参数检查不严会很容易导致远程命令执行漏洞,给系统带来不必要的安全隐患。

   17. ​​​​​​​PHP中避免使用preg_replace()函数。当使用/e修饰符,preg_replace会将replacement参数当作PHP代码执行,如使用不当将容易引入漏洞,建议使用preg_match()替代。

   18. ​​​​​​​PHP中明确使用GET、_GET、 
GET、_POST、COOKIE而不是_COOKIE而不是 COOKIE而不是_REQUEST获取用户请求数据,这有助于降低漏洞被成功利用的概率

   19. ​​​​​​​使用主流Web安全扫描工具扫描Web服务器和Web应用,不存在“高”级别的漏洞。

   20. ​​​​​​​预防、监测和反应:一个强壮的系统也需要一套攻击侦测机制。

   21. ​​​​​​​分层防御:Web应用程序是用户和系统中最后的屏障,故一定要注意后台系统的保护。如对输入进行强制认证,保护数据库等。

   22. ​​​​​​​注意故障模式:注意发送给用户的错误信息。信息必须很含糊,但系统要有一份清晰的记录。

   23. ​​​​​​​注意应用程序拒绝服务:拒绝服务DoS(Denial of Service)一般基于网络。但开发人员的失误也可能导致信息具有DoS的可能性。如果没有自动解锁机制,或为匿名连接储存数据等都可以轻易导致DoS。

   24. ​​​​​​​防火墙也不能确保安全:可以阻止一部分访问,减少服务器和网络攻击面,但通常不能对任何应用程序安全相关问题起到作用。


虽然我们生活在阴沟里,但依然有人仰望星空!


发布了178 篇原创文章 · 获赞 75 · 访问量 10万+

猜你喜欢

转载自blog.csdn.net/God_XiangYu/article/details/103138755