代码审计
代码审计常用漏洞总结
1.1 审计方法总结
主要代码审计方法是跟踪用户输入数据和敏感函数参数回溯:
跟踪用户的输入数据,判断数据进入的每一个代码逻辑是否有可利用的点,此处的代码逻辑
可以是一个函数,或者是条小小的条件判断语句。
敏感函数参数回溯,根据敏感函数,逆向追踪参数传递的过程。这个方法是最高效,最常用
的方法。大多数漏洞的产生是因为函数的使用不当导致的,只要找到这些函数,就能够快速
挖掘想要的漏洞。
以下是基于关键词审计技巧总结:
在搜索时要注意是否为整个单词,以及小写敏感这些设置
漏洞名称 |
关键词 |
|
|
密码硬编码、密码明文存储 |
password 、pass、jdbc |
|
|
XSS |
getParamter、<%=、param. |
|
|
SQL 注入 |
Select、Dao 、from 、delete 、update、insert |
|
|
任意文件下载 |
download 、fileName 、filePath、write、getFile、getWriter |
|
|
任意文件删除 |
Delete、deleteFile、fileName 、filePath |
|
|
文件上传 |
Upload、write、fileName 、filePath |
|
|
命令注入 |
getRuntime、exec、cmd、shell |
|
|
缓冲区溢出 |
strcpy,strcat,scanf,memcpy,memmove,memeccpy |
|
Getc(),fgetc(),getchar;read,printf |
|
|
XML 注入 |
DocumentBuilder、XMLStreamReader、SAXBuilder、SAXParser |
|
SAXReader 、XMLReader |
|
SAXSource 、TransformerFactory 、SAXTransformerFactory 、 |
|
SchemaFactory |
|
|
反序列化漏洞 |
ObjectInputStream.readObject |
|
、ObjectInputStream.readUnshared、XMLDecoder.readObject |
|
Yaml.load 、 XStream.fromXML 、 ObjectMapper.readValue 、 |
|
JSON.parseObject |
|
|
url 跳转 |
sendRedirect、setHeader、forward |
|
|
不安全组件暴露 |
activity 、 Broadcast Receiver 、 Content Provider 、 Service 、 |
|
inter-filter |
|
|
日志记录敏感信息 |
log log.info logger.info |
|
|
代码执行 |
eval、system、exec |
|
|
2.1 可基于关键词审计的漏洞
2.1.1 密码硬编码
审计方法
密码硬编码最容易找,直接用 Sublime Text 打开项目目录,然后按 Ctrl + Shift + F 进行全局
搜索 password 关键词:
2.1.2 反射型 XSS
审计方法:反射型 XSS 一般 fortify 一般都能扫描出来
如果是手工找,可全局搜索以下关键词
getParamter
<%=
param.
漏洞代码示例:
1. EL 表达式输出请求参数:
代码在 170 行和 305 行处获取请求参数中的 groupId 值,在未经检查参数合法性的情况
下输出在 JavaScript 代码中,存在反射型 XSS 漏洞。
2. 输出 getParamter 获取的参数
然后在 224 行打印到如下的 js 代码中:
2.1.3 存储型 XSS
审计方法:方法有主要有两种:
- 全局搜索数据库的插入语句(关键词:insert,save,update),然后找到该插入语句所属的方 法名如 (insertUser()) , 然后全局搜索该方法在哪里被调用, 一层层的跟踪。直到 getParamter()方法获取请求参数的地方停止,如果没有全局 XSS 过滤器,跟踪的整个流 程都没有对获取的参数过滤,则存在存储型 XSS。
- 从 getParamter 关键词开始 ,跟踪请求参数,直到插入数据库的语句,如果中间没有过 滤参数,则存在存储型 XSS。
代码中 45 行和 46 行获取 usertype 和 name 的值,然后在 56 行存进数据库由于没有过
滤传进来的参数,所以会在显示时出来触发 XSS
2.1.4SQL 注入
审计方法:
SQL 注入一般 fortify 一般都能扫描出来
手动找的话,一般直接搜索 select、update、delete、insert 关键词就会有收获
如果 sql 语句中有出现+ append、 $() # 等字眼,如果没有配置 SQL 过滤文件,则判断存
在 SQL 注入漏洞
当找到某个变量关键词有 SQL 注入漏洞时,还可以直接全局搜索那个关键词找出类似漏洞
的文件,上面中可以直接全局搜索 tableName 关键词:
要查找那个页面调用到含有漏洞的代码,就要跟踪方法的调用栈。以上面的注入点 tableName 为例:
双击打开该文件,然后查看该变量所在函数:
发现该函数对应的 URL 为/lookOverCubeFile ,对应的功能为查看模型任务生成的文件。
2.1.5 任意文件下载
审计方法:全局搜索以下关键词 fileName
filePath getFile getWriter
漏洞示例:
代码在 downloadFile()函数中获取请求参数中的 affixalName 的值,然后赋值给 FileName
变量,接着在 196 行处通过拼接字符串赋值给 downPath 变量,然后在 198 行处调用
download 函数并把 downPath 的值传进函数,download 函数的代码如下:
download 函数把 filePath 处的文件写到 http 响应中,在整个流程中并没有对文件名的合法
性进行检查,存在任意文件下载漏洞,如通过把 affixalName 的值设置
为../../../WEB-INF/web.xml 可以下载网站的 web.xml 文件。
2.1.6 任意文件删除
审计方法:任意文件删除漏洞搜索以下关键词可以找到: delete, deleteFile,fileName ,filePath
漏洞案例:
代码在 41 行获取 fileName 的值,在 44 行处调用 ds.deleteFile()函数删除文件,该函数的代
码如下:
在整个流程中并没有对文件名的合法性进行检查,存在任意文件删除漏洞,如通过把 fileName 的值设置为../WEB-INF/web.xml 可以删除网站的 web.xml 文件。
2.1.7 文件上传
审计方法:
文件上传可以搜索以下关键词:(需注意有没有配置文件上传白名单)
upload,write,fileName ,filePath
在查看时,主要判断是否有检查后缀名,同时要查看配置文件是否有设置白名单或者黑名单,
像下面这种是检查了的:
下面的这种没检查:
List<FileItem> fileItems = servletFileUpload.parseRequest(request); for (int i = 0; i < fileItems.size(); ++i) {
FileItem fi = (FileItem) fileItems.get(i); String strFileName = fi.getName();
if (strFileName != null && !"".endsWith(strFileName)) { String fileName = opId + "_" + getTimeSequence() + "."
+ getFileNameExtension(strFileName);
String diskFileName = path + fileName; File file = new File(diskFileName); if (file.exists()) {
file.delete();
}
fi.write(new File(diskFileName)); resultArrayNode.add(fileName);
......
private String getFileNameExtension(String fullFileName) { if (fullFileName == null) {
return null;
}
int pos = fullFileName.lastIndexOf(".");
if (pos != -1) {
return fullFileName.substring(pos + 1, fullFileName.length());
} else {
return null;
}
2.1.8 命令注入
审计方法:可以搜索以下关键词: getRuntime,exec,cmd,shell
在第 205 行中,通过拼接传过来的 ip 值来执行命令。如果 ip 值通过外部传入,则可以构造
以下的 ip 值来执行 net user 命令:
127.0.0.1&&net user
2.1.9 缓冲区溢出
审计方法:主要通过搜索关键词定位,再分析上下文
可搜索以下关键字:
strcpy,strcat,scanf,memcpy,memmove,memeccpy Getc(),fgetc(),getchar;read,printf
漏洞示例:
文件\kt\frame\public\tool\socket_repeater\mysocket.h 中第 177 行,这里的的参数
hostname 拷贝到 m_hostname,具体如下图所示:
继续看,可以看到大小为 255
如果传入的长度比 255 要大,就会造成缓冲区溢出。
2.1.10XML 注入
审计方法:
XML 解析一般在导入配置、数据传输接口等场景可能会用到,可通过搜索以下关键字定位:
DocumentBuilder、XMLStreamReader、SAXBuilder、SAXParser、SAXReader 、XMLReader、SAXSource 、TransformerFactory 、SAXTransformerFactory 、SchemaFactory
涉及到 XML 文件处理的场景可留意下 XML 解析器是否禁用外部实体,从而判断是否存在 XXE
漏洞示例:
在代码 6 行处、获取 DOM 解析器,解析 XML 文档的输入流,得到一个 Document
如果没有禁用 DTD 则存在 XXE 漏洞,以下代码为 XXE 防御代码
2.1.11 日志记录敏感信息
审计方法:
通过搜索关键词 log.info logger.info 来进行定位
在SFtpOperate.java文件中,代码134行处,直接将用户名密码记录在日志中
2.1.12URL 跳转
审计方法:通过搜索以下关键词定位:
sendRedirect、setHeader、forward
需注意有没有配置 url 跳转白名单
漏洞示例:
以下代码中 40 行处只判断 site 只是否为空,没有对 url 进行判断是否为本站 url,导致了 url
跳转漏洞
2.1.13 敏感信息泄露及错误处理
审计方法:查看配置文件是否配置统一错误页面,如果有则不存在此漏洞,如果没有再通过
搜索以下关键词搜索定位,
Getmessage、exception
漏洞代码示例:
在以下文件中代码 89 行处打印出程序发生异常时的具体信息
2.1.14 反序列化漏洞
审计方法:
Java 程序使用 ObjectInputStream 对象的 readObject 方法将反序列化数据转换为 java 对象。
但当输入的反序列化的数据可被用户控制,那么攻击者即可通过构造恶意输入,让反序列化
产生非预期的对象,在此过程中执行构造的任意代码。
反序列化操作一般在导入模版文件、网络通信、数据传输、日志格式化存储、对象数据落磁
盘或 DB 存储等业务场景,在代码审计时可重点关注一些反序列化操作函数并判断输入是否
可控,如下:
ObjectInputStream.readObject
ObjectInputStream.readUnshared
XMLDecoder.readObject
Yaml.load
XStream.fromXML
ObjectMapper.readValue
JSON.parseObject
漏洞示例:
以下代码中,程序读取输入流并将其反序列化为对象。此时可查看项目工程中是否引入可利
用的 commons-collections 3.1、commons-fileupload 1.3.1 等第三方库,即可构造特定反序列
化对象实现任意代码执行。
2.1.15 不安全组件暴露
审计方法:
通过查看配置文件 AndroidManifest.xml,查看<inter-filter>属性有没有配置 false
AndriodManifest.xml 文件中,代码 24 行处 activity 组件添加<intent-filter>属性,没有配置 false,
默认组件可被导出
3.1 其他漏洞审计方法
3.1.1CSRF
审计方法:通过查看配置文件有没有配置 csrf 全局过滤器,如果没有则重点看每个操作前有
没有添加 token 的防护机制
在 Smpkpiappealcontroller.java 中 200 处,直接用用 ids 控制删除操作,而没有添加防
csrf 的随机 token 验证检查,存在 csrf 漏洞。
Java/main/com/venustech/tsoc/cupid/smp/kpi/dao/smpkpideclardao.java 517 行,对传
入的 ids 进行删除操作。
3.1.2Struts2 远程代码执行漏洞
审计方法:查看 struts 插件的版本信息是否为漏洞版本
漏洞版本查询网址:https://www.exploit-db.com/
3.1.3 越权操作
审计方法:重点关注用户操作请求时查看是否有对当前登陆用户权限做校验从而确定是否存 在漏洞,有些厂商会使用一些主流的权限框架,例如 shiro ,spring security 等框架,那么需要 重点关注框架的配置文件以及实现方法
漏洞示例:
在以下文件中采用了 shiro 框架进行权限控制,在代码 58-72 行处为控制访问路径的权限设
置,51-55 行处为对 admin 路径下访问限制,只有 SysyUserFilter 设置了 isAccessAllowed
方法,其他过滤均没有
SysUserFilter 中 isAccessAllowed 具体实现方法如下,90-93 行处没有对是否为当前用户进
行判断,导致了越权
其他过滤文件均只设置了 onAccessDaniad()方法
如果没有使用框架的话,就要注意每个操作是否有权限
代码 7 行处获取 session 里的 username,只判断了 username 是不是为空,如果在截取
数据包的时候将 username 再重新赋一个值就有可能造成越权漏洞。
以这个年度服务费用编制功能为例,测试一下,代码如图所示:
3.1.4 会话超时设置
审计方法:
Javaweb 应用会话超时设置一般有俩种方法:
一是在配置文件 web.xml 设置
二是通过 java 代码设置
3.1.5 敏感数据弱加密
审计方法:
敏感数据弱加密主要看数据传输中的加密方法,一般写在工具类 util 中
以下文件中为 base64 编码方法