安全编程复习
网络安全编程技术
第一章 绪论
1.2 软件安全性
- 安全编程的概念
- 安全的程序是在任何输入输出接口时,都能够正确执行自己的既定任务
- 安全程序不损害它运行系统的本地安全策略
- 程序员的职责是保证程序可以正常的执行任务
1.3 安全原则
- 原则1:加固最脆弱的环节
- 原则2:纵深防御
- 原则3:故障保护
- 原则4:最小特权
- 原则5:分隔
- 原则6:简单化
- 原则7:提高保密性
- 原则8:难以隐藏秘密
- 原则9:不要轻信
- 原则10:利用社会资源
1.4 安全软件构建
- 设计系统时要有安全性观念
- 根据已知和预期的风险分析系统
- 根据严重性划分风险等级
- 进行风险测试
- 从设计过程开始对破坏的系统重复以上步骤
1.5 安全编程
- 1、警惕和验证输入
- 检查接收到的每一条数据是安全的程序中的第一道防线。
- 所有的数据必须在使用之前被检查
- 2、防止缓冲区溢出
- 3、安全调用组件
- 只使用安全组件、只传递有效数据,确保数据可以正确进行处理,检查返回值和异常情况,并且当数据在应用程序和组件之间传递时对数据进行保护
- 4、避免竞争条件
- 当由于事件次序异常而造成对同一资源的竞争,从而导致程序无法正常运行时,就会出现“竞争条件”。
- 如果一个外部的攻击者可以通过意想不到的方式干扰程序,那么就会出现很多安全问题。
- 5、最小化特权
- 安全的程序必须最小化特权,以降低 bug 转化为安全缺陷的可能性。
第二章 内存安全
2.1 堆栈缓冲区溢出
- 缓冲区:一块连续的计算机内存区域,可以保存相同数据类型的多个实例。
- 在C的字符数组中,静态变量在程序加载时定位于数据段,动态变量在程序运行时定位于堆栈之中。
- 缓冲区溢出问题主要是针对动态缓冲区的溢出问题,即基于堆栈的缓冲区溢出。
- 堆栈缓冲区是进程在内存中运行时的分配的一部分区域。实际上,进程在内存中运行时,被分成三个区域:
- 程序代码区;
- 静态存储区;
- 动态存储区(堆栈)。
- 程序运行时,代码在内存中分别存储在5个段中
- Code:代码段
- Data :数据段
- BSS段
- Heap:堆段
- 存储程序其他变量
- 大小可变
- 从存储器低地址向高地址增长
- 应用程序分配,分配器和回收器算法管理:
- 在C中malloc和free函数如p1= (char*)malloc(10),free(p1);在C++中用new和delete运算符。如p2 = new char[10],delete [] p2
- Stack:堆栈段
- LIFO
- 存储函数调用间的数据,以及局部变量
- 大小可变
- 从存储器高地址向低地址增长
- 由系统自动分配
- 例如,函数内部定义一个变量 int b,系统自动在堆栈中为b开辟空间
示例:
int a = 0 ; //全局初始化区(data)
char *p1 ; //全局未初始化区(bss)
main()
{
int b; //栈(stack)
char s[] = “abc”; //栈(stack)
char *p2; //栈(stack)
static int c =0; //全局初始化区(data)
p1 = (char *)malloc(t); //堆区(heap)
p2 = (char *)malloc(20); //堆区(heap)
}
- 堆和堆栈功能
- 堆栈用来辅助执行程序:在函数调用时,保存返回环境(函数调用语句的下一条可执行语句的地址、堆栈指针)和函数参数(多数C编译器中,参数是由右往左入栈的,是函数中的局部变量)、局部变量。
- 堆主要用来存放对象,像储物堆。
- 缓冲区溢出基本思想:
- 向缓冲区写入超长数据,使其超过缓冲区的边界,直至覆盖返回地址,从而使得程序的执行流程发生改变。
- 攻击者将一段恶意可执行代码(通常称之为shell-code)放入缓冲区中,同时改变函数返回地址使之指向这段可执行代码。
- 通过修改某些内存区域,把一段恶意代码存储到一个buffer中,并且使这个buffer被溢出,以便当前进程被非法利用(执行这段恶意的代码)
stackOverflow
堆栈缓冲区溢出- 函数调用时,完成如下操作:
- 1.函数参数入栈
- 2.指令寄存器(EIP)中的内容作为返回地址入栈
- 3.压入基址寄存器(EBP)
- 4.EBP (ESP)
- 5.为函数内本地变量分配空间
- 发生原因:
- 由于输入的字符串太长,数组buffer容纳不下,但是也要将多余的字符写入堆栈。这些多余的字符没有分配合法的空间,就会覆盖堆栈中以前的内容。如果覆盖的内容仅仅是一些普通数据,表面上也不会出什么问题,只是会造成原有数据的丢失。
- 但是,堆栈中还有一块区域专门保存着指令指针,存放下一个CPU指令存放的内存地址(你可以理解为某个函数的地址)。如果该处被覆盖,系统会错误地将覆盖的新值当成某个指令来执行。如上面的例子中,刚好是"3456"(0x36353433)覆盖了那一片区域,系统会将"3456"(0x36353433)的 ASCII 码视作返回地址,认为程序接下来要执行的是0x36353433所指向的那个函数,因此试图执行0x36353433处的指令,出现难以预料的后果,程序出错退出。
- 但是,仅仅让程序出错退出并没有什么用。如果将该处的内容不用"3456"覆盖,而用某一个函数的地址覆盖,我们就可以运行那个函数了
- 函数调用时,完成如下操作:
- 防范缓冲区溢出
- 引入新的、安全的函数,取代旧的、有缺陷的函数;
- 插入保护码(在返回地址和局部变量之间插入,被攻击时会先覆盖保护码);
- 将堆栈设置为不可执行的。
- 解决缓冲区溢出的方法
- 1:积极检查边界。
- 2:不让攻击者执行缓冲区内的命令。
- 3:编写风格良好的代码。
- 4:程序指针检查。
2.2 整数溢出
- 原理:由于整数在内存里面保存在一个固定长度的空间内,它能存储的最大值就是固定的,当尝试去存储一个数,而这个数超出能够存储的数值范围,将会导致整数溢出。
- 解决整数溢出
- 主要是编程之前必须进行详细的预测,多考虑一些问题, 在编程时将各种问题考虑到并且进行相应的处理。如:
- 充分考虑各种数据的取值范围,使用合适的数据类型;
- 尽量不要在不同范围的数据类型之间进行赋值;等等。
- 主要是编程之前必须进行详细的预测,多考虑一些问题, 在编程时将各种问题考虑到并且进行相应的处理。如:
第三章 线程/进程安全
-
进程就是一个程序,线程是这个程序能够同时做的各件事情。
- 进程是程序在计算机上的一次执行活动。通俗地讲,是一个正在执行的程序。
- 线程是进程中的一个实体,是被系统独立调度和分派的基本单位,它与其它线程共享进程的资源。
-
多线程:让应用程序看起来好像同时能做好几件事情。
-
线程同步:
- 发出一个功能调用时,在没有得到结果之前,该调用就不返回,同时其它线程也不能调用这个方法。
- synchronized
- 该方法的本质是将需要独占CPU的代码用synchronized(this)包围起来。一个线程进入这段代码之后,就在this上加了一个标记(同步锁),直到该线程将这段代码运行完毕,才释放这个标记。如果其他线程想要抢占CPU,先要检查this上是否有这个标记。若有,就必须等待。
-
线程协作:
- 多个线程合作完成一件事情时,线程之间实现了协作。
- 解决方案:在运行一个线程时,命令其他线程等待该线程运行完毕,才能抢占CPU进行运行。
-
死锁(DeadLock)
- 两个或两个以上的线程在执行过程中,因争夺资源而造成的一种互相等待的现象。此时称系统处于死锁状态,这些永远在互相等待的线程称为死锁线程。
- 死锁四个必要条件:
- 互斥条件
- 请求与保持条件
- 不剥夺条件
- 循环等待条件
-
死锁排除:
- 可以撤消陷于死锁的全部线程。
- 可以逐个撤消陷于死锁的进程,直到死锁不存在。
- 从陷于死锁的线程中逐个强迫放弃所占用的资源,直至死锁消失。
-
线程生命周期中的安全问题
- 线程暂停或者终止时,某些资源的锁并没有释放,它所保持的资源保持锁定状态;
- 线程暂停之后,由于无法预计它什么时候会继续,如果对某个资源的锁长期被保持,其他线程在任何时候都无法再次访问该资源,极有可能造成死锁。
-
一个进程可以包含若干线程,线程可以帮助应用程序同时做几件事。进程也有运行、阻塞、就绪三种状态,并随一定条件而相互转化。
第四章 异常/错误处理中的安全
- 程序开发过程中可能出现的问题有如下几种:
- 编译错误,即语法错误。如果使用了错误的语法、函数、结构和类,程序就无法被生成运行代码。
- 在运行时发生的错误,它分为不可预料的逻辑错误和可以预料的运行异常。
- 异常处理处理的是可以预料的运行异常,属于运行错误。
- 主要是针对程序语法没有问题时,在运行的过程中出现的突发情况。
- 异常处理中捕获(catch)异常有两种方法捕获:
- 就地捕捉异常(try-catch-finally);
- 将异常向前端(调用方)抛出。
- try-catch-finally结构
- 过程:
- 1:用try块将可能出现异常的代码包起来;
- 2:用catch块来捕获异常并处理异常;
- 3:如果有一些工作是不管异常是否出现都要执行的,则将相应的代码用finally块将其包起来。
- 对于try-catch-finally结构,有如下规定:
- 一个try后面必须至少接一个catch块;
- try后面可以不接finally块;
- try后面最多只能有一个finally块。
- try块后可接多个catch块,可用某一个catch用于捕获某种异常。
- 单个catch块时,代码的运行机制变为:
- 当程序中出现异常时,try块后剩余的的内容不执行,转而执行catch块;
- 不管是否出现异常,catch块是否执行,都在最后执行finally块。
- 多个catch块时,代码的运行机制变为:
- 当try块内的代码如果出现异常,程序则在catch块内寻找匹配的异常catch块,进行处理;
- 然后运行finally块。
- 在异常处理机制中,可以加入一个catch块来处理其他不可预见的异常,即catch(Exception ex)。
- catch(Exception ex)必须写在catch块的最后一个,以保证只有前面无法处理的异常,才被这个块处理。
- finally块在保证系统的可靠性方面,并不是可有可无的:
- finally最大的特点就是:在try块内即使跳出了代码块,甚至跳出函数,finally内的代码仍然能够运行。
- 不管程序在try或者catch内如何跳转,只要执行了try,他所对应的finally一定会执行。
- 单个catch块时,代码的运行机制变为:
- 过程:
第五章 输入安全
- 输入是一个很广泛的概念,既是用户和软件之间的交互手段,也是软件内部模块之间的交互手段。
- 软件用户的输入有很多类型,如:
- 用户在软件上输入一个命令,进行相应操作;
- 用户输入自己的账号密码,进行登录验证;
- 用户输入一个关键字,进行查询;等等。
- 模块之间进行数据传递时,也会有相应输入,如:
- 一个模块调用另一个模块时,输入一些参数;
- 一个模块读取一个配置文件,来对自己的行为进行配置等等。
- 软件用户的输入有很多类型,如:
- 正则表达式
- 字符表达式
\d
:0~9的数字;\w
:任意一个字母或数字或下划线;\s
:包括空格、制表符、换页符等空白字符的其中任意一个;.
:匹配除换行符\n
以外任意一个字符。- eg.1:表达式
\d\d
,在匹配 “abc123”- 匹配到的内容是:"12";匹配到的位置是:开始于3,结束于5。
- eg.2:表达式
a.\d
,在匹配 “aaa100”- 匹配到的内容是:"aa1";匹配到的位置是:开始于1,结束于4。
- 简单的转义字符
\r
,\n
:代表回车和换行符;\t
:制表符;- 一些不便书写的或有其他特殊用途的字符,在前面加
\
后,就代表该符号本身。转义字符的匹配方法与 "普通字符" 类似的。也匹配与之相同的一个字符。\\
:代表\
符号本身;\^
:代表^
符号本身;\$
:代表$
符号本身;\.
:代表.
符号本身
- eg.:表达式
\$d
,匹配字符串abc$de
- 匹配到的内容是:
$d
;匹配到的位置是:开始于3,结束于5。
- 匹配到的内容是:
- 自定义‘多种字符’ 表达式
- 方括号
[ ]
包含一系列字符,能够匹配其中任意一个字符 - 用
[^ ]
包含一系列字符,则能够匹配其中字符之外的任意一个字符[ab5@]
:匹配a
或b
或5
或@
;[f-k]
:匹配f~k
之间的任意一个字母;[^abc]
:匹配a,b,c
之外的任意一个字符;[^A-F0-3]
匹配A~F
,0~3
之外的任意一个字符。
- eg.1:表达式
[bcd][bcd]
, 匹配abc123
- 匹配到的内容是:
bc
;匹配到的位置是:开始于1,结束于3。
- 匹配到的内容是:
- eg.2:表达式
[^abc]
,匹配abc123
- 匹配到的内容是:"1";匹配到的位置是:开始于3,结束于4。
- 方括号
- 修饰匹配次数的特殊符号
- 表达式加上修饰匹配次数的特殊符号,不用重复书写表达式就可以重复匹配。
- 使用方法:"次数修饰"放在"被修饰表达式"后边。如:
[bcd][bcd]
写成[bcd]{2}
{n}
:表达式重复n次,如"a{5}" 相当于 "aaaaa";{m,n}
:表达式至少重复m次,最多重复n次,比如:"ba{1,3}"可以匹配 "ba"或"baa"或"baaa";{m,}
:表达式至少重复m次,比如:\w\d{2,}
可以匹配a12
,_456
等;?
:表达式出现0次或者1次,相当于{0,1};+
:表达式至少出现1次,等价于{1,};*
:表达式不出现或出现任意次,相当于{0,}。
- eg.1:表达式
\d+\.?\d*
,匹配 “It costs $12.5”- 匹配到的内容是:"12.5";匹配到的位置是:开始于10,结束于14。
- eg.2:表达式
go{2,8}gle
,匹配 “Ads by goooooogle”- 匹配到的内容是:"goooooogle";匹配到的位置是:开始于7,结束于17。
- 抽象意义的特殊符号
^
:与字符串开始的地方匹配,不匹配字符;$
:与字符串结束的地方匹配,不匹配字符;|
:左右两边表达式之间 "或" 关系,匹配左边或者右边;( )
:- (1).在被修饰匹配次数的时候,括号中的表达式可以作为整体被修饰
- (2).取匹配结果的时候,括号中的表达式匹配到的内容可以被单独得到
- eg.1:表达式 “^aaa” 能匹配 “xxx aaa xxx” ,还是匹配“aaa xxx xxx”?同理,表达式 “aaa$” 能匹配 “xxx aaa xxx” ,还是匹配“xxx xxx aaa”?
aaa xxx xxx
;xxx xxx aaa
。
- eg.2:表达式 “Tom|Jack” 在匹配字符串 “I‘m Tom, he is Jack” 时呢?
- 匹配到的内容是:“Tom”;匹配到的位置是:开始于4,结束于7。
- 匹配下一个时,匹配到的内容是:“Jack”;匹配到的位置时:开始于15,结束于19。
- eg.3:表达式
¥(\d+\.?\d*)
”,匹配 “$10.9,¥20.5”?- 匹配到的内容是:“¥20.5”;匹配到的位置是:开始于6,结束于10。单独获取括号范围匹配到的内容是:“20.5”。
- 字符表达式
- 口令与密钥
- 口令破解的方法:
- 猜测
- 字典攻击
- 暴力破解
- 强口令:
- 密码具有复杂性,至少6个字符,至少来自字符类别中的3种;
- 易于记忆,不易被猜测
- 口令破解的方法:
第六章 国际化安全
-
国际化
- 主要目的:是调整软件,使之能适用于不同的语言及地区。
- 国际化要求软件的业务逻辑和程序源代码不用作改变或修正,但是软件又必须让该地区和语言的用户方便地使用;
-
本地化(localization):实现国际化的一些手段的集合。
- 本地化是为了满足特定地区和特定语言的用户对语言和功能的特殊要求。
- 软件本地化,可能涉及文字的翻译、用户界面布局调整、本地特性开发、联机文档和印刷手册的制作,以及保证本地化版本能正常工作等。
-
国际化和本地化这两个工作,一个是设计思想,一个是工作的手段,互为补充。
-
国际化过程:
- 基础:将文本和其他与环境相关的资源单独编写,和程序代码相分离。
- 1:资源文件。是一个文件,能够保存各种不同语言所对应的资源。
- 2:读取工具。能够根据语言来读取资源文件。
- 3:应用程序。调用读取工具,读取资源文件。
-
国际化安全
- 最重要的问题是不同的语言文字,在不同的系统中具有不同的编码。编码是不同国家的语言在计算机中的一种存储和解释规范,在各个不同规范中,存储了相应字符集。
- 源数据可能来自于不同的字符集(如支持不同字符集的数据库),目标程序所支持的字符集和源数据属于的字符集可能不一致,导致系统显示出错:
- 1:当目标程序所支持的字符集和源数据属于的字符集完全不兼容时,数据无法显示(或者以乱码形式显示)。
- 2: 当目标程序所支持的字符集是源数据属于的字符集的子集时,信息会部分丢失。例如,如果源数据库使用GBK,而目标程序字符集使用GB2312,这个过程中绝大部分字符都能够正确转换,但是由于GB2312字符集小于GBK,因此一些超出GB2312字符集的字符变为乱码。
- I18N缓冲区溢出问题
-
Unicode
- Unicode又称统一码、万国码或单一码,是国际组织制定的可以容纳世界上所有文字和符号的字符编码方案。
- 作为一种在计算机上使用的字符编码,针对每种语言中的每个字符,Unicode为都设定了统一并且唯一的二进制编码。
- Unicode采用16位编码体系,使用两个字节表示一个字符,对于ASCII字符它也使用两字节表示。
- Unicode制定了三套编码方式。分别是UTF-8,UTF-16和UTF-32(使用较少)。因此,如果在开发软件的过程中使用Unicode,并且不将Unicode和其他字符集进行转换,就基本上不会遇到转码过程中的安全问题。
第七章 面向对象编程安全
实例化:
- 类的实例化:
- 类是用于描述同一类型的对象的一个抽象的概念,类中定义了这一类对象所应具有的属性和方法。
- 多个对象的抽象成为类,类的具体化就是对象,通常的说法,创建一个对象实际上就是将类实例化。
- 对象的实例化:对象分配内存,一般叫做对象的实例化。
序列化:
- 对象序列化,是指将对象的状态转换成字节流(当然也可能是字节流以上的一些包装流),在使用的时候,可以通过读取流中的内容,生成相同状态的对象。
- 序列化过程:
- 对象将描述自己状态的数据写出到流中,描述自己状态的数据,一般是成员变量,因此,序列化的主要任务是写出对象成员变量的数值。
- 特殊情况下,如果对象中,某个成员变量是另一对象的引用,则被引用的对象也要序列化,因此,序列化工作是递归的。
第八章 WEB编程安全
URL操作攻击的解决
- 程序员在编写Web程序时,可以从以下方面加以注意:
- 1:为了避免非登陆用户进行访问,对于每一个只有登录成功才能访问的页面,应该进行session的检查;
- 2:为限制访问未授权的资源,可在查询时将用户名也考虑进去。
- 例如在向数据库查询时,就可以首先检查“guokehua”是否在登录状态,然后根据学号(0035)和教师用户名(guokehua)综合进行查询。
页面状态值安全
- 页面传值四种方法:
- URL传值;
- 表单传值;
- Cookie方法;
- session方法。
- URL传值:
- 缺点
- 传输的数据只能是字符串;
- 传输数据的值会在浏览器地址栏里面被看到。
- 优点:具有简单性和平台支持的多样性。
- 缺点
- 表单传值:
- 缺点
- 传输的数据只能是字符串;
- 传输数据的值在客户端源代码里面会被看到;
- 攻击者可以在客户端通过修改源代码来修改任意学生的成绩。
- 优点:具有简单性和平台支持的多样性。
- 缺点
- cookie方法:
- 原理:
- Cookie是一个小的文本数据,由服务器端生成,发送给客户端浏览器,客户端浏览器如果设置为启用cookie,则会将这个小文本数据保存到其某个目录下的文本文件内。
- 客户端下次登录同一网站,浏览器则会自动将Cookie读入之后,传给服务器端。
- 服务器端可以对该Cookie进行读取并验证(当然也可以不读取)。一般情况下,Cookie中的值是以key-value的形式进行表达的。
- 优点:
- 在客户端的浏览器上,看不到任何的和传递的值相关的信息;
- Cookie的值能够持久化,减轻用户一些验证工作的输入负担;
- Cookie可以帮助服务器端保存多个状态信息,但是不用服务器端专门分配存储资源,减轻了服务器端的负担。
- Cookie可以持久保持一些和客户相关的信息,如个性化设置。
- 缺点:
- Cookie是以文件形式保存在客户端的,客户端存储的Cookie文件就可能被获知。
- 如果将用户名、密码等敏感信息保存在Cookie内,在用户离开客户机时不注意清空,这些信息容易泄露,因此Cookie在保存敏感信息方面具有潜在危险。
- Cookie的被盗取方法:
- 利用跨站脚本技术,将信息发给目标服务器;为了隐藏跨站脚本的URL,可以结合Ajax(异步Javascript和XML技术)在后台窃取Cookie;
- 通过某些软件,窃取硬盘下的Cookie;
- 利用客户端脚本盗取Cookie,跨站脚本的一种实现方式。
- cookie安全问题的解决:
- 1:替代cookie。将数据保存在服务器端,可选的是session方案;
- 2:及时删除cookie。要删除一个已经存在的Cookie,有以下几种方法:
- 1:给一个Cookie赋以空值;
- 2:设置Cookie的失效时间为当前时间,让该Cookie在当前页面的浏览结束后就被删除;
- 3:通过浏览器删除Cookie。如IE中,在Internet选项中删除Cookies;
- 4:禁用Cookie。
- 原理:
- session方法
- session:指某个用户在网站上的有始有终的一系列动作的集合。
- 原理:
- 在不考虑服务器负载的情况下,将数据保存在服务器端。
- session中的数据可以被同一个客户在网站的一次会话过程共享。但是对于不同客户来说,每个人的session是不同的。
- 在客户进行第一次访问时,服务器端就给session分配了一个sessionId,并且让客户端记住了这个sessionId,客户端访问下一个页面时,又将sessionId传送给服务器端,服务器端根据这个sessionId来找到前一个页面用的session,保证为同一个客户服务的session对象是同一个。
- 编程方面session安全的解决:session检查,过滤;
- 防止sessionId泄露安全问题:
- 1:在服务器端,可以在客户端登陆系统时,尽量不要使用单一的sessionId对用户登陆进行验证。可以使用动态sessionId;
- 2:在客户端,应该在浏览器关闭时删除服务器端的session,在关闭时必须通知服务器端。最简单的方法,可以用Javascript实现。
- xss攻击
- 攻击者为了得到客户的隐秘信息,在网站中通过一些手段放入一段可以执行的代码,吸引客户执行(通过鼠标点击等);客户点击后,代码执行,可以达到攻击目的。
- XSS可以诱使Web站点执行本来不属于它的代码,而这些行代码由攻击者提供、为用户浏览器加载,攻击者利用这些代码执行来获取信息。
sql注入攻击
- 攻击者通过对数据库的恶意输入,可以将信息注入正在运行的流程,获取敏感数据,甚至危害进程的运行状态。
- 常见sql操作:
- SELECT - 从数据库表中获取数据
- UPDATE - 更新数据库表中的数据
- DELETE - 从数据库表中删除数据
- INSERT INTO - 向数据库表中插入数据 - 针对SELECT的注入攻击:
- 客户输入账号为:“ aa‘ OR 1=1 --”,密码随便输入,如“aa”:
- SQL语句变为:
SELECT * FROM USERS WHERE ACCOUNT='aa' OR 1=1 --' AND PASSWORD='aa'
- 其中,--表示注释,因此,真正运行的SQL语句是:
SELECT * FROM USERS WHERE ACCOUNT='aa' OR 1=1
- 此处,“1=1”永真,所以该语句将返回USERS表中的所有记录。网站受到了SQL注入的攻击。
- SQL语句变为:
- 客户输入账号为:“ aa‘ OR 1=1 --”,密码随便输入,如“aa”:
- 使用通配符进行注入
- 客户输入
%‘--
- SQL语句变为:
SELECT * FROM STUDENTS WHERE STUNAME LIKE '%%'--%'
- 真正运行的SQL语句是:
SELECT * FROM STUDENTS WHERE STUNAME LIKE '%%'
- SQL语句变为:
- 或输入
%';DELETE FROM STUDENTS --
SELECT * FROM STUDENTS WHERE STUNAME LIKE '%%';DELETE FROM STUDENTS --%'
- 达到删除表STUDENTS中所有的内容的目的。
- 客户输入
- 针对DELETE语句的注入攻击
- 输入
Java‘ OR 1=1 --
,构造永真式; - SQL语句变为
DELETE FROM BOOKS WHERE BOOKNAME=' Java' OR 1=1 --'
- 即
DELETE FROM BOOKS WHERE BOOKNAME=' Java' OR 1=1
,将表中所有内容删除。
- 输入
- 针对UPDATE语句的注入攻击
- cname和account为输入的变量;
- 输入cname的值为:“ guokehua‘, PASSWORD=’111‘ --”,account随便输入,如“111”;
- SQL语句变为:
UPDATE CUSTOMER SET CNAME ='guokehua', PASSWORD='111' --' WHERE ACCOUNT='111'
- 将所有记录的CNAME改为guokehua,密码改为111。
- 针对INSERT语句的注入攻击
String sql = "INSERT INTO CUSTOMER VALUES('" + account +"', '" + password +"', '" +cname +"', 0) "
,最后一个字段为账户money字段,默认为0;- 输入
0001
,akbj
,cname的值为:guokehua‘, 1000) --
INSERT INTO CUSTOMER VALUES('0001', 'akdj', ' guokehua', 1000) --',0)
- 注册一个账号,默认的MONEY字段变成了1000。
- sql注入攻击防范方法
- 1:将输入中的单引号变成双引号;
- 2:使用存储过程,将查询功能写在存储过程prcGetCustomer内;
- 3:认真对表单输入进行校验,从查询变量中滤去尽可能多的可疑字符;
- 4:在程序中,组织SQL语句时,应该尽量将用户输入的字符串以参数的形式来进行包装,而不是直接嵌入SQL语言;
- 5:严格区分数据库访问权限;
- 6:多层架构下的防治策略;
- 7:对于数据库敏感的、重要的数据,不要以明文显示,要进行加密;
- 8:对数据库查询中的出错信息进行屏蔽,尽量减少攻击者根据数据库的查询出错信息来猜测数据库特征的可能;
- 9:由于SQL注入有时伴随着猜测,因此,如果发现一个IP不断进行登录或者短时间内不断进行查询,可以自动拒绝他的登陆;也可以建立攻击者IP地址备案机制,对曾经的攻击者IP进行备案,发现此IP,直接拒绝;
- 10:可以使用专业的漏洞扫描工具来寻找可能被攻击的漏洞。
第十章 远程调用和组件安全
- 远程过程调用:允许程序调用驻留在其他机器上的过程。
- 远程过程调用安全问题:
- 1:攻击者可能会恶意地调用RPC服务器中的过程,或者输入一些恶意的数据导致服务器失效。
- 解决:
- 利用防火墙封堵端口。
- 临时禁用某些服务,如DCOM。
- 解决:
- 2:客户端和服务器之间传递的信息可能被窃听;攻击者可能会对传输中的数据进行篡改。
- 解决:采用数据加密和解密的方法来实现。
- 1:攻击者可能会恶意地调用RPC服务器中的过程,或者输入一些恶意的数据导致服务器失效。
第十一章 避免拒绝服务攻击
- 拒绝服务(DoS)攻击,是网络上常见的一类攻击的总称,其目的是使计算机或网络无法提供正常的服务。
- 网络带宽攻击::主要针对网络,恶意向网络发送极大的通信量,使得可用网络资源被消耗,而合法的用户连接反而无法通过;
- 连通性攻击:主要是针对网络上的计算机,向这些计算机发出大量的连接请求,消耗计算机可用的操作系统资源,导致计算机无法再处理合法用户的请求。
- 攻击方式:
- 消耗网络带宽:
- 使用真实的IP地址,对服务器发起大量的真实连接,抢占带宽,由于服务器的承载能力有限,就有可能造成合法用户无法连接,当然也有可能造成服务器的资源耗尽,系统崩溃。
- 还可以使用假的IP地址(IP地址欺骗),使得服务器端无法通过“黑名单”来拒绝一些恶意的IP地址。
- 消耗网络设备的CPU;
- 消耗网络设备的内存;
- 导致网络上设备系统崩溃;
- 对网络上服务器的攻击:
- 针对同一个服务器的某个端口(如HTTP所在的80端口),短时间内发送大量伪造的连接请求报文,造成服务器忙不过来,严重的时候资源耗尽、系统停止响应甚至崩溃。
- 消耗网络带宽:
- 从攻击原理分,拒绝服务攻击可分为两类:
- 基于漏洞的攻击,又称为逻辑攻击(Logic Attack)。
- 基于流量的攻击,又称为洪水攻击(Flooding
- DDoS攻击(分布式拒绝服务攻击):分布、协作、大规模的攻击方式,从多个攻击源攻击一个目标。
第十二章 数据的加密保护
对称加密算法
- 优势是计算量较小、加密速度较快、效率较高。
- 不足之处是,通信双方都使用同样的密钥,密钥在传送的过程中,可能被敌方获取,安全性得不到保证。
- 目前流行的算法:
- DES;
- 3DES;
- IDEA;
- AES。
非对称加密算法
- 公钥密码体制一般基于大整数分解、离散对数问题。
- 目前,在非对称密码体系中,使用得比较广泛的是非对称加密算法有:
- RSA;
- 美国国家标准局提出的DSA;
- ECC:椭圆曲线密码,密钥长度短、运算速度快、安全强度性高和密钥生成时间短。
- 非对称加密算法的保密性比较好,在通信的过程中,只存在公开密钥在网络上的传输,而公开密钥被敌方获取,也没有用;因此,基本不用担心密钥在网上被截获而引起的安全的问题。
- 但该加密体系中,加密和解密花费时间比较长、速度比较慢,一般情况下,它不适合于对大量数据的文件进行加密,而只适用于对少量数据进行加密。
单向加密
- 常用:MD5、SHA
- 消息验证码和MD5/SHA1算法不同的地方是:
- 在生成摘要时,发送者和接收者都拥有一个共同的密钥。这个密钥可以是通过对称密码体系生成的,事先被双方共有,在生成消息验证码时,还必须要有密钥的参与。
- 只有同样的密钥才能生成同样的消息验证码。
第十三章 数据的其他保护
- 数据加密的如下特点,可能会给数据保护带来副作用:
- 1:数据加密必须要将数据用加密算法进行处理,不管是对称密码体系还是非对称密码体系,算法复杂度都较高,如果数据量大,所花的时间较多,在有些需要迅速响应的实时系统中,不太适合。
- 2:除了单向加密方法之外,其它常见的加密算法都需要保存密钥,密钥的保存除了额外消耗空间之外,也增加了数据本身对外界的依赖性,如果密钥被破坏,数据将面临无法解密的可能。
- 内存数据保护两种方案:
- 避免将数据写入硬盘文件,尽量不使用虚拟内存;
- 从内存及时擦除数据
即便不高谈理想,也要心存信仰。