1. HTML表单没有CSRF保护
CSRF(Cross-site request forgery),中文名称:跨站请求伪造,也被称为:one click attack/session riding,缩写为:CSRF/XSRF。
CSRF攻击:攻击者盗用了你的身份,以你的名义发送恶意请求。CSRF能够做的事情包括:以你名义发送邮件,发消息,盗取你的账号,甚至于购买商品,虚拟货币转账……造成的问题包括:个人隐私泄露以及财产安全。
CSRF的防御可以从服务端和客户端两方面着手,防御效果是从服务端着手效果比较好,现在一般的CSRF防御也都在服务端进行。有以下三种方法:
(1).Cookie Hashing(所有表单都包含同一个伪随机值):
(2).验证码
(3).One-Time Tokens(不同的表单包含一个不同的伪随机值)
1.服务端进行CSRF防御
服务端的CSRF方式方法很多样,但总的思想都是一致的,就是在客户端页面增加伪随机数。
这可能是最简单的解决方案了,因为攻击者不能获得第三方的Cookie(理论上),所以表单中的数据也就构造失败.
<?php
//构造加密的Cookie信息
$value = “DefenseSCRF”;
setcookie(”cookie”, $value, time()+3600);
?>
在表单里增加Hash值,以认证这确实是用户发送的请求。
<?php
$hash = md5($_COOKIE['cookie']);
?>
<form method=”POST” action=”transfer.php”>
<input type=”text” name=”toBankId”>
<input type=”text” name=”money”>
<input type=”hidden” name=”hash” value=”<?=$hash;?>”>
<input type=”submit” name=”submit” value=”Submit”>
</form>
然后在服务器端进行Hash值验证
<?php
if(isset($_POST['check'])) {
$hash = md5($_COOKIE['cookie']);
if($_POST['check'] == $hash) {
doJob();
} else {
//…
}
} else {
//…
}
?>
这个方法已经可以杜绝99%的CSRF攻击了,那还有1%….由于用户的Cookie很容易由于网站的XSS漏洞而被盗取,这就另外的1%。一般的攻击者看到有需要算Hash值,基本都会放弃了,某些除外,所以如果需要100%的杜绝,这个不是最好的方法。
这个方案的思路是:每次的用户提交都需要用户在表单中填写一个图片上的随机字符串,这个方案可以完全解决CSRF,但在易用性方面似乎不是太好,还有是验证码图片的使用涉及了一个被称为MHTML的Bug,可能在某些版本的微软IE中受影响。
在实现One-Time Tokens时,需要注意一点:就是“并行会话的兼容”。如果用户在一个站点上同时打开了两个不同的表单,CSRF保护措施不应该影响到他对任何表单的提交。考虑一下如果每次表单被装入时站点生成一个伪随机值来覆盖以前的伪随机值将会发生什么情况:用户只能成功地提交他最后打开的表单,因为所有其他的表单都含有非法的伪随机值。必须小心操作以确保CSRF保护措施不会影响选项卡式的浏览或者利用多个浏览器窗口浏览一个站点。
以下实现:
1).先是令牌生成函数(gen_token()):
<?php
function gen_token() {
//这是贪方便,实际上单使用Rand()得出的随机数作为令牌,也是不安全的。
//这个可以参考写的Findbugs笔记中的《Randomobject created and used only once》
$token = md5(uniqid(rand(), true));
return $token;
}
2).然后是Session令牌生成函数(gen_stoken()):
<?php
function gen_stoken() {
$pToken = “”;
if($_SESSION[STOKEN_NAME] == $pToken){
//没有值,赋新值
$_SESSION[STOKEN_NAME] = gen_token();
}
else{
//继续使用旧的值
}
}
?>
3).WEB表单生成隐藏输入域的函数:
<?php
function gen_input() {
gen_stoken();
echo “<input type=\”hidden\” name=\”” .FTOKEN_NAME . “\”
value=\”” . $_SESSION[STOKEN_NAME] . “\”> “;
}
?>
4).WEB表单结构:
<?php
session_start();
include(”functions.php”);
?>
<form method=”POST” action=”transfer.php”>
<input type=”text” name=”toBankId”>
<input type=”text” name=”money”>
<? gen_input(); ?>
<input type=”submit” name=”submit” value=”Submit”>
</FORM>
5).服务端核对令牌:
jQuery是继prototype之后又一个优秀的Javascrīpt框架。
jQuery 1.6.3之前版本中存在跨站脚本漏洞。当使用location.hash选择元素时,通过特制的标签,远程攻击者利用该漏洞注入任意web脚本或HTML。
目前厂商已经发布了升级补丁以修复此安全问题,补丁获取链接:
http://www.ubuntu.com/usn/USN-1722-1/
升级jQuery版本。
跨站脚本攻击是通过在网页中加入恶意代码,当访问者浏览网页时恶意代码会被执行或者通过给管理员发信息的方式诱使管理员浏览,从而获得管理员权限,控制整个网站。攻击者利用跨站请求伪造能够轻松地强迫用户的浏览器发出非故意的HTTP请求,如诈骗性的电汇请求、修改口令和下载非法的内容等请求。
风险等级:高
风险范围:
任何存在输入/输出方法(包括GET与POST)的页面皆可能存在恶意符号输入缺陷,主要影响应用包括留言板、在线通讯信息、文章发布页面等。
对用户输入的参数执行严格检测:
1、对产生漏洞模块的传入参数进行有效性检测。int类型的只允许0-9的整型数字;string等字符类型的只允许(1-9,a-z,A-Z)的英文字母;
2、当客户端输入限定值意外的字符后,立即转向自定义的错误页,而不能使用服务器默认的错误输出方式;
3、对穿入参数进行危险字符过滤,禁止('、"、+、%、&、<>、()、;、,.等)特殊字符的传入。
加固范例(一):
/*将login.jsp中[String u =request.getParameter("u");]替换为如下内容:*/
String u = request.getParameter("u");
u = u.replace ('<','_');
u = u.replace ('>','_');
u = u.replace('"','_');
u = u.replace('\'','_');
u = u.replace ('%','_');
u = u.replace(';','_');
u = u.replace('(','_');
u = u.replace(')','_');
u = u.replace('&','_');
u = u.replace('+','_');
加固范例(二):
/*更积极的方式是利用正则表达式只允许输入指定的字符:*/
/*在[String u = request.getParameter("u");]后代入以下isValidInput函数作辨别*/
public boolean isValidInput(Stringstr)
{
if(str.matches("[a-z0-9]+"))return true;
else return false;
}
通过构建URL,攻击者可以使用户重定向到任意URL,利用这个漏洞可以诱使用户访问某个页面,挂马、密码记录、下载任意文件等,常被用来钓鱼。
对输入参数进行做处理,建议过滤出所有以下字符:
[1] |(竖线符号)
[2] & (& 符号)
[3];(分号)
[4] $(美元符号)
[5] %(百分比符号)
[6] @(at 符号)
[7] '(单引号)
[8] "(引号)
[9] \'(反斜杠转义单引号)
[10] \"(反斜杠转义引号)
[11] <>(尖括号)
[12] ()(括号)
[13] +(加号)
[14] CR(回车符,ASCII 0x0d)
[15] LF(换行,ASCII 0x0a)
[16] ,(逗号)
[17] \(反斜杠)
对输入参数进行做处理。
加固范例(一):
/*将login.jsp中[String u = request.getParameter("u");]替换为如下内容:*/
String u =request.getParameter("u");
u = u.replace ('<','_');
u = u.replace ('>','_');
u = u.replace ('"','_');
u = u.replace ('\'','_');
u = u.replace ('%','_');
u = u.replace (';','_');
u = u.replace ('(','_');
u = u.replace (')','_');
u = u.replace ('&','_');
u = u.replace ('+','_');
加固范例(二):
/*更积极的方式是利用正则表达式只允许输入指定的字符:*/
/*在[String u = request.getParameter("u");]后代入以下isValidInput函数作辨别*/
public boolean isValidInput(String str)
{
if(str.matches("[a-z0-9]+")) returntrue;
else return false;
}
不安全存储,在页面上显示密码。
加密密码或不在页面及源码上显示密码。
一切涉及敏感信息读写操作的页面,如登陆页面、登陆处理页面等。
风险范例:
/*Add_user.jsp*/
String sql;
sql="insert into user(username,password) values (" + Username + "," + Password +")";
Statement sm = cn.createStatement();
sm.executeUpdate(sql);
sm.close();
加固范例:
/*在生成sql变量内容前加入对Password变量的加密处理:*/
<%@ pageimport="java.security.*" %>
<%@ pageimport="java.util.*" %>
…
public String byte2hex(byte[] b)//二行制转字符串
{
Stringhs="";
Stringstmp="";
for(int n=0;n<b.length;n++)
{
stmp=(java.lang.Integer.toHexString(b[n]& 0XFF));
if(stmp.length()==1) hs=hs+"0"+stmp;
elsehs=hs+stmp;
//if(n<b.length-1) hs=hs+":";
}
returnhs.toUpperCase();
}
…
java.security.MessageDigestalg=java.security.MessageDigest.getInstance("SHA-256");
alg.update(Password.getBytes());
byte[] digest=alg.digest();
Password=byte2hex(digest);
错误/警告消息,可能会泄露敏感信息。
在编码阶段开发者对敏感页面缺乏授权保护,导致相关URL页面敏感信息泄露。建议修改错误信息。
一切敏感或需要权限方可浏览的页面,包括:敏感信息中转处理页面、上传页面、管理平台页面、用户自管理页面等。
风险范例:
/*风险范例为一切需要敏感但编码阶段没有进行授权鉴别的页面*/
加固范例:
if((session.getValue("UserName")==null)||(session.getValue("UserClass")==null)||(!session.getValue("UserClass").equals("系统管理员")))
{
response.sendRedirect("err.jsp?id=14");
return;
}
用户名、密码输入字段未经加密即进行了传递。
确保所有登录请求都以https加密方式发送到服务器。
方法一:配置SSL加密传输
【概念理解】keystore 是一个密码保护的文件,用来存储密钥和证书
(1)生成一个keystore文件(包含证书),文件位置/usr/local/tomcat/conf/.keystore
# cd /usr/local/jdk/bin/
# ./keytool -genkey -alias tomcat -keyalg RSA -keystore/usr/local/tomcat/conf/.keystore
输入密码、提供你的信息即可。如果不是用来“玩”的话,请如实的填写自己以及单位的信息吧。
【注意】它会在前后问你两次密码,第二次直接回车就行了,如果两个密码不一样,将会出现java.io.IOException错误。详情请见:[url]http://issues.apache.org/bugzilla/show_bug.cgi?id=38217[/url]
(2)修改tomcat/conf/server.xml
启用这一段:
<Connector port="8443"protocol="HTTP/1.1" SSLEnabled="true"
maxThreads="150" scheme="https" secure="true"
clientAuth="false"sslProtocol="TLS" />
并修改为:
<Connector port="8443" protocol="HTTP/1.1"SSLEnabled="true"
maxThreads="150" scheme="https" secure="true"
keystoreFile="/usr/local/tomcat/conf/.keystore"
keystorePass="snailwarrior"
clientAuth="false" sslProtocol="TLS" />
(3)重启Tomcat
# /usr/local/tomcat/bin/shutdown.sh
# /usr/local/tomcat/bin/startup.sh
(4)防火墙开启8443端口
浏览器输入:[url]https://192.168.32.50:8443/[/url]
方法二:把text="password"这个用其他的代替,就可以解决已解密的登录请求,仅共参考
<div><li>密 码:<input type="text"id="password1" style="width:146px;height:18px;"
onkeypress="javascript:hiddenPass(event)"onkeyup="this.value=this.value.replace(/./g,'*');"/></li>
<li><inputid="password" type="hidden"name="password"/></li>
<div>
js代码
functionhiddenPass(e){
e = e ? e : window.event;
var kcode = e.which ? e.which : e.keyCode;
var pass =document.getElementByIdx_x("password1");
var j_pass = document.getElementByIdx_x("password");
if(kcode!=8)
{
var keychar=String.fromCharCode(kcode);
j_pass.value=j_pass.value+keychar;
j_pass.value=j_pass.value.substring(0,pass.length);
}
}
获取密码:document.getElementByIdx_x("password").value;
HTTP存在DOS漏洞。
如果远程攻击者使用发包工具向Apache服务器发送了不完整的HTTP请求,服务器会打开连接等待接受完整的头,但如果发包工具不再继续发送完整请求而是发送无效头的话,就会一直保持打开的连接。这种攻击所造成的影响很严重,因为攻击者不需要发送很大的通讯就可以耗尽服务器上的可用连接。也就是说,即使低带宽的用户也可以攻击大流量的服务器。
临时解决方法:
更改默认的TimeOut选项少于7000ms,或使用mod_limitipconn模块限制单个IP地址的连接数。
厂商补丁:
Apache Group
------------
目前厂商还没有提供补丁或者升级程序,我们建议使用此软件的用户随时关注厂商的主页以获取最新版本:http://www.apache.org
关于HTTP版本低漏洞信息,如下:
1).漏洞的描述
http://www.venustech.com.cn/NewsInfo/124/17205.Html
2).TOMCAT官网说这个不是一个漏洞,没有打算出补丁,只有缓解方法
详细可以看,
http://tomcat.apache.org/security-6.html#Not_a_vulnerability_in_Tomcat
查找 CVE-2012-5568 会看到官网说明。
缓解方法
通过server.xml内定义的连接器的connectionTimeout属性,配置一个合适的超时时间。
https://blogs.oracle.com/jyrivirkki/entry/web_server_7_meets_slowloris
3).但CVE 的漏洞还是所有版本也存在。下面是一个CVE的详细信息地址,此页面最后更新为2013-03-07,当时6.0.35为最新版本。
http://www.cvedetails.com/cve-details.php?t=1&cve_id=CVE-2012-5568
4).公开的漏洞测试代码
http://ha.ckers.org/slowloris/slowloris.pl
同“1.HTML表单没有CSRF保护”。
同“6.错误的页面信息”
受外部影响的输入来构造SQL 命令的全部或一部分,但是它对可能在所需 SQL 命令发送到数据库时修改该命令的特殊元素未正确进行无害化处理。如果在用户可控制的输入中没有对 SQL 语法充分地除去或引用,那么生成的 SQL 查询可能会导致将这些输入解释为 SQL 而不是普通用户数据。这可用于修改查询逻辑以绕过安全性检查,或者插入其他用于修改后端数据库的语句,并可能包括执行系统命令。
public static String filterContent(Stringcontent){
String flt ="'|and|exec|insert|select|delete|update|count|*|%|chr|mid|master|truncate|char|declare|;|or|-|+|,";
Stringfilter[] = flt.split("|");
for(int i=0;i<filter.length ; i++)
{
content.replace(filter[i], "");
}
return content;
}
参考信息:http://www.owasp.org/index.php/Top_10_2010-A1
Apache/IIS等版本过低存在众多安全漏洞。
升级Apache/IIS等到最新版本。
攻击者可以利用“~”字符猜解或遍历服务器中的文件名,或对IIS服务器中的.Net Framework进行拒绝服务攻击。
升级netframework 至4.0以上版本。
可能会收集有关 Web 应用程序的敏感信息,如用户名、密码、机器名和/或敏感文件位置。
在 Web.Config 文件的 <system.web> 元素之下,添加下面这一行:
<machineKey validation="3DES"/>
Unicode编码未指定
在源码内指定编码类型即可解决如:UTF-8
发现SSL证书信息
使用公认第三方如CA的签名证书。
可能会查看和下载特定 Web应用程序虚拟目录的内容,其中可能包含受限文件。
[1] 将 Web 服务器配置成拒绝列出目录。
[2] 根据 Web 服务器或 Web 应用程序上现有的问题来下载特定安全补丁。部分已知的目录列表问题列在这个咨询的“引用”字段中。
[3] 利用“CERT”咨询中的变通方法(在这项咨询的“引用”字段中)来修订短文件名(8.3 DOS 格式)问题:
a. 想要完全由 Web 服务器来保护的文件仅用 8.3 标准短文件名。在FAT 文件系统(16 位)上,您可以启用“Win31FileSystem”注册表键(设为 1,注册表路径:HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\FileSystem\)来强制这一点。
b. 在 NTFS(32 位)上,您可以启用“NtfsDisable8dot3NameCreation”注册表键(设为 1,注册表路径:HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\FileSystem\)来禁用创建长文件名文件的8.3 标准短文件名。不过,这个步骤可能会引起与16 位应用程序的兼容性问题。
c. 使用基于 NTFS 的 ACL(目录或文件级别的访问控制表)来扩增或替换基于 Web 服务器的安全。
存在不必要的备份残留文件,可能会被信息采集进入步深入渗透。
删除不必要的备份文件。
使用.NETFramework所编译的ASP.Net应用中没有正确地实现加密,攻击者可以解密并篡改敏感数据。
如果要理解这个漏洞,首先要了解加密系统中的提示机制,当你提出问题时提示机制会给出某种形式的答案。此漏洞涉及到ASP.NET对加密信息中填充数据的提示,攻击者可以通过向Web服务器发送特定的密文文本,然后通过检查所返回的出错代码来判断数据是否被正确解密。通过反复上述操作,攻击者就可以收集到足够的信息用来解密剩余部分的密文文本。
打上MS10-070漏洞补丁。
不安全明文传输登录请求。
使用SSL加密。
不安全明文传输方式。
使用所以页面通过SSL加密。
struts2框架版本过低,存在远程任意命令执行漏洞。
升级struts2框架到最新版本。
使用如:123456、test等弱口令。
按电信密码规范要求配置口令。
可能会在 Web 服务器上运行远程命令。这通常意味着完全破坏服务器及其内容。
假定所有输入都是恶意的。使用“接受已知善意”输入验证策略:严格遵守规范的可接受输入的白名单。拒绝任何没有严格遵守规范的输入,或者将其转换为遵守规范的内容。不要完全依赖于将恶意或格式错误的输入加入黑名单。但是,黑名单可帮助检测潜在攻击,或者确定哪些输入格式不正确,以致应当将其彻底拒绝。
执行输入验证时,请考虑所有潜在相关属性,包括长度、输入类型、可接受值的完整范围、缺失或多余输入、语法、跨相关字段的一致性以及业务规则一致性。以业务规则逻辑为例,“boat”可能在语法上有效,因为它仅包含字母数字字符,但如果预期为颜色(如“red”或“blue”),那么它无效。
对于文件名,请使用限制要使用的字符集的严格白名单。如果可行,请仅允许文件名中出现单个“.”字符以避免 CWE-23 之类的弱点,并排除“/”之类的目录分隔符以避免 CWE-36。请使用允许的文件扩展名的白名单,这有助于避免 CWE-434。
源代码暴露。
删除源代码文件或对需要的未解析的源代码进行解析。
SSL证书过期或SSL证书不合法等。
重新生成配置SSL证书。
SSL证书加密方式弱,导致加密信息可能被解密。
重新生成SSL证书,加密算法选择如:RSA-1024等。
攻击者可能注入自定义HTTP头。例如,攻击者可以注入会话cookie或HTML代码。这可能会进行类似的XSS(跨站点脚本)或会话固定漏洞。
这种现象往往表现在带有参数传递的网页,只要合理的过滤好就OK啦,提供PHP代码:
$post =trim($post);
2 $post =strip_tags($post,""); //清除HTML如<br />等代码
3 $post =ereg_replace("\t","",$post); //去掉制表符号
4 $post =ereg_replace("\r\n","",$post); //去掉回车换行符号
5 $post =ereg_replace("\r","",$post); //去掉回车
6 $post =ereg_replace("\n","",$post); //去掉换行
7 $post =ereg_replace(" ","",$post); //去掉空格
8 $post= ereg_replace("'","",$post); //去掉单引号
同上:Http请求头的额外的回车换行符注入。
使用GET方法MBean提交密码字段。
更改为POST提交方法。
发现JBoss框架登录管理后台等信息。
限制JBOSS控制台等目录访问权限。
Apache Tomcat版本过低
升级ApacheTomcat到最新版本。
发现存在ApacheTomcat的示例文件、控制台等信息。
删除ApacheTomcat的示例文件及控制台相关文件。
发现系统、数据库类等漏洞没法加固或暂时无法加固。
关闭不必要的应用或使用系统防火墙限制非公众使用的端口进行来源绑定访问。
发现XSS、SQL等漏洞的应急加固办法。
apache commons-lang工具包里的类,可以在工程中写一个过滤器,使用该工具类去实现敏感字符的过滤。
过滤器示例1参考地址:http://my.oschina.net/mousai/blog/88832
过滤器示例2如下:
使用JAVA过滤器对攻击特征进行过滤如:
一。写一个过滤器
代码如下:
package com.liufeng.sys.filter;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
importjavax.servlet.http.HttpServletRequest;
importjavax.servlet.http.HttpServletResponse;
public class IllegalCharacterFilterimplements Filter {
private String[] characterParams =null;
private boolean OK=true;
public void destroy() {
// TODO Auto-generated method stub
}
/**
* 此程序块主要用来解决参数带非法字符等过滤功能
*/
public void doFilter(ServletRequest request,ServletResponse response,
FilterChain arg2) throwsIOException, ServletException {
HttpServletRequest servletrequest =(HttpServletRequest) request;
HttpServletResponse servletresponse= (HttpServletResponse) response;
boolean status = false;
java.util.Enumeration params =request.getParameterNames();
String param="";
String paramValue ="";
servletresponse.setContentType("text/html");
servletresponse.setCharacterEncoding("utf-8");
while(params.hasMoreElements()) {
param = (String)params.nextElement();
String[] values =request.getParameterValues(param);
paramValue = "";
if(OK){//过滤字符串为0个时不对字符过滤
for (int i = 0; i <values.length; i++)
paramValue=paramValue+values[i];
for(inti=0;i<characterParams.length;i++)
if(paramValue.indexOf(characterParams[i]) >= 0) {
status = true;
break; www.2cto.com
}
if(status)break;
}
}
// System.out.println(param+"="+paramValue+";");
if (status) {
PrintWriter out =servletresponse.getWriter();
out
.print("<script language='javascript'>alert(\"对不起!您输入内容含有非法字符。如:\\\"'\\\".等\");"
// +servletrequest.getRequestURL()
+"window.history.go(-1);</script>");
}else
arg2.doFilter(request,response);
}
public void init(FilterConfig config)throws ServletException {
if(config.getInitParameter("characterParams").length()<1)
OK=false;
else
this.characterParams = config.getInitParameter("characterParams").split(",");
}
}
二。在web.xml文件中加入如下内容:
<!-- 非法字符过滤器 -->
<filter>
<filter-name>IllegalCharacterFilter</filter-name>
<filter-class>
com.liufeng.sys.filter.IllegalCharacterFilter
</filter-class>
<init-param>
<param-name>characterParams</param-name>
<param-value>',@</param-value><!-- 此处加入要过滤的字符或字符串,以逗号隔开 -->
</init-param>
</filter>
<filter-mapping>
<filter-name>IllegalCharacterFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
重启你的服务器就OK了。
这样,增加此过滤器后能提高网站的安全,防止SQL注入,防止跨站脚本XSS等。