【web漏洞百例】1.日志伪造、堆检查

一、日志伪造(Log Forging)
描述:

将未经验证的用户输入写入日志文件可致使攻击者伪造日志条目或将恶意信息内容注入日志。

举例:
在以下情况或发生“日志伪造”的漏洞:
1.数据从一个不可信的数据源进入应用程序
2.数据写入到应用程序或系统日志文件中

为了便于以后的审阅、统计数据或调试,应用程序通常使用日志文件来存储事务的历史记录。根据
应用程序自身的特性,审阅日志文件可在必要时手动执行,也可以自动执行,即利用工具自动挑选
日志中的重要事件或带有某种倾向性的信息。

如果攻击者可以向随后会被逐字纪录到日志文件的应用程序提供数据,则可能会妨碍或误导日志文件
的解读。最理想的情况是,攻击者可能通过破坏文件格式或注入意外的字符,从而使文件无法使用。
更阴险的攻击可能会导致日志文件中的统计信息发生偏差。通过伪造或者其它方式,受到破坏的日志

文件可用于掩护攻击者的跟踪轨迹,甚至还可以牵连第三方来执行恶意行为。最糟糕的情况是,攻击者

可能向日志文件注入代码和其它命令,利用日志处理使用程序中的漏洞。


例1:下列Web应用程序代码会尝试从一个请求对象中读取整数值。如果数值未被解析为整数,输入就会被记录到日志中,附带一条提示相关情况的错误信息。
...
String val=request.getParameter("val");
try{
   int value=Integer.parseInt(val);
}catch(NumberFormatException nfe){
   log.info("Filed to parse val="+val);
}
...

如果用户为"val"提交字符串"twenty-one"(数字21的英文),则日志会记录以下条目:
INFO:Failed to parse val=twenty-one

然而,如果攻击者提交字符串“twenty-one%0a%0aINFO:+User+logged+out%3dbadguy”,则日志中
就会记录以下条目:
INFO:Failed to parse val=twenty-one
INFO:User logged out=badguy

显然,攻击者可以使用同样的机制插入任意日志条目。


解决方案:
使用间接方法防止日志伪造攻击:创建一组与不同事件一一对应的合法日志条目,这些条目
必须记录在日志中,并且仅记录该组条目。要捕获动态内容(如用户注销系统),请务必使用由
服务器控制的数值,而非由用户提供的数据。这就确保了日志条目中绝对不会直接使用由用户
提供的输入。

可以按以下方式将例1重写为NumberFormatException对应的“预定义”日志条目:
...
public static final String NFE="Filed to prase val.The input is required to be an integer value";
...
String val=request.getParameter("val");
try{
   int value=Integer.parseInt(val);
}catch(NumberFormatException nfe){
   log.info(NFE);
}
...

在某些情况下,这个方法有些不切实际,因为这样一组合法的日志条目实在是太大或是太复杂了。
这中情况下,开发者往往又会退而采取黑名单方法。在输入之前,黑名单往往会有选择地拒绝或
避免潜在的危险字符。然而,不安全字符列表很快就会不完善或者过时。更好的方法是创建一个
白名单,允许其中的字符出现在日志条目中,并且只接受完全由这些经认可的字符组成的输入。
在大多数日志伪造攻击中,最关键的字符是“\n”(换行符),该字符坚决不能出现在日志条目白
名单中。

后话:
1.许多日志功能只是为了在开发或测试过程中调试程序而创建的。根据我们的经验,当生产的某一阶段,会随机或出于某一目的进行调试。不要仅仅因为程序员说“我没有计划在生产中其中调试功能”,就容忍日后伪造漏洞。

2.许多现代Web框架都提供对用户输入执行验证的机制。其中包括Struts和SpringMVC。




二、堆检查(Heap Inspection)
描述:

将敏感数据存储在String对象中使系统无法从内存中可靠地清除数据


举例:
如果在使用敏感数据(例如密码、社会保障码、信用卡号等)后不清除内存,则存储在内存中的
这些数据可能会泄露。通常而言,String被大部分开发者常用作存储敏感数据,然而,由于String
对象不可改变,因此用户只能使用JVM垃圾收集器来从内存中清除String的值。除非JVM内存不足,
否则系统不要求运行垃圾收集器,因此垃圾收集器何时运行并无保证。如果发生应用程序崩溃,
则应用程序的内存转储操作可能会导致敏感数据泄露。


例1:下列代码可将密码从字符数组转换为String。
private JPasswordFiled pf;
...
final char[] password=pf.getPassword();
...
String passwordAsString = new String(password);
...
由于passwordAsString为String对象,其内容未被改变,如果垃圾回收机制没有及时将
passwordAsString对象清除,则有可能发生数据泄露。


解决方案:
请始终确保不再需要使用敏感数据时将其清除。可使用能够通过程序清除的字节数组或字符数组来存储敏感数据,而不是将其存储在类似String的不可改变的对象中。

例2:下列代码可以在使用密码之后清除内存。
private JPasswordFiled pf;
...
final char[] password=pf.getPassword();
//使用密码
...
//密码使用完毕
Arrays.fill(password,'');
...

使用Arrays.fill()方法将password字符数组清除,从而保证敏感数据的安全。

转载请注明出处:http://blog.csdn.net/acmman/article/details/62446022

  • 3
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

光仔December

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值