静态类的非静态变量生命周期
在过去的十年中,黑客的艺术和实践发生了重大变化。 从攻击的数量和复杂性到为成名或财富而进行黑客攻击的国际参与者的人数不断增长,黑客都是现代海盗,他们在互联网的公海寻求冒险。
但是,使这种趋势变得更加关键的是Internet能够实现的攻击面的大小。 我们生活在一个日益互联的世界中,物理或软件包安全性不再是黑客的障碍。 取而代之的是,网络协议,应用程序的知识以及不断增长的利用和实用程序列表构成了黑客的工具包。
如今,黑客攻击已成为大生意。 软件中以前未知的漏洞,称为零时差攻击 ,可以带来丰厚的利润。 例如,在地下市场卖零天可产生250,000美元的收益(对于Apple iOS漏洞利用,而随软件的普及程度或健壮性而降低)。
最底层的是新手黑客。 黑客不仅是学习艺术的人,而且是缺乏技能的人。 所谓的脚本小子能够使用黑客社区(除了白帽渗透测试人员)开发的行业工具,以破坏传统应用程序或具有已知漏洞的应用程序。 窃听信息,控制权,金钱或短暂成名的公司,政府,私人团体和个人处于最高端。 这些人的专业知识和支持使其不仅对我们已部署的应用程序,而且对整个行业(金融,能源,公用事业等)都最危险。
无论出于何种原因,结果都是我们每天编写的软件受到几乎恒定的围攻。 作为开发人员,我们的工作曾经是编写简单有效的软件。 今天,我们的软件不仅必须运行,而且必须在持续的威胁下可靠地运行。
尽管安全曾经是软件开发中的事后考虑,但现在必须在整个软件开发生命周期(SDLC)中予以考虑。 对于本文,我将生命周期分为三个单独的阶段:设计,开发和验证以及生产。 设计阶段是一个湿件过程,您可以在其中确定需求并制定架构和设计。 在开发和验证期间,您编写和测试系统。 最后,在生产中,您将部署和维护系统。
保护系统安全需要根据生命周期阶段的不同而采用不同的方法和工具(请参见图1)。 在设计阶段,您需要依靠良好,安全的设计流程和审查(以及某些规范方法,例如规范或建模语言)。 在开发和验证阶段,您拥有可以触摸和测试的代码,并且非常适合在执行时进行自动检查和检查。 在生产中,您可以检查正在执行的应用程序。 执行中的自动审查和检查应用程序都有特殊的名称-分别是静态分析和动态分析 。
静态分析提供了几种技术来分析未执行的源(或对象)代码。 在此类别中,提供了诸如Secure Programming Lint(Splint)和IBM®SecurityAppScan®Source之类的工具。 动态分析工具依靠可执行代码进行分析或提取信息的工具。 在动态类别中,有诸如Valgrind和IBM Security AppScan Standard and Enterprise之类的工具。
动态测试还有另一种形式,称为网络侦察 。 此子类别中的工具可帮助通过远程网络访问识别应用程序中的漏洞。
静态分析是对源代码(或编译后的目标代码)的检查。 静态分析工具使用多种方法(例如数据流分析)可以发现诸如内存泄漏,缓冲区溢出甚至并发问题之类的问题。 静态分析通过扫描一个或多个源文件并创建扫描源的表示形式进行分析来工作(参见图2)。
此类别中最有趣的开源工具之一是名为Splint的程序。 Lint是UNIX®实用程序,最早于1979年出现,可用于标记程序中可疑或不可移植的结构。 鉴于Lint的想法,鉴于此问题日益受到重视,因此Splint现在已将安全漏洞的重点作为重点。
清单1提供了一个Splint的简单示例。 如图所示,简单的(写得不好)函数应该获取PATH环境变量并将其写入传递的字符串参数中。 夹板发现了一些问题(为简洁起见,删除了一些修脚用品)。 特别是,不能保证传递的字符串不是NULL,并且传递的字符串中没有足够的空间来保存getenv
操作的内容。 两者都是有效的问题,第二个问题使程序对于缓冲区溢出攻击不安全。
$ cat getpath.c
void getPath( char *str )
{
strcpy(str, getenv("PATH"));
}
$ splint getpath.c -strict
Splint 3.1.2 --- 03 May 2009
getpath.c: (in function getPath)
getpath.c:3:3: Undocumented modification of *str possible from call to strcpy:
strcpy(str, getenv("PATH"))
An externally-visible object is modified by a function with no /*@modifies@*/
comment. The /*@modifies ... @*/ control comment can be used to give a
modifies list for an unspecified function. (Use -modnomods to inhibit warning)
getpath.c:3:15: Possibly null storage passed as non-null param:
strcpy (..., getenv("PATH"))
A possibly null pointer is passed as a parameter corresponding to a formal
parameter with no /*@null@*/ annotation. If NULL may be used for this
parameter, add a /*@null@*/ annotation to the function parameter declaration.
(Use -nullpass to inhibit warning) getpath.c:3:3: Possible out-of-bounds
store: strcpy(str, getenv("PATH"))
Unable to resolve constraint:
requires maxSet(str @ getpath.c:3:10) >= maxRead(getenv("PATH") @ getpath.c:3:15)
needed to satisfy precondition:
requires maxSet(str @ getpath.c:3:10) >= maxRead(getenv("PATH") @ getpath.c:3:15)
derived from strcpy precondition: requires
maxSet() >= maxRead()
A memory write may write to an address beyond the allocated buffer. (Use
-boundswrite to inhibit warning)
...
Finished checking --- 5 code warnings
$
您将在清单1中注意到的一件事是Splint建议使用“控件注释”。 这些注释可以应用于注释内部的源代码,这使开发人员可以进一步完善Splint的有关程序的信息,以进行更详细的分析。
Splint并不是唯一通过源扫描提供静态分析的实用程序。 尽管您可以使用Splint分析C
和C++
程序,但其他实用程序专注于其他语言和应用程序框架。 表1简要列出了其他静态分析工具及其目标语言或框架。
语言或框架 | 静态工具 |
---|---|
C 或C++ |
夹板,VisualCodeGrepper |
Java™技术 | FindBugs,LAPSE +,VisualCodeGrepper |
JavaScript | JSLint,JSHint |
Python | pylint,PyChecker |
PHP | 入侵防御系统 |
Ruby on Rails | 煞车人,codesake_dawn |
从专业的角度来看,还有商业化的IBM Security AppScan Source。 该产品为传统和移动应用程序提供了完整的产品组合解决方案,并为审计和合规性目的提供了对威胁的全面了解。 除了提供的技术洞察力之外,它还可以与动态测试聚合在一起,以混合的方式查看安全风险,并包括用于高级状态的各种仪表板。 安全性AppScan Source涵盖多种流行语言(例如C/C++
,PHP,SAP,Java和Microsoft®.NET)并与集成开发环境集成,是安全测试和风险管理的理想选择。
最后,探索安全保护时不要忘记编译器工具链。 大多数编译器都包含增强的错误检查功能,通常默认情况下将其禁用,但是一旦启用,它就可以帮助发现源代码中的重大问题。
动态分析是在运行时检查程序。 与静态分析一样,动态分析根据要提取的数据使用多种技术。 您可以使用动态分析来标识代码覆盖率(或给定应用程序中采用的路径)。 这很有用,因为未在应用程序中使用的路径可能未经测试并且包含错误或漏洞利用。 动态分析的工作方式是在构建时将自省代码集成到应用程序中(最常见的方法),或者提供一种平台仿真形式,以了解执行期间应用程序的内部行为(参见图3)。
动态分析的一个有趣示例是Valgrind工具。 Valgrind通过在应用程序和物理平台之间运行来获得自省功能。 应用程序可执行文件被转换为应用了工具的中间表示形式。 然后,使用即时(JIT)编译技术将此中间表示形式转换为物理机器代码,以提供可能的最佳性能。 Valgrind提供了几种工具来分析正在执行的程序。 这些工具可以检查未初始化的内存,动态内存的无效使用,动态内存的泄漏,堆分析,检测多线程代码中的竞争条件等。
让我们用Valgrind探索一个简单的例子。 此示例显示一个简单的错误程序,以查看Valgrind检测到什么以及如何报告错误。
清单2中显示了示例应用程序,构建和测试。请注意, badmem
函数中存在两个问题。 第一种是尝试超出缓冲区范围进行写操作,第二种是已分配但从未释放过的缓冲区。
// mem.c
#include
char* badmem( void )
{
char *ptr = malloc( 8 );
ptr[8] = 0;
return ptr;
}
void main( void )
{
char *result;
result = badmem();
return;
}
接下来,我为Valgrind准备程序,然后在Valgrind虚拟机(VM;请参见清单3)中执行它。 我在禁用优化( -O0
)和调试信息( -g
)的情况下构建了示例应用程序,以便可以在输出中接收符号(函数名,行号)。 构建后,我执行Valgrind,启用泄漏检查并指定我的测试应用程序。 请注意,在输出中Valgrind检测到我的越界写入,并且作为堆摘要的一部分,我可以看到从堆中分配了8个字节并且它们仍在使用中。
$ gcc -g -O0 mem.c -o mem
$
$ valgrind --leak-check=yes ./mem
==17340== Memcheck, a memory error detector
==17340== Copyright (C) 2002-2009, and GNU GPL'd, by Julian Seward et al.
==17340== Using Valgrind-3.6.0.SVN-Debian and LibVEX; rerun with -h for copyright info
==17340== Command: ./mem
==17340==
==17340== Invalid write of size 1
==17340== at 0x80483FF: badmem (mem.c:7)
==17340== by 0x8048414: main (mem.c:16)
==17340== Address 0x419b030 is 0 bytes after a block of size 8 alloc'd
==17340== at 0x4024F20: malloc (vg_replace_malloc.c:236)
==17340== by 0x80483F5: badmem (mem.c:5)
==17340== by 0x8048414: main (mem.c:16)
==17340==
==17340==
==17340== HEAP SUMMARY:
==17340== in use at exit: 8 bytes in 1 blocks
==17340== total heap usage: 1 allocs, 0 frees, 8 bytes allocated
==17340==
==17340== LEAK SUMMARY:
==17340== definitely lost: 0 bytes in 0 blocks
==17340== indirectly lost: 0 bytes in 0 blocks
==17340== possibly lost: 0 bytes in 0 blocks
==17340== still reachable: 8 bytes in 1 blocks
==17340== suppressed: 0 bytes in 0 blocks
==17340== Reachable blocks (those to which a pointer was found) are not shown.
==17340== To see them, rerun with: --leak-check=full --show-reachable=yes
==17340==
==17340== For counts of detected and suppressed errors, rerun with: -v
==17340== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 12 from 7)
$
对于较大的程序,您会注意到性能有所下降。 因为Valgrind是动态转换的(从二进制转换为中间表示,然后再转换为在基础体系结构上执行),所以确实会发生一些性能损失。
Valgrind是动态分析工具的一个示例(请参见表2)。 一个类似的名为DynamoRIO的工具支持运行时代码操纵以进行程序分析(启用性能分析,检测,优化和转换)。 此类的另一个示例是Pin,它允许JIT编译的操作模式和探测模式,以有限的功能集为代价使正在运行的程序的开销最小化。
在VM或仿真方法之外,还可以使用内省工具进行动态分析。 最常见的之一是GNU的gcov
和gprof
,它们使用编译时工具提供覆盖率分析和性能分析。 调试Malloc( dmalloc
)库提供了Malloc / free(及其变体)的直接替换,以实现对内存泄漏,越界写入和其他功能的运行时资源跟踪。
动态分析风格 | 工具类 |
---|---|
动态翻译/ VM | Valgrind,DynamoRIO,Pin |
编译时检测 | gcov , gprof , dmalloc |
最后,手动断言是一种可能无法充分利用的防止异常的功能。 尽管在生产代码中不是理想的方法,但是assert
函数(在检测到灾难性或不可恢复的问题时导致程序退出)对于在开发过程中识别错误很有用。 大多数语言都实现一种形式或断言,并且可以帮助查明可能成为下一个利用机会的问题。
探索的最后一类动态测试是漏洞扫描。 这种测试形式允许进行所谓的网络侦察 ,并且通常称为渗透测试 。 对于面向Internet的基于Web的应用程序,这种类型的分析对于确保鲁棒和安全的应用程序至关重要。 您可以在发布应用程序之前以及部署和运行应用程序时执行此测试。
漏洞扫描涉及一个旨在访问设备以寻找弱点的程序。 漏洞扫描程序的接触点是通过这些端口公开的设备,端口和协议。 图4提供了漏洞扫描程序的通用体系结构。
最受欢迎的端口扫描程序是一个称为Network Mapper ( nmap
)的程序。 nmap
实用程序非常广泛,包括一个脚本引擎,使您可以编写脚本以与目标进行交互(使用Lua脚本语言)。 清单4在一个简单的示例中演示了nmap
。 我首先对整个网络进行简单的端口扫描(使用-sP
或Ping Scan)。 这将生成目标列表及其名称和IP地址。 感兴趣的是HP打印机。 接下来,我将nmap
指向打印机并请求进行端口扫描(并假定主机使用-PN
)。 这为我提供了端口列表,通过这些端口,我可以访问设备以尝试控制设备。 然后,我进一步深入研究,以了解使用Telnet检索更多信息(打印机名称,序列号,专用集成电路[ASIC]的ID等)在HTTP端口(80)后面的含义。 下一步是搜索HP打印机这些端口的可用漏洞,并应用metasploit等漏洞利用框架以利用它们。
$ sudo nmap -sP 192.168.1.*
Starting Nmap 5.00 ( http://nmap.org ) at 2013-07-29 11:26 MDT
Host Frylock (192.168.1.1) is up (0.0018s latency).
...
Host mtjs-iPhone.hsd1.**********.net (192.168.1.100) is up (0.0011s latency).
Host 192.168.1.101 is up (0.0011s latency).
Host Megans-iMac.hsd1.**********.net (192.168.1.108) is up (0.0027s latency).
Host marcs-iPod.hsd1.**********.net (192.168.1.123) is up (0.00030s latency).
Host HPA20BE7.hsd1.**********.net (192.168.1.125) is up (0.00035s latency).
...
$ sudo nmap -PN 192.168.1.125
Starting Nmap 5.00 ( http://nmap.org ) at 2013-07-29 11:31 MDT
Interesting ports on HPA20BE7.hsd1.**********.net (192.168.1.125):
Not shown: 987 filtered ports
PORT STATE SERVICE
80/tcp open http
139/tcp open netbios-ssn
443/tcp open https
445/tcp open microsoft-ds
515/tcp open printer
631/tcp open ipp
7435/tcp open unknown
8080/tcp open http-proxy
9100/tcp open jetdirect
9101/tcp open jetdirect
9110/tcp open unknown
9111/tcp open DragonIDSConsole
9220/tcp open unknown
Nmap done: 1 IP address (1 host up) scanned in 89.84 seconds
$
$ telnet 192.168.1.125 80
Trying 192.168.1.125...
Connected to 192.168.1.125.
Escape character is '^]'.
HEAD / HTTP/1.1
HTTP/1.1 200 OK
Server: HP HTTP Server; HP Officejet Pro 8600 - CM749A; Serial Number: CN3CMCZGG505KC;
Coulomb_base_pp Built:Fri May 31, 2013 08:21:06PM {CLV1CM1342CR, ASIC id 0x00320104}
Last-Modified: Fri, 31 May 2013 20:21:06 GMT
...
Content-Type: text/html; charset=UTF-8
Content-Encoding: gzip
Content-Length: 700
Connection closed by foreign host.
$
该演示的重点是,在构建网络或面向Internet的设备时,您必须对暴露的内容保持勤奋。 每个打开的端口都是潜在的漏洞,端口(以及通过这些端口公开的信息)越少,设备的安全性就越高。
漏洞测试类别中存在许多工具,其中一些与端口和网络扫描有关,其他用于目标漏洞扫描器,还有其他用于模糊和低级分析的工具。 您将在表3中找到这些工具的列表。在此表中,端口扫描程序会枚举网络或主机上的可用端口,并实施某种形式的应用程序指纹识别以找出其中的内容(例如主机的操作系统或端口后面的应用程序)。 漏洞扫描程序提供了一个框架,可以在每个操作系统,应用程序和版本的基础上使用已知漏洞利用的目录来利用这些端口。 现在,根据应用程序对漏洞扫描程序进行了细分(一个示例是安全扫描程序的数据库类)。 Web扫描程序类似于漏洞扫描程序,但仅专注于Web系统。 模糊测试工具提供了一种生成随机(无效或意外)输入到应用程序以测试其错误检查范围的方法。 最后,低级网络工具(例如Wireshark)提供了检查协议流量详细信息的方法。
网络侦察风格 | 工具类 |
---|---|
端口扫描器 | nmap , scanrand |
漏洞扫描器 | Metasploit,OpenVAS |
网络扫描仪 | Nikto,SQLMap |
模糊测试工具 | w3af,Ski鱼,Wfuzz |
低级网络工具 | tcpdump ,Wireshark |
从专业的角度来看,还有安全性AppScan Standard。 该产品提供了自动扫描范围广泛的应用程序安全漏洞的优先级结果。 除了涵盖每个Open Web Application Security Project的前10个漏洞之外,AppScan Standard还会自动更新规则以使最新威胁保持最新状态。
这篇简短的文章涵盖了很多基础,探讨了静态和动态测试以及漏洞扫描方法和工具。 那么问题来了,哪个是您开发的正确选择? 每种形式都应在开发生命周期,设计和开发,测试以及生产中应用某种形式。 无论您选择开源产品的集合还是IBM的AppScan产品组合之类的集成产品系列,选择实际上都是在交付可靠的产品和下一次公开的,备受关注的安全性失败之间进行选择。
翻译自: https://www.ibm.com/developerworks/security/library/se-static/index.html
静态类的非静态变量生命周期