CH19 查找源代码中的漏洞

一、代码审查方法
(1)从进入点开始追踪用户向应用程序提交的数据,审查负责处理这些数据的代码;
(2)在代码中搜索表示存在常见漏洞的签名,并审查这些签名,确定某个漏洞是否确实存在;
(3)对内在危险的代码进行逐行审查,理解应用程序的逻辑,并确定其中存在的所有问题
(4)应用程序可能扩展了类库与接口,在进行审查之前应了解这些定制的范围 并相应调整审查方法

需要进行仔细审查的组件包括:关键安全机制(验证、会话管理、访问控制、输入确认)、外部组件接口以及任何使用本地代码的情况 。

二、常见漏洞签名
(1)XSS
String link = “<a href=” + HttpUtility.UrlDecode(Request.QueryString

[“refURL”]) + “&SiteID=” + SiteId + “&Path=” + HttpUtility.UrlEncode

(Request.QueryString[“Path”]) + “</a>”;

objCell.InnerHtml = link;
(2)SQL注入
直接使用用户输入 
StringBuilder SqlQuery = newStringBuilder(“SELECT name, accno FROM

TblCustomers WHERE “ + SqlWhere);

if(Request.QueryString[“CID”] != null &&

Request.QueryString[“PageId”] == “2”)

{

SqlQuery.Append(“ AND CustomerID = “);
}
...
在代码中搜索关键字:
“SELECT

“INSERT

“DELETE

“ AND

“ OR

“ WHERE

“ ORDER BY

(3)路径遍历
通过在代码中搜索任何与文件名有关的查询字符串参数(如AttachName等)以及在相关语言中搜寻所有文件API并检查提交它们的参数,就可以迅速确定相关的功能。
public byte[] GetAttachment(HttpRequest Request)

{

FileStream fsAttachment = new FileStream(SpreadsheetPath +

HttpUtility.UrlDecode(Request.QueryString[“AttachName”]),

FileMode.Open, FileAccess.Read, FileShare.Read);

byte[] bAttachment = new byte[fsAttachment.Length];

fsAttachment.Read(FileContent, 0,

Convert.ToInt32(fsAttachment.Length,

CultureInfo.CurrentCulture));

fsAttachment.Close();

(4)任意重定向 
private void handleCancel()

{

httpResponse.Redirect(HttpUtility.UrlDecode(Request.QueryString[

“refURL”]) + “&SiteCode=” +

Request.QueryString[“SiteCode”].ToString() +

“&UserId=” + Request.QueryString[“UserId”].ToString());

}

JS:
url = document.URL;

index = url.indexOf(‘?redir=’);

target = unescape(url.substring(index + 7, url.length));

target = unescape(target);

if ((index = target.indexOf(‘//’)) > 0) {

target = target.substring (index + 2, target.length);

index = target.indexOf(‘/’);

target = target.substring(index, target.length);

}

target = unescape(target);

document.location = target;

(5)OS命令注入
void send_mail(const char *message, const char *addr)

{

char sendMailCmd[4096];

snprintf(sendMailCmd, 4096, “echo ‘%s’ | sendmail %s”, message, addr);

system(sendMailCmd);

return;

}

(6)后门密码
private UserProfile validateUser(String username, String password)

{

UserProfile up = getUserProfile(username);

if (checkCredentials(up, password) ||

“oculiomnium”.equals(password))

return up;

return null;

}

(7)本地代码漏洞
a. 缓冲区溢出 
BOOL CALLBACK CFiles::EnumNameProc(LPTSTR pszName)

{

char strFileName[MAX_PATH];

strcpy(strFileName, pszName);

...

}

b. 整数漏洞
有符号的整数与无符号的整数进行比较,就会有问题
BOOL CALLBACK CFiles::EnumNameProc(LPTSTR pszName, int len)

{

char strFileName[MAX_PATH];

if (len < sizeof(strFileName))

strcpy(strFileName, pszName);

...

}

c. 格式化字符串漏洞
通过检查printf与FormatMessage系列函数的用法,如果发现格式化字符串参数并未硬编码,而是由用户控制,就可以确定这类漏洞。
(8)源代码注释
关键词:bug、 problem、 bad、 hope、 todo、 fix、 overflow、 crash、 inject、 xss、 trust

三、JAVA平台 
(1)确定用户提交的数据
JAVA应用程序通过javax.servlet.http.HttpServletRequest接口获取用户提交的输入,该接口对javax.servlet.servletRequest接口进行了扩展。API如下:

(2)会话交互
javax.servlet.http.HttpSession接口保存和检索当前会话中的信息,每会话存储是字符串名称与对象值之间的一个映射。

(3)潜在危险的API
1、文件访问
    主要的类为有:
    java.io.File
    java.io.FileInputStream
    java.io.FileOutputStream
    java.io.FileReader
    java.io.FileWriter
2、数据库访问
    java.sql.Connection.createStatement
    java.sql.Statement.execute
    java.sql.Statement.executeQuery
以下API更可靠,允许应用程序创建一个预先编译的SQL语句,并以可靠且类型安全的方式指定它的参数占位符的值:
java.sql.Connection.prepareStatement
java.sql.PreparedStatement.setString
java.sql.PreparedStatement.setInt
java.sql.PreparedStatement.setBoolean
java.sql.PreparedStatement.setObject
java.sql.PreparedStatement.execute
java.sql.PreparedStatement.executeQuery

3、动态代码执行
4、OS命令执行
    java.lang.runtime.Runtime.getRuntime
    java.lang.runtime.Runtime.exec

    攻击成功:
    String userinput = “calc”;
    Runtime.getRuntime.exec(userinput);
    攻击失败:
    String userinput = “| calc”;
    Runtime.getRuntime.exec(“notepad “ + userinput);    【notepad后有空格】
    攻击成功 :
    String userinput = “\\..\\system32\\calc”;
    Runtime.getRuntime().exec(“notepad” + userinput);  【notepad后无空格】

5、URL重定向
    javax.servlet.http.HttpServletResponse.sendRedirect
    javax.servlet.http.HttpServletResponse.setStatus
    javax.servlet.http.HttpServletResponse.addHeader

6、套接字
    java.net.Socket

(4)配置Java环境
web.xml是配置文件。主要配置项有:
login-config:配置认证细节,两类验证分别是基于表单的(页面由form-login-page元素指定)与在auth-method元素中指定的Basic-Auth或Client-Cert,如果使用基于表单的认证,指定的表单必须有j_security_check动作,须提交j_username与j_password参数。
security-constraint:如果定义了login-config,就可以使用security-constraint元素限定资源。这个元素可用于定义受保护的资源,可以使用url-pattern元素定义资源集。如:<url-pattern>/admin/*</url-pattern>,分别在role-name与principal-name元素中定义的角色与主要用户可以访问的资源
session-config:会话超时时间 (分钟)
error-page:error-code与exception-type分别处理HTTP错误代码与Java异常
init-param:配置初始化参数,listings应设置为false; debug应设置为0

除web.xml文件外,可能还包含次要配置文件weblogic.xml文件等,都应检查

四、ASP.NET
(1)确定用户提交的数据
ASP.NET通过System.Web.HttpRequest类获取用户提交的输入。

(2)会话交互
使用session属性 保存和检索当前会话中的信息。
Session["MyName"] = txtMyName.Text;
lblWelcome.Text = "Welcome "+Session["MyName"];
用户个性化配置中,数据以下列方式保存和检索:
Profile.MyName =  txtMyName.Text; 
lblWelcome.Text = "Welcome "+Profile.MyName;
System.Web.SessionStage.HttpSessionState 类也用于保存和检索会话中的信息。

(3)潜在危险的API
1、 文件访问
System.IO.File类

下面的类常用于读取与写入文件内容:
System.IO.FileStream
System.IO.StreamReader
System.IO.StreamWriter
以下两个直接拼接用户输入 的操作都会造成路径遍历漏洞。
string userinput = "..\\boot.ini";
FileStream fs = File.Open("C:\\temp\\" + userinput,FileMode.OpenOrCreate);

string userinput = “..\\foo.txt”;
FileStream fs = new FileStream(“F:\\tmp\\” + userinput,FileMode.OpenOrCreate);

2、数据库访问
System.Data.SqlClient.SqlCommand
System.Data.SqlClient.SqlDataAdapter
System.Data.Oledb.OleDbCommand
System.Data.Odbc.OdbcCommand
System.Data.SqlServerCe.SqlCeCommand
通过它们的Parameters属性支持预处理语句,允许应用程序创建一个包含参数占位符的SQL语句,并以可靠且类型安全的方式设定这些占位符的值。

3、动态代码执行
Eval函数接受一个包含VBScript表达式的字符串自变量。
Execute和ExecuteGlobal接受一个包含ASP代码的字符串。

4、OS命令执行
System.Diagnostics.Start.Process
System.Diagnostics.Start.ProcessStartInfo

5、URL重定向
System.Web.HttpResponse.Redirect
System.Web.HttpResponse.Status
System.Web.HttpResponse.StatusCode
System.Web.HttpResponse.AddHeader
System.Web.HttpResponse.AppendHeader
Server.Transfer

6、套接字
System.Net.Sockets.Socket

(4)配置 ASP.NET环境
we.config XML文件包含ASP.NET环境的配置设置。

反常情况:
a. $GLOBALS是一个包含在脚本全局范围内定义的所有变量的引用的数组。使用它可以根据名称访问其他变量
b. 如果配置 指令 register_globals被激活,PHP会为所有请求参数(即$_REQUEST数组中的全部数据)建立全局变量。这表示,应用程序可通过与相关参数相同的名称引用一个变量,从而访问用户输入。
c. PHP还在$_SERVER数组中增加了一个数据,用于处理在请求中收到的任何定制HTTP消息 头。如提交消息头Foo: Bar,则生成:$_SERVER['HTTP_FOO'] = "Bar"
d. 名称包含下标的输入参数被自动转换为数组。如:https://xxx/xxx.php?query[a]=foo&query[b]=bar,将使$_GET['query'] 变量的值转换成一个包含两个成员 的数组 。

(2)会话交互
PHP使用$_SESSION数组保存和检索用户会话中的信息。如:
$_SESSION[‘MyName’] = $_GET[‘username’]; // store user’s name
echo “Welcome “ . $_SESSION[‘MyName’]; // retrieve user’s name
$HTTP_SESSION_VARS数组的用法与上面的数组相同。如果register_globals被激活,那么全局变量将通过以下方式保存在当前会话中:
$MyName = $_GET[‘username’];
session_register(“MyName”);

PS: register_globals 在PHP 6已经删除。

(3)潜在危险的API
1、文件访问
fopen、readfile、 file、 fpassthru、 gzopen、gzfile、gzpassthru、 readgzfile、 copy、rename、rmdir、mkdir、unlink、file_get_contents、file_put_contents、parse_ini_file
下面的函数可用于包含并执行一个指定的PHP脚本:
include、include_once、require、require_once、virtual
远程文件检索协议 :


PHP 5.2以后引入了一个新选项allow_url_include,这个默认的配置 防止前面提到的方法在调用 文件包含函数时用于指定一个远程文件。

2、数据库访问
mysql_query、mssql_query、pg_query
下面的函数用于创建预处理语句,允许应用程序建立一个包含参数占位符的SQL查询,并以可靠而且类型安全的方式设定这些占位符的值:
mysqli->prepare、stmt->prepare、stmt->bind_param、stmt->execute、odbc_prepare

3、动态代码执行
eval、call_user_func、call_user_func_array、call_user_method、call_user_method_array、create_function
分号可以连接几个语句。
搜索与替代正则表达式的preg_replace函数,如果以/e选项调用,可用于运行一段特殊的PHP代码。
PHP可以通过一个包含函数名称的变量动态调用该函数,下面的代码将调用在查询字符串func参数中指定的函数:<?php $var=$_GET[‘func’]; $var();?> 用户可以通过修改func参数的值,使应用程序调用任意一个没有参数的函数,如phpinfo.

4、OS命令执行
exec、passthru、popen、proc_open、shell_exec、system、反单引号 (`)
| 可以连接命令

5、URL重定向
http_redirect、header、HttpMessage::setResponseCode、HttpMessage::setHeaders
一般用http_redirect,但是header也可以,如header("Location:/target.php");

6、套接字
socket_create、socket_connect、socket_write、socket_send、socket_recv、fsockopen、 pfsockopen
fsockopen与 pfsockopen 可用于打开连接指定主机与端口的套接字,并返回一个可用在fwrite和fgets等标准文件函数中的文件指针。

7、配置 PHP环境(php.ini)
(1)使用全局变量注册
如果register_globals被激活,PHP会为所有请求参数建立全局变量,如果PHP不要求变量在使用前被初始化,就会导致安全漏洞 。
PS: register_globals 在PHP 6已经删除。
(2)安全模式
safe_mode被激活后,PHP会对一些危险函数做限制:
a. shell_exec被禁用
b. mail函数的additional_parameters参数被禁用
c. exec函数仅能执行safe_mode_exec_dir指定目标下的可执行程序,命令字符串中的元字符被自动转义
PS: 安全模式在PHP 6已经删除。
(3)magic quotes
虽然激活magic_quotes_gpc指令会将请求中包含的任何单引号、双引号、反斜线和空字符都会有生个反斜线自动 转义,但是由于其局限性与不规则性,建议禁用该 选项。
PS: 在PHP 6已经删除。
(4)其他选项:

六、Perl
CGI.pm 是最常用于创建Web应用程序的Perl模块
(1)确定用户提交的数据

(2)会话交互
Perl模块CGISession.pm对模块CGI.pm进行扩展,为会话追踪与数据存储提供支持:
$q->session_data(“MyName”=>param(“username”)); // store user’s name
print “Welcome “ . $q->session_data(“MyName”); // retrieve user’s name

(3)潜在危险的API
1、文件访问
open与sysopen
如果文件名参数的开头或结尾为管道符(|),就可以执行任意命令。
2、数据库访问
selectall_arrayref函数 用于向数据库发送一个查询,并以一系列数组的形式检索查询结果。
do 函数 用于执行一个查询,并返回受影响的行的数量。
prepare与execute用于创建预处理语句,同样的会添加占位符,以防止SQL注入。
3、动态代码执行
eval,分号分隔符连接语句
4、OS命令执行
system、exec、qx、反单引号(`)
5、URL   重定向
redirect函数
6、套接字
socket与connect
7、配置Perl环境
污染模式(taint mode):#!/usr/bin/perl -T
当以taint 模式运行时,解释器会追踪该程序以外提交的每一个输入,并把它当做被污染的输入处理。如果另一个变量根据一个受污染的数据分配它的值,那么Perl也认为它受到污染。
这个模式旨在防止许多类型的漏洞,但只有当开发者使用适当的正则表达式从被污染的输入中提取“清洁“的数据时它才会有效。

七、JavaScript
重点审查以下API:

八、数据库代码组件
1、SQL注入
不同的数据库平台使用不同的方法动态执行包含SQL语句的字符串:
 MS-SQL — EXEC
 Oracle — EXECUTE IMMEDIATE
Sybase — EXEC
DB2 — EXEC SQL
在Oracle中,存储过程默认在定义者权限而非调用者权限下运行,因此,如果应用程序使用一个低权限帐户访问数据库,并且使用DBA建立存储过程,攻击者就可以利用某个过程中存在的SQL注入漏洞提升自己的权限,并执行任意数据库查询。
2、调用危险函数
a. Powerful default stored procedures in MS-SQL and Sybase that allow execution of commands, registry access, and so on
b. Functions that provide access to the file system
c. User-defi ned functions that link to libraries outside the database
d. Functions that result in network access, such as through OpenRowSet in MS-SQL or a database link in Oracle

九、代码浏览工具
Source Insight

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,937评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,503评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,712评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,668评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,677评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,601评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,975评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,637评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,881评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,621评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,710评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,387评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,971评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,947评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,189评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,805评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,449评论 2 342

推荐阅读更多精彩内容

  • 一、SSRF简介 SSRF(Server-Side Request Forgery),服务器端请求伪造,利用漏洞伪...
    知了堂_IT阅读 671评论 0 0
  • 作者:lanz 博客链接:http://netsecurity.51cto.com/art/201303/3862...
    Fa1se003阅读 502评论 1 3
  • [SQL注入攻击] SQL注入攻击是黑客对数据库进行攻击的常用手段之一。随着B/S模式应用开发的发展,使用这种模式...
    James黄杰阅读 2,635评论 0 30
  • 表情是什么,我认为表情就是表现出来的情绪。表情可以传达很多信息。高兴了当然就笑了,难过就哭了。两者是相互影响密不可...
    Persistenc_6aea阅读 124,027评论 2 7
  • 16宿命:用概率思维提高你的胜算 以前的我是风险厌恶者,不喜欢去冒险,但是人生放弃了冒险,也就放弃了无数的可能。 ...
    yichen大刀阅读 6,030评论 0 4