代码审计For小白

前言:对于没从事过开发的人来说,代码审计是有不小的挑战的,要快速上手,就需要一些小技巧了。详情请看“审计关键”。

Java常见漏洞Top10:
日志伪造Log Forging:将未经验证的用户输入写入日志文件可致使攻击者伪造日志条目或将恶意信息内容注入日志。
示例代码:

  1. public void risk(HttpServletRequest request, HttpServletResponse response) {
  2.  	String val = request.getParameter(""val"");;
    
  3.  	try {
    
  4.  		int value = Integer.parseInt(val);
    
  5.  	}
    
  6.  	catch (NumberFormatException nfe) {
    
  7.  		log.info(""Failed to parse val = "" + val);
    
  8.  	}
    
  9.  }
    

修复代码:

  1. public void risk(HttpServletRequest request, HttpServletResponse response) {
  2.  	String val = request.getParameter(""val"");;
    
  3.  	try {
    
  4.  		int value = Integer.parseInt(val);
    
  5.  	}
    
  6.  	catch (NumberFormatException nfe) {
    
  7.  		val = val.replace("\r", "");
    
  8.  		val = val.replace("\n", "");
    
  9.  		log.info(""Failed to parse val = "" + val);
    
  10. 	}
    
  11. }
    

审计关键:看代码中是否有像7、8行这样的过滤掉\r\n这两个换行符。

资源未释放:数据流Unreleased Resource: Streams:此类漏洞导致程序可能无法成功释放某一项系统资源。
示例代码:

  1. private void processFile(String fName) throws FileNotFoundException, IOException {
  2. FileInputStream fis = new FileInputStream(fName);
  3. int sz;
  4. byte[] byteArray = new byte[BLOCK_SIZE];
  5. while ((sz = fis.read(byteArray)) != -1) {
  6.  processBytes(byteArray, sz);
    
  7. }
  8. }
    修复代码:
    public void processFile(String fName) throws FileNotFoundException, IOException {
    FileInputStream fis;
    try {
    fis = new FileInputStream(fName);
    int sz;
    byte[] byteArray = new byte[BLOCK_SIZE];
    while ((sz = fis.read(byteArray)) != -1) {
    processBytes(byteArray, sz);
    }
    }
    finally {
    if (fis != null) {
    safeClose(fis);
    }
    }
    }
    审计关键:看代码中是否对输入流判断非null值再进行数据流关闭。(假如是Java8.0版本语言开发,则可以直接对数据进行关闭)

跨站脚本:反射型Cross-Site Scripting: Reflected:向一个 Web 浏览器发送未经验证的数据会导致该浏览器执行恶意代码。
示例代码:
以下 JSP 代码片段可在数据库中查询具有给定 ID 的雇员,并输出相应雇员姓名。
public void risk(HttpServletRequest request,
HttpServletResponse response ,org.apache.log4j.Logger logger) {
String text = request.getParameter(“text”);
try {
response.getWriter().print(text);
} catch (IOException e) {
logger.warn(“Exception”, e);
}
}
修复代码:使用struts自带的跨站修复函数方式
public void fix(HttpServletRequest request,
HttpServletResponse response ,org.apache.log4j.Logger logger) {
String text = request.getParameter(“text”);
try {
String filtedText = org.apache.struts.util.ResponseUtils.filter(text);
response.getWriter().print(filtedText);
} catch (IOException e) {
logger.warn(“Exception”, e);
}
}
审计关键:看代码中是否对前端输入的数据进行特殊符号的转义过滤。

密码管理:密码在配置文件中Password Management: Password in Configuration File:在配置文件中存储明文密码,可能会危及系统安全。
示例代码:
<bean id=”dataSource” class=”org.apache.commons.dbcp.BasicDataSource”
destroy-method=”close”
p:driverClassName=”oracle.jdbc.driver.OracleDriver”
p:url=”jdbc:oracle:thin:@127.0.0.1:1523:orcl”
p:username=”czw”
p:password=”czw”

修复代码:
对于Spring框架项目中,有专门加密配置文件密码的方法如下:
1、将配置文件抽取到property中来:



2、扩展PropertyPlaceholderConfigurer父类PropertyResourceConfigurer的解密方法convertProperty:
import org.springframework.beans.factory.config.PropertyPlaceholderConfigurer;
public class ConvertPwdPropertyConfigurer extends PropertyPlaceholderConfigurer{
@Override
protected String convertProperty(String propertyName, String propertyValue) {
System.out.println("=================="+propertyName+":"+propertyValue);
if(“userName”.equals(propertyName)){
return “czw”;
}
if(“password”.equals(propertyName)){
return “czw”;
}
return propertyValue;
}
}
3、然后将上面完成的类替换配置文件中的PropertyPlaceholderConfigurer:

审计关键:查看程序代码中是否存在敏感信息,安全开发规范标准中明确规定敏感信息应 加密&保存 于配置文件中。

sql注入SQL Injection:通过不可信来源的输入构建动态 SQL 指令,攻击者就能够修改指令的含义或者执行任意 SQL 命令。
示例代码:
public void risk(HttpServletRequest request, Connection c, org.apache.log4j.Logger logger) {
String text = request.getParameter(“text”);
String sql = “select * from tableName where columnName = '” + text
+ “’”;
try {
Statement s = c.createStatement();
s.executeQuery(sql);
} catch (SQLException e) {
logger.warn(“Exception”, e);
}
}
修复代码:
public void fix(HttpServletRequest request, Connection c, org.apache.log4j.Logger logger) {
String text = request.getParameter(“text”);
String sql = “select * from tableName where columnName = ?”;
try {
PreparedStatement s = c.prepareStatement(sql);
s.setString(1, text);
s.executeQuery();
} catch (SQLException e) {
logger.warn(“Exception”, e);
}
}
审计关键:查看代码中是否有使用PreparedStatement参数化查询。

动态代码评估:代码注入Dynamic Code Evaluation: Code Injection:在运行时中解析用户控制的指令,会让攻击者有机会执行恶意代码。
示例代码:

修复代码:
使用正则表达式对传入的代码参数进行约束,限制外界传入 eval 的参数中只包含字母和数字。

审计关键:查看代码中是否有对传入参数进行过滤。

可移植性缺陷:文件分隔符Portability Flaw: File Separator:使用硬编码文件分隔符会导致可移植性问题。
示例代码:
以下代码使用硬编码文件分隔符来打开文件:

File file = new File(directoryName + “\” + fileName);

修复代码:
使用独立于平台的 API 来指定文件分隔符:


File file = new File(directoryName + File.separator + fileName);

审计关键:查看代码中是否调用了File.separator来代替分隔符“\”,“/”。
Open重定向Open Redirect:如果允许未验证的输入控制重定向机制所使用的 URL,可能会有利于攻击者发动钓鱼攻击。
示例代码:
<%

String strDest = request.getParameter(“dest”);
pageContext.forward(strDest);

%>
修复代码:
<%

try {
int strDest = Integer.parseInt(request.getParameter(“dest”));
if((strDest >= 0) && (strDest <= strURLArray.length -1 )){
strFinalURL = strURLArray[strDest];
pageContext.forward(strFinalURL);
}
}
catch (NumberFormatException nfe) {

}
%>
审计关键:查看代码中是否有使用创建编号的方法指定并校验重定向的目标URL。

弱加密Weak Encryption:识别调用会使用无法保证敏感数据的保密性的弱加密算法。
审计关键:加密算法不应为MD5或者DES或者3DES,至少应该是AES。

弱加密:RSA不恰当填充Weak Encryption: Inadequate RSA Padding:公钥 RSA 加密在不使用 QAEP 填充模式下执行,因此加密机制比较脆弱。
示例代码:
public Cipher getRSACipher() {
Cipher rsa = null;
try {
rsa = javax.crypto.Cipher.getInstance(“RSA/NONE/NoPadding”);
}
catch (java.security.NoSuchAlgorithmException e) {
log(“this should never happen”, e);
}
catch (javax.crypto.NoSuchPaddingException e) {
log(“this should never happen”, e);
}
return rsa;
}
修复代码:
public Cipher getRSACipher() {
Cipher rsa = null;
try {
rsa = javax.crypto.Cipher.getInstance(“RSA/CBC/OAEPWithMD5AndMGF1Padding”);
}
catch (java.security.NoSuchAlgorithmException e) {
log(“this should never happen”, e);
}
catch (javax.crypto.NoSuchPaddingException e) {
log(“this should never happen”, e);
}
return rsa;
}
审计关键:加密算法后面的填充方式不应为空或者是ECB,至少应CBC。

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值