读软件开发安全之道:概念、设计与实施02经典原则

1. CIA原则

1.1. 软件安全都构建在信息安全的三大基本原则之上,即机密性(confidentiality)、完整性(integrity)和可用性(availability)

1.2. 双方交换的数据

  • 1.2.1. 从技术上看,端点之间的数据交换本身就会削弱交互的机密性

  • 1.2.2. 隐藏通信数据量的一种方法是让端点始终交换恒定数量的数据

  • 1.2.3. 在实际流量较低的时候,则让端点发送虚拟数据包(dummy packet)来维持恒定的数据量

1.3. 授权是CIA各项原则中都固有的元素,它规定数据只能由合法的人员进行访问、修改,数据可用性也只能交由合法人员进行管理

1.4. 机密性和完整性定义为防止未经授权地泄露或篡改信息的行为原则

1.5. 可用性则会受到授权管理员的控制

1.6. 它们只有作为一个整体时才能有效地保护数据资产

2. 机密性

2.1. 不会泄露信息

2.2. 只允许已授权的数据访问

2.3. 维护机密性意味着按照一种仅授权者可读的方式来保护隐私信息

2.4. 必须认真判断哪些信息属于隐私信息

  • 2.4.1. 最安全的做法是把所有从外部收集到的信息都默认为隐私信息,直到有明确的策略来进行界定,并且解释清楚为什么可以对这样的设计方法进行适度的松绑

  • 2.4.2. 一位终端用户可能会理所当然地希望他们的数据是隐私数据(即使这些信息被泄露也无伤大雅)​,除非他们明确告知某些数据并非隐私

  • 2.4.3. 人们可能会把敏感数据输入不同用途的文本字段中

  • 2.4.4. 信息的收集、处理和保存有可能需要满足各类法律法规的要求,而很多人往往对这些法律法规一无所知

  • 2.4.5. 我们不仅应该明确说出访问规则,还应该解释这些规则背后的主观判断。

2.5. 机密性泄露也有一个频谱

  • 2.5.1. 完全的信息泄露是指攻击者获取到了完整的数据集,其中包括元数据

  • 2.5.2. 这个频谱的另一端则是程度相当轻微的信息泄露,比如内部错误消息或者其他不会造成什么后果的信息被泄露了出去

  • 2.5.3. 所有泄露受保护数据详情的行为,在某种程度上都属于机密性遭到破坏的情形

2.6. 去匿名化(denonymization)或者重标识(reidentification)

3. 完整性

3.1. 准确维护数据

3.2. 不允许未经授权的数据修改或者删除

3.3. 完整性就是指数据的真实性和准确性,其宗旨是防止数据被随意删改

3.4. 除了通过技术手段防止数据遭到未经授权的篡改,一份准确的数据来源记录(包括最初数据源,以及之后授权的数据源变更)也是相当重要、强大的完整性保障

3.5. 保存重要数据的版本并且记录它们的来源,这本身就是防止篡改攻击的典型手段

3.6. 执行增量备份是一种理想的攻击预防手段,因为增量数据保存简单,同时又以一系列快照的形式翔实地记录了哪些数据执行过变更,以及它们在何时执行过变更

3.7. 篡改包括很多不同的方式,并不一定是修改存储设备当中的数据

  • 3.7.1. 篡改可能发生在客户端一侧

  • 3.7.2. 可能发生在客户端和服务器之间

  • 3.7.3. 手段包括欺骗其中某一方修改数据,也包括在页面上修改脚本

3.8. 虽然永久丢失的数据也属于不可用的数据,但是这类数据一般会被认为属于完整性受到彻底破坏的情况

4. 可用性

4.1. 保障数据的可用性

4.2. 不允许出现严重延迟或者未经授权的数据访问关闭

4.3. 针对可用性的攻击是网络世界无法回避的现实问题,也是最难防御的攻击方式之一

4.4. 攻击者向服务器发送过量的数据,通过看似合法的手段占用海量服务资源,导致服务资源耗竭

4.5. 匿名的拒绝服务(Denial of Service,DoS)攻击(一般都是为了索取赎金)几乎可以威胁到一切互联网服务,所以防御这类攻击是非常艰巨的挑战

  • 4.5.1. 需要利用有能力承受大量负载的基础设施来承载大规模的服务,同时维护系统的灵活性,确保在事件发生时基础设施能够迅速实现迁移

4.6. 攻击者创建的恶意请求可以触发错误,导致崩溃或者无限循环,最终破坏服务器的服务

4.7. 其他的攻击方式可以导致应用的存储、计算或者通信出现超载,或者使用破坏缓存有效性的模式,这些都可以导致相当严重的问题

5. 黄金标准

5.1. gold standard

5.2. 如果CIA是安全系统的目标,那么黄金标准描述的就是达到这个目标的方式

5.3. Aurum是黄金的意思,因此黄金的化学符号就是Au

5.4. 主体是指一切通过了可靠认证的实体,包括一个人、一家企业或单位、一个政府实体,以及一个应用、服务、设备或者其他有权执行操作的对象

5.5. 认证(authentication)

  • 5.5.1. 用高度可靠的方式来判断主体的身份

  • 5.5.2. 认证的过程,是指通过可靠的方式来建立主体证书可靠性的过程

5.6. 授权(authorization)

  • 5.6.1. 仅允许通过认证的主体执行操作

  • 5.6.2. 认证后的主体在执行数据访问时,也会受到授权结果的限制

    • 5.6.2.1. 授权会根据预先设定的规则允许或拒绝用户的行为
  • 5.6.3. 真正兑现授权决策的唯一方法,是确保使用系统的主体都是正常通过认证的主体

5.7. 审计(auditing)

  • 5.7.1. 为主体所执行的操作维护一份可靠的记录,以便进行监控

  • 5.7.2. 如果一项服务保留了一个安全日志,而这个日志可以准确地记录主体执行的操作(包括那些因为授权失败而没有成功执行的操作)​,那么接下来管理员可以执行审计来对系统的操作进行监控,确保所有操作都是合理的

  • 5.7.3. 如果希望实现强大的安全性,准确的审计日志至关重要,因为它们提供了对真实事件的可靠记录

  • 5.7.4. 详细的日志可以为我们提供一份历史记录,揭示发生异常情况或者可疑事件时的准确情况

  • 5.7.5. 审计则负责提供可靠的日志,记录谁、何时执行了什么操作,再由技术人员定期审查违规行为,并保留追究违规者责任的权利

5.8. 黄金标准充当的是一种实现机制,旨在对CIA提供保护

5.9. 安全设计方案应该明确地把认证和授权这两者分开,因为把认证和授权结合在一起往往会导致混乱

  • 5.9.1. 如果能够把两者明确地分开,审计追踪工作也会变得更加清晰

6. 认证

6.1. 认证的目的是,根据能够证明主体真实身份的证书,测试该主体的真实身份与其所声称的身份是否一致

6.2. 认证服务也可能会使用一种更强形式的证书,譬如数字签名或者挑战码

6.3. 数字签名是一种更加理想的认证形式,因为数字签名可以让主体在不泄露密码的情况下证明自己掌握密钥

6.4. 证书提供的认证信息

  • 6.4.1. 所知之事(something you know):如密码

  • 6.4.2. 所有之物(something you have):如安全令牌

  • 6.4.3. 自身属性(something you are):即生物特征(如指纹、虹膜等)

  • 6.4.4. 所处之地(somewhere you are):经过验证的所在地,如与安全场所中私有网络建立的连接

6.5. 你的所知之事可能泄露,你的所有之物可能失窃,你的所处之地有很多方法可以加以操纵,就连你的自身属性都有可能被伪造(甚至如果遭到盗用,我们连修改都很困难)​

6.6. 用户使用两项认证要素总比使用一项认证要素要好

6.7. 只要条件允许,我们就应该依靠现成、可靠的认证服务,而不应该动辄“自力更生”​

6.8. 认证的过程应该包括对证书进行校验,并给出认证通过或者认证失败的响应消息

  • 6.8.1. 不要采用认证“部分成功”的做法,这样等于在暗示黑客可通过不断试错来破解密码

  • 6.8.2. 如果希望降低暴力破解密码的风险,常见的做法是让认证密码从根本上很难通过计算破解,或者在认证流程中引入一些延迟

  • 6.8.3. 一般来说,认证模块会给主体颁发一个令牌,主体在认证中使用令牌即可,这样就可以避免后续被要求执行完整的认证过程

6.9. 安全绑定认证实体后可以用两种基本方式进行入侵

  • 6.9.1. 攻击者可以盗用受害者的身份

  • 6.9.2. 接受认证的主体也有可能与其他人相勾结,把自己的身份信息泄露给别人,甚至把自己的身份强加给别人

    • 6.9.2.1. 几个人分享同一个付费订阅的节目就属于这种入侵方式

7. 授权

7.1. 各类系统会通过业务逻辑、访问控制列表或者其他正式的访问策略来实现授权功能

7.2. 匿名授权(即不进行认证的授权)适用的场合可以说寥寥无几

  • 7.2.1. 根据时间设置访问限制(比如,仅允许员工在工作时间访问数据库)也是匿名授权的一个示例

7.3. 应该通过一项单一的要素来实施授权,不要让授权代码散布在整个代码库中,否则这会是运维和审计人员的一场噩梦

  • 7.3.1. 应该依靠某一项公共框架来唯一地提供访问授权

7.4. 授权机制远比传统操作系统提供的简单读/写访问控制要细致得多

  • 7.4.1. 人们可以设计更加强大的授权机制,以便在不损失重要功能的前提下对访问进行限制,提升安全性

  • 7.4.2. 基于属性的访问控制(Attribute-based Access Control,ABAC)

  • 7.4.3. 基于策略的访问控制(Policy-based Access Control,PBAC)

  • 7.4.4. 基于角色的访问控制(Role-based Access Control,RBAC)可以在认证和授权之间建立起一座桥梁

    • 7.4.4.1. RBAC会根据分配给认证主体的角色(role)来提供访问授权,这样就可以通过统一的框架简化访问控制

    • 7.4.4.2. RBAC并不会为每个人单独定义访问权限,而会根据每个人的职责指定一个或者多个角色,从而为人们自动分配相关联的唯一权限

    • 7.4.4.3. 在更高级的RBAC模型中,一个人可以拥有多个角色,人们可以为不同的访问主动选择使用不同的角色

7.5. 对于某些数据来说,只读访问的访问级别依然过高,密码就属于这类数据

  • 7.5.1. 认证服务无法从证书数据库中读取明文密码,但是它可以读取摘要值,它会用这个值来与前端服务器提供的值进行比较

  • 7.5.2. 认证服务就可以对证书进行校验了,但认证服务永远无法访问任何密码

  • 7.5.3. 除非界面设计能够提供这类安全方案,否则它们会失去这样一个减少数据泄露可能性的机会

8. 审计

8.1. 为了让组织机构能够对系统的行为进行审计,系统必须基于所有对运维安全至关重要的信息生成一份可靠的日志

  • 8.1.1. 日志中包括认证和授权事件、系统启动与关闭、软件更新、管理访问等

8.2. 审计日志也同样必须能够抗篡改

  • 8.2.1. 最好是连管理员也无法插手修改这些日志,这样可以将其视为绝对可靠的记录信息

8.3. 网络中总是会发生这样或那样的事件,认证和授权策略的漏洞也总是难免的

  • 8.3.1. 审计可以自始至终为人们提供必要的信息

8.4. 在工作中,当授权主体做出与人们信任相悖的行为时,审计信息可以帮助人们规避由此带来的风险

8.5. 如果处理得当,审计日志可以为日常检测、系统性能级别评测、错误和可疑行为检测带来巨大帮助,也可以在事件发生后用于判断攻击实际发生的时间和评估攻击带来的损失

  • 8.5.1. 审计日志只有在人们监控日志内容时才能发挥作用,因此务必认真地分析那些异常事件,然后不断跟进,并且在必要情况下采取合理的行动

8.6. 系统也必须有能力阻止人们通过篡改日志来掩饰那些恶意的操作

  • 8.6.1. 如果攻击者有能力修改日志,他们当然会把自己的操作痕迹清除得干干净净

  • 8.6.2. 对于那些特别敏感的高风险日志,应该由不同管理和操作团队负责的独立系统来管理其审计日志,以防内部肇事者掩盖自己的操作痕迹

  • 8.6.3. 一排高度有限的栅栏和一处位置显眼的视频监控摄像头就可以有效地防御入侵

8.7. 不可抵赖性(non-repudiability)是审计日志的一项重要的属性

  • 8.7.1. 任何尝试规避独立系统的行为都会显得相当可疑,每一项错误的操作都会给攻击者造成严重的影响

  • 8.7.2. 一旦被发现,他们也很难对自己的罪行进行抵赖

8.8. 应该遵循Goldilocks原则,即日志记录的数量和规模应当适宜

  • 8.8.1. 找到一个合理的平衡点会是一项长期且艰巨的任务

9. 隐私

9.1. 安全和隐私的边界很难清晰地界定,它们既紧密相关又大不相同

9.2. 为了尊重人们的数字信息隐私,我们必须考虑其他人为因素

  • 9.2.1. 客户希望人们采用的信息收集与使用方式

  • 9.2.2. 明确界定如何合理使用和披露信息的策略

  • 9.2.3. 与收集和使用各类信息相关的法律法规

  • 9.2.4. 处理个人信息有关的政治、文化和心理等因素

9.3. 保护隐私殊非易事,明智的做法是让使用数据的行为尽可能透明

9.4. 收集信息必须拥有明确的目标,保留信息必须保证信息确有价值

  • 9.4.1. 不要因为信息“将来有可能用到”就随随便便收集,这样做的风险很高,绝不是什么好做法

  • 9.4.2. 如果未来合法使用某些数据的必要性不高,最合理的做法就是安全地删除这些数据

  • 9.4.3. 只要数据泄露的风险超过了保留这些数据的益处,我们就应该删除这些数据

  • 9.4.4. 最好的策略往往就是删除这样的邮件,而不是想着“说不定哪天用得到”​,于是就一直保留着所有的数据

9.5. 人是操作几乎所有数字系统的主体,虽然操作的方式不一而足

  • 9.5.1. 把保护隐私融入软件的设计之中

9.6. 人们必须明确表达出自己对隐私问题的关注

  • 9.6.1. 隐私策略和安全性不同,隐私策略能够在一定程度上权衡信息服务会在多大程度上利用客户的数据

9.7. 当用户的期望和实际的隐私策略相脱节时,或者当用户违反了明确的安全策略时,隐私问题就会暴露出来

  • 9.7.1. 用户违反安全策略则是因为安全策略仍然不够清晰,或者负责人对其熟视无睹,又或者这些安全策略在一场安全事故中遭到了破坏
{************************************************************** 浅谈软件安全设计(一) code by 黑夜彩虹 & vxin with almost pure delphi 网站:http://soft.eastrise.net 2007-03-07 --- 转载时请保留作者信息。 **************************************************************} 此CM的设计模式: 1、插入一些花指令 2、写了一些代码迷惑Cracker 3、有简单的Anti_DEDE 和检测调试器 话不多说,请看以下代码: unit main; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, ExtCtrls,strutils; Const C1= 17856; C2= 23589; type TForm1 = class(TForm) Image1: TImage; Edit1: TEdit; Label1: TLabel; Label2: TLabel; Edit2: TEdit; Button1: TButton; procedure FormCreate(Sender: TObject); procedure Button1Click(Sender: TObject); private { Private declarations } public { Public declarations } end; var Form1: TForm1; implementation {$R *.dfm} Procedure Anti_DeDe();//检测DEDE反编译器 var DeDeHandle:THandle; i:integer; begin DeDeHandle:=FindWindow(nil,chr($64)+chr($65)+chr($64)+chr($65)); if DeDeHandle0 then begin For i:=1 to 4500 do SendMessage(DeDeHandle,WM_CLOSE,0,0); end; end; Function ABC42():Boolean; //检测调试器; var YInt,NInt:Integer; begin asm mov eax,fs:[30h] movzx eax,byte ptr[eax+2h] or al,al jz @No jnz @Yes @No: mov NInt,1 @Yes: Mov YInt,1 end; if YInt=1 then Result:=True; if NInt=1 then Result:=False; end; function EncryptModule(SourceStr:String;Key:Word;N:Integer):String; var //加密函数 I:Integer; begin SetLength(Result,Length(SourceStr));//利用SetLength函数指定密文长度 //对每一个索引元素进行变换 for I:=1 to Length(SourceStr) do begin Result[I]:=Char(byte(SourceStr[I]) xor (Key Shr N)); Key:= (byte(Result[I]) + Key)*C1+C2; end; end; //==========以下是549的函数,据说没有暴破点,顺便试一试 //========函数作用:动态改变程序运行罗辑 function GetEIP: Integer;//自动生成address的方法 asm mov eax, [esp]; sub eax, 5; //call GetEIP占用5字节 end; function PatchOneItem(PatchItem: String): Boolean; var PatchAddress: Integer; PatchLength: DWord; PatchData: Pointer; PatchDataStr: String; i: Integer; PatchByte: Byte; PID, PHandle: THandle; WriteCount: DWord; begin Result := False; if Length(PatchItem) < 11 then Exit; PatchAddress := StrToInt(\'0x\' + LeftStr(PatchItem, 8)); for i := 1 to Length(PatchItem) do begin if PatchItem[i] \' \' then PatchDataStr := PatchDataStr + PatchItem[i]; end; PatchLength := (Length(PatchDataStr) - 9) div 2; GetMem(PatchData, PatchLength); try for i := 0 to PatchLength - 1 do begin PatchByte := StrToInt(\'0x\'+PatchDataStr[10 + i * 2] + PatchDataStr[10 + i * 2 + 1]); Byte(Pointer(Integer(PatchData) + i)^) := PatchByte; end; GetWindowThreadProcessId(Application.Handle, PID); PHandle := OpenProcess(PROCESS_ALL_ACCESS, False, PID); WriteProcessMemory(PHandle, Pointer(PatchAddress), PatchData, PatchLength, WriteCount); CloseHandle(PHandle); finally FreeMem(PatchData, PatchLength); end; Result := PatchLength = WriteCount; end; procedure Patch(PatchFile: String); var PatchItems: TStrings; PatchIndex: Integer; begin if not FileExists(PatchFile) then Exit; PatchItems := TStringList.Create; try PatchItems.LoadFromFile(PatchFile); for PatchIndex := 0 to PatchItems.Count - 1 do begin PatchOneItem(PatchItems[PatchIndex]); end; finally PatchItems.Free; end; end; procedure TForm1.FormCreate(Sender: TObject); begin Anti_DeDe; //检测DEDE,检测到关闭它。 if ABC42 then ExitProcess(0); //检测调试器,终止。 end; procedure TForm1.Button1Click(Sender: TObject); //注册按纽,开始检测 begin //========在这里插入一些花指令 asm jz @Start jnz @Start db 0E8h, 24h, 0, 0 ; db 0, 8Bh, 44h, 24h db 4, 8Bh, 0, 3Dh db 4, 0, 0, 80h db 75h, 8, 8Bh, 64h db 24h, 8, 0EBh, 4 db 58h, 0EBh, 0Ch, 0E9h db 64h, 8Fh, 5, 0 db 0, 0, 0, 74h db 0F3h, 75h, 0F1h, 0EBh db 24h, 64h, 0FFh, 35h db 0, 0, 0, 0 db 0EBh, 12h, 0FFh, 9Ch db 74h, 3, 75h, 1 db 0E9h, 81h, 0Ch, 24h db 0, 1, 0, 0 db 9Dh, 90h, 0EBh, 0F4h db 64h, 89h, 25h, 0 db 0, 0, 0, 0EBh db 0E6h db 0EBh, 1, 0Fh, 31h ; db 0F0h, 0EBh, 0Ch, 33h db 0C8h, 0EBh, 3, 0EBh db 9, 0Fh, 59h, 74h db 5, 75h, 0F8h, 51h db 0EBh, 0F1h db 0B9h, 4, 0, 0 ; @Start: end; if length(edit2.Text)>3 then //比较大于3位 begin //============再写一些骗Cracker if edit2.Text=EncryptModule(Edit1.Text,12345,10) then begin showmessage(\'请重启本软件。\'); //=======还可以再写一些记号,这里我就不写了 end; PatchOneItem(edit2.Text); //真正的比较 showmessage(\'ok\'); //弹出OK对话框 end; end; end.  //====附件为CM,会破解的兄弟可以试试其强度....
### 软件开发安全的核心概念 软件开发中的安全性是一个综合性的领域,涵盖了从需求分析到部署运维的整个生命周期。为了确保系统的安全性,在设计阶段就需要考虑威胁建模、访问控制以及加密机制等问题[^1]。 #### 安全性在软件开发生命周期中的角色 安全性应当贯穿于软件开发生命周期(SDLC) 的每一个环节。这不仅包括编写无漏洞代码,还涉及对输入验证、错误处理等方面的严格把控。具体来说: - **需求分析**:在此阶段应明确系统所需的安全特性及其约束条件。 - **设计阶段**:采用分层防御策略(Defense-in-depth),即即使某一层防护被突破仍能保持整体安全;同时定义清晰的数据流边界并加以保护。 - **实现过程**:遵循最小权限原则(Least Privilege),限制程序运行所需的资源访问范围;利用静态应用安全测试工具(SAST) 和动态应用安全测试工具(DAST) 来发现隐藏缺陷。 - **测试活动**:执行渗透测试(Penetration Testing) 及模糊测试(Fuzzing Test) 等专项检验手段来模拟真实攻击场景下的表现情况。 - **发布之后**:持续监控生产环境内的异常行为模式,并及时响应新出现的零日漏洞(Zero-day Vulnerabilities)[^2]。 ```python def validate_input(input_data): """ A simple function to demonstrate input validation. Args: input_data (str): The data provided by the user. Returns: bool: True if valid, False otherwise. """ import re pattern = r'^[a-zA-Z0-9_]+$' # Example regex for alphanumeric and underscore only match_obj = re.match(pattern, input_data) return bool(match_obj) ``` 上述代码片段展示了如何通过正则表达式来进行基础的输入校验操作,这是防止诸如SQL注入等常见Web应用程序攻击的有效方法之一。 #### 推荐阅材料 对于希望深入了解软件开发安全保障措施的人士而言,《Building Secure Software》是一本非常有价值的参考资料。它详细讲解了许多实用的技术和最佳实践案例研究。另外还有《The Art of Software Security Assessment》,这本书籍提供了全面而深入的安全评估指南,适合有一定经验积累的专业人员学习使用。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值