如何防止JAVA程序源代码被反编译我们都知道JAVA是一种解析型语言 , 这就决定JAVA文件编译后不是机器码,而是一个字节码文件,也就是CLASS文件 。而这样的文件是存在规律的,经过反编译工具是可以还原回来的 。例如Decafe、FrontEnd,YingJAD和Jode等等软件 。下面是《Nokia中Short数组转换算法》
类中Main函数的ByteCode:0 ldc #162 invokestatic #185 astore_16 return其源代码是:short [] pixels = parseImage("/ef1s.png");
我们通过反编译工具是可以还原出以上源代码的 。而通过简单的分析,我们也能自己写出源代码的 。
第一行:ldc #16
ldc为虚拟机的指令 , 作用是:压入常量池的项,形式如下ldc index这个index就是上面的16,也就是在常量池中的有效索引 , 当我们去看常量池的时候,我们就会找到index为16的值为String_info,里面存了/ef1s.png.
所以这行的意思就是把/ef1s.pn作为一个String存在常量池中,其有效索引为16 。
第二行:2 invokestatic #18
invokestatic为虚拟机指令,作用是:调用类(static)方法,形式如下
invokestatic indexbyte1 indexbyte2
其中indexbyte1和indexbyte2必须是在常量池中的有效索引,而是指向的类型必须有Methodref标记 , 对类名,方法名和方法的描述符的引用 。
所以当我们看常量池中索引为18的地方,我们就会得到以下信息:
Class Name : cp_info#1
Name Type : cp_info#19
1 和19都是常量池中的有效索引,值就是右边中的值,再往下跟踪我就不多说了,有兴趣的朋友可以去JAVA虚拟机规范 。
这里我简单介绍一下parseImage(Ljava/lang/String;)[S 的意思 。
这就是parseImage这个函数的运行,我们反过来看看parseImage的原型就明白了
short [] parseImage(String)
那么Ljava/lang/String;就是说需要传入一个String对象,而为什么前面要有一个L呢 , 这是JAVA虚拟机用来表示这是一个Object 。如果是基本类型,这里就不需要有L了 。然后返回为short的一维数组,也就是对应的[S 。是不是很有意思 , S对应着Short类型,而“[”对应一维数组,那有些朋友要问了,两维呢 , 那就“[[”,呵呵,是不是很有意思 。
好了,调用了函数,返回的值要保存下来吧 。那么就是第三行要做的事情了 。
如何防止java文件被反编译无法防止 。.class文件的标准是公开的 , 无法防止别人反编译你的代码 。
你顶多可以用代码扰乱工具扰乱你的代码,这样反编译的代码就难以阅读 。比如可以试试用proguard来扰乱(“加密”)和反扰乱(“解密”)你的代码 。
但是java有那么多很不错的代码阅读分析工具,即使你用了扰乱器,也不能保证代码的安全 。
如何防止别人看到网页源代码如果我们要防止别人看网页源代码,那我们先分析下别人是怎么查看网页源代码的吧 。一般我们都知道通过IE也就是我们所说的微软出品的IE浏览器,当你打开一个网页的时候,等她完全加载好之后,点击浏览器菜单栏里的“查看”,里面有“源文件”选项(或者在网页的空白处右击,选择“查看源文件”就也可以查看到网页源代码了) 。
现在一般很多人是通过JS来防止别人查看网页源代码的 , 具体的方法也比较多 , 这边炬点网就为大家简单整理了几个方法,不过这些既然叫“方法”那必然会有高手有方法还是能破解开的 。
一、下面的这个还算是比较好的防止查看网页源代码的方法,大家也可以试试?
html
head
script language="javascript"
function clear(){
Source=document.body.firstChild.data;
document.open();
document.close();
document.title="看不到源代码";
document.body.innerHTML=Source;
}
/script
/head
body onload=clear()
!--
a href="https://www.04ip.com/post/;炬点网/a源代码好像是不让看的!--
/body
/html
二、下面的这个方法是防止别人在网页上面使用右键查看网页源代码的方法 , 大家可以看看 。
SCRIPT language=javascript
function click() { if (event.button==2) { alert(\'对不起,禁止使用此功能^_^.\') } } document.onmousedown=click
/SCRIPT
script language="JavaScript"
!-- locate = 0; function scroller()
{ if (locate !=500 ) { locate; scroll(0,locate); clearTimeout(timer); var timer = setTimeout("scroller()",3); timer; } } // --
/script
这第二种方法 , 大家需要在HTML代码中加入“SCRIPT language=javascript function click() {if (event.button==2) {alert('不能查看!');}}document.onmousedown=click /SCRIPT”一段代码的 。
三、直接让你在浏览网页的时候右键点击失效,下面的我们应用的代码 。
script language="JavaScript"
!--
if (window.Event)
document.captureEvents(Event.MOUSEUP);
function nocontextmenu()
{
event.cancelBubble = true
event.returnValue = https://www.04ip.com/post/false;
return false;
}
function norightclick(e)
{if (window.Event)
{
if (e.which == 2 || e.which == 3)
return false;
}
else
【怎么防止java代码被看 java如何开启防止抓包】if (event.button == 2 || event.button == 3)
{
event.cancelBubble = true
event.returnValue = https://www.04ip.com/post/false;
return false;
}
}
document.oncontextmenu = nocontextmenu; // for IE5
document.onmousedown = norightclick; // for all others
//--
/script
四、屏蔽右键菜单查看方式
Script Language=java script
function Click(){
alert('版权所有(C)XXXltd.');
window.event.returnValue=https://www.04ip.com/post/false;
}
document.oncontextmenu=Click;
/Script
这样无论采取什么方式点击鼠标,都不会再出现快捷菜单了 。不过值得注意的是,如果访问者直接在浏览器地址栏中键入"java script:alert(document.oncontextmenu='')",就可以解除对右键菜单的屏蔽 。
五、屏蔽窗口菜单栏查看方式(这个方式其实是对第四点的一个防范了)这个方法是对新打开窗口的各种属性可以进行控制,具体包括控制菜单栏、滚动条及地址栏是否可见等 。如果把父窗口关闭,并将新打开窗口的菜单栏和地址栏隐藏,不就可以屏蔽窗口菜单栏查看方式了吗?实现代码如下:
Head
Object id=closes type="application/x-oleobject"
classid="clsid:adb880a6-d8ff-11cf-9377-00aa003b7a11"
Param name="Command" value="https://www.04ip.com/post/Close"
/Object
/Head
Body
Script Language=java script
closes.Click()
window.open("网页文件名.htm","","menubar=no,location=no,
scrollbars=yes,resizable=yes")
/Script
/Body
这种法的原理就是首先将自己网站的首页制作成index.htm形式,把首页设计成一个过渡页 。然后将自己的真正主页制作成default.htm形式(具体实现过程见本文所附源代码) 。这样访问者无论如何也无法查看网页源代码了 。这不仅仅保护了您的版权,也为进一步开发提供了保障 。通过此方法 , 您可以结合Cookie技术,真正做到限制用户浏览网页,从而避免主页资料被非法访问者访问 。
不过话又说回来了,人家网易、新浪她们怎么没有防止人家查看网页源代码呢?你一个小小的站长这么矫情?当然这个不是这样讲的啦 。毕竟人家那些大型网站可能和一些网络的爱好者们不同啦 。
此外,炬点还想指出的是,有些禁用页面效果的Javascript脚本在Firefox浏览器里就会失效的,再加上Firefox的网页开发插件 , 那就更加如虎添翼了 。所以呢,有时候我们在绞尽脑汁不想让别人查看到源代码的时候,别人当然也能够通过一定的方法来和你较劲啦!其实 , 如果人家真想看源代码是没办法阻止的,不然你只能对服务器进行加密处理咯 。
java正则表达式怎么防止代码漏洞javaWeb安全漏洞及处理方式
关注
转载自怎么防止java代码被看:
1、SQL注入攻击
SQL注入攻击就是通过把SQL命令插入到Web表单提交或输入域名或页面请求的查询字符串,最终达到欺骗服务器执行恶意的SQL命令 。具体来说 , 它是利用现有应用程序,将(恶意)的SQL命令注入到后台数据库引擎执行的能力,它可以通过在Web表单中输入(恶意)SQL语句得到一个存在安全漏洞的网站上的数据库 , 而不是按照设计者意图去执行SQL语句 。
随着B/S框架结构在系统开发中的广泛应用,恶意攻击者利用SQL命令在Web表单中输入合法的字符或查询字符串来欺骗服务器执行SQL命令 。当注入攻击得逞后,Web程序将泄露大量用户隐私数据和数据库中数据结构 。攻击者能够获得系统较高的访问权限 , 进行破坏操作 。
SQL注入可以分为平台层注入和代码层注入 。前者由不安全的数据库配置或数据库平台的漏洞所致;后者主要是由于程序员对输入未进行细致地过滤,从而执行怎么防止java代码被看了非法的数据查询 。基于此,SQL注入的产生原因通常表现在以下几方面:
1)不当的类型处理;
2)不安全的数据库配置;
3)不合理的查询集处理;
4)不当的错误处理;
5)转义字符处理不合适;
6) 多个提交处理不当 。
解决方法:
数据库安全通信包括SQL注入攻击的防范、安全设置、异常信息处理三个方面 。
1.服务端Filter对访问者输入的字符进行过滤检验,但是攻击者经常把危险字符潜藏在用户输入的有效字符中完 成过滤检验 。
2.通过正则表达式对页面的文本框输入的数据进行限制可以减少过滤检验存在的漏洞 。
3.使用prepareStatment预编译sql语句
2、XSS跨站脚本攻击
跨站脚本(Cross-site scripting,简称XSS) , 是一种迫使Web站点回显可执行代码的攻击技术,而这些可执行代码由攻击者提供、最终为用户浏览器加载 。不同于大多数攻击(一般只涉及攻击者和受害者),XSS涉及到三方 , 即攻击者、客户端与网站 。XSS的攻击目标是为了盗取客户端的cookie或者其他网站用于识别客户端身份的敏感信息 。获取到合法用户的信息后,攻击者甚至可以假冒最终用户与网站进行交互 。
XSS 属于被动式的攻击 。攻击者先构造一个跨站页面,利用SCRIPT、IMG、IFRAME等各种方式使得用户浏览这个页面时 , 触发对被攻击站点的HTTP 请求 。此时,如果被攻击者如果已经在被攻击站点登录,就会持有该站点cookie 。这样该站点会认为被攻击者发起了一个HTTP请求 。而实际上这个请求是在被攻击者不知情情况下发起的,由此攻击者在一定程度上达到了冒充被攻击者的目的 。精心的构造这个攻击请求,可以达到冒充发文 , 夺取权限等多个攻击目的 。在常见的攻击实例中,这个请求是通过script 来发起的,因此被称为Cross Site Script 。
XSS漏洞成因是由于动态网页的Web应用对用户提交请求参数未做充分的检查过滤,允许用户在提交的数据中掺入HTML代码(最主要的是“”、“”),然后未加编码地输出到第三方用户的浏览器,这些攻击者恶意提交代码会被受害用户的浏览器解释执行 。
分为三种类型:
1)反射型(数据流向:浏览器 -后端 - 浏览器)
反射型XSS脚本攻击即如我们上面所提到的XSS跨站脚本攻击方式,该类型只是简单地将用户输入的数据直接或未经过完善的安全过滤就在浏览器中进行输出,导致输出的数据中存在可被浏览器执行的代码数据 。由于此种类型的跨站代码存在于URL中,所以黑客通常需要通过诱骗或加密变形等方式 , 将存在恶意代码的链接发给用户,只有用户点击以后才能使得攻击成功实施 。
2)存储型(数据流向是:浏览器 -后端 - 数据库 - 后端- 浏览器)
存储型XSS脚本攻击是指Web应用程序会将用户输入的数据信息保存在服务端的数据库或其他文件形式中,网页进行数据查询展示时,会从数据库中获取数据内容,并将数据内容在网页中进行输出展示,因此存储型XSS具有较强的稳定性 。
存储型XSS脚本攻击最为常见的场景就是在博客或新闻发布系统中,黑客将包含有恶意代码的数据信息直接写入文章或文章评论中 , 所有浏览文章或评论的用户,都会在他们客户端浏览器环境中执行插入的恶意代码 。
3)基于DOM(数据流向是:URL--浏览器 )
基于DOM的XSS跨站脚本攻击是通过修改页面DOM节点数据信息而形成的XSS跨站脚本攻击 。不同于反射型XSS和存储型XSS,基于DOM的XSS跨站脚本攻击往往需要针对具体的javascript DOM代码进行分析,并根据实际情况进行XSS跨站脚本攻击的利用 。
解决方法:
1).输入过滤 。对用户的所有输入数据进行检测 , 比如过滤其中的“”、“”、“/”等可能导致脚本注入的特殊字符,或者过滤“script”、“javascript”等脚本关键字,或者对输入数据的长度进行限制等等 。同时 , 我们也要考虑用户可能绕开ASCII码,使用十六进制编码来输入脚本 。因此,对用户输入的十六进制编码 , 我们也要进行相应的过滤 。只要能够严格检测每一处交互点,保证对所有用户可能的输入都进行检测和XSS过滤 , 就能够有效地阻止XSS攻击 。
2).输出编码 。通过前面对XSS攻击的分析,我们可以看到,之所以会产生XSS攻击,就是因为Web应用程序将用户的输入直接嵌入到某个页面当中,作为该页面的HTML代码的一部分 。因此,当Web应用程序将用户的输入数据输出到目标页面中时 , 只要用HtmlEncoder等工具先对这些数据进行编码,然后再输出到目标页面中 。这样,如果用户输入一些HTML的脚本,也会被当成普通的文字,而不会成为目标页面HTML代码的一部分得到执行.
3、CSRF跨站请求伪造漏洞防护
CSRF是CrossSite Request Forgery的缩写,乍一看和XSS差不多的样子,但是其原理正好相反 , XSS是利用合法用户获取其信息 , 而CSRF是伪造成合法用户发起请求 。
字面理解意思就是在别的站点伪造了一个请求 。专业术语来说就是在受害者访问一个网站时,其 Cookie 还没有过期的情况下 , 攻击者伪造一个链接地址发送受害者并欺骗让其点击,从而形成 CSRF 攻击 。
根据HTTP协议,在HTTP头中有一个字段叫Referer,它记录了该HTTP请求的来源地址 。在通常情况下,访问一个安全受限页面的请求必须来自于同一个网站 。
解决方案:
配置FILTER拦截用户所有请求(POST/GET),对用户请求Referer头URL进行合法性校验 。
4、URL链接注入漏洞防护
链接注入是修改站点内容的行为,其方式为将外部站点的 URL 嵌入其中,或将有易受攻击的站点中的脚本 的 URL 嵌入其中 。将URL 嵌入易受攻击的站点中,攻击者便能够以它为平台来启动对其他站点的攻击,以及攻击这个易受攻击的站点本身 。
解决方案:
1,二次验证,进行重要敏感操作时,要求用户进行二次验证 。
2,验证码,进行重要敏感操作时,加入验证码 。
3,验证 HTTP 的 Referer 字段 。
4,请求地址中添加 Token 并验证 。
5,HTTP 头中自定义属性并验证 。
5、会话COOKIE中缺少HttpOnly防护
会话cookie中缺少HttpOnly属性会导致攻击者可以通过程序(JS脚本、Applet等)获取到用户的cookie信息,造成用户cookie信息泄露,增加攻击者的跨站脚本攻击威胁 。
HttpOnly是微软对cookie做的扩展,该值指定cookie是否可通过客户端脚本访问 。Microsoft Internet Explorer 版本 6 Service Pack 1 和更高版本支持cookie属性HttpOnly 。
如果在Cookie中没有设置HttpOnly属性为true,可能导致Cookie被窃取 。窃取的Cookie可以包含标识站点用户的敏感信息 。
如果在Cookie中设置HttpOnly属性为true,兼容浏览器接收到HttpOnly cookie,那么客户端通过程序(JS脚本、Applet等)将无法读取到Cookie信息,这将有助于缓解跨站点脚本威胁 。
解决方案:
配置filter拦截器,将服务器端返回请求,向所有会话cookie中添加“HttpOnly”属性 。
示例代码:
HttpServletResponseresponse=(HttpServletResponse)paramServletResponse;
response.setHeader("SET-COOKIE","JSESSIONID="sessionid"; HttpOnly");
6、点击劫持漏洞(Clickjacking)防护
点击劫持是一种视觉上的欺骗手段,攻击者使用一个透明的、不可见的iframe,覆盖在一个网页上 , 然后诱使用户在该网页上进行操作,此时用户在不知情的情况下点击了透明的iframe页面 。通过调整iframe页面的位置,可以诱使用户恰好点击在iframe页面的一些功能性按钮上 。
解决方案:
配置FILTER拦截器 , 在服务器端返回请求中,使用一个HTTP头“X-Frame-Options”值为SAMEORIGIN-同源策略,则frame页面的地址只能为同源域名下面的页面 , 防止点击劫持漏洞发生 。
示例代码:
HttpServletResponseresponse=(HttpServletResponse)paramServletResponse;
response.addHeader("x-frame-options","SAMEORIGIN");
7、HTTP host 头攻击漏洞
使用HTTP代理工具,可以篡改HTTP报文头部中HOST字段时 , 该值可被注入恶意代码 。因为需要控制客户端的输入,故该漏洞较难利用 。
解决方案:
配置FILTER拦截器,对请求输入HOST头信息进行信息安全性校验 , 防止HOST头信息被恶意篡改利用 。
示例代码:
HttpServletRequest request =(HttpServletRequest)servletRequest;
//主机ip和端口 或 域名和端口
String myhosts = request.getHeader("host");
if(!StringUtils.equals(myhosts, "xx.xx.xxx.xxx:xxxx")
!StringUtils.equals(myhosts, "xx.xx.xxx.xxx:xxxx")
!StringUtils.equals(myhosts,"xx.xx.xxx.xxx:xxxx")StringUtils.equals(myhosts,"xx.xx.xxx.xxx")
!StringUtils.equals(myhosts,"xx.xx.xxx.xxx")!StringUtils.equals(myhosts,"xx.xx.xxx.xxx" ){
logger.error("======访问host非法,已拦截======");
response.sendRedirect(request.getContextPath()"/login.jsp");
return;
}
8、越权访问漏洞防护
越权访问(Broken Access Control , 简称BAC)是Web应用程序中一种常见的漏洞,分为垂直越权访问和水平越权访问 。垂直越权是指不同用户级别之间的越权,如普通用户执行管理员用户的权限 。水平越权是指相同级别用户之间的越权操作 。
Web应用程序如果存在越权访问漏洞 , 可能导致以下危害:
1)导致任意用户敏感信息泄露怎么防止java代码被看;
2)导致任意用户信息被恶意修改或删除 。
解决方案:
配置FILTER拦截器,对请求所有URL进行拦截 , 对于需要进行授权的URL进行权限校验,防止用户越权访问系统资源 。
9.弱口令漏洞
解决方案:最好使用至少6位的数字、字母及特殊字符组合作为密码 。数据库不要存储明文密码,应存储MD5加密后的密文,由于目前普通的MD5加密已经可以被破解 , 最好可以多重MD5加密,或者多种加密方式叠加组合 。
10.JSP页面抛出的异常可能暴露程序信息 。
有经验的入侵者,可以从JSP程序的异常中获取很多信息,比如程序的部分架构、程序的物理路径、SQL注入爆出来的信息等 。
解决方案:自定义一个Exception , 将异常信息包装起来不要抛到页面上 。
11.本地缓存漏洞
合法用户“注销”后,在未关闭浏览器的情况下,点击浏览器“后退”按钮,可从本地页面缓存中读取数据,绕过了服务端filter过滤 。
解决方案:配置filter对存放敏感信息的页面限制页面缓存 。如:
httpResponse.setHeader("Cache-Control","no-cache");
httpResponse.setHeader("Cache-Control","no-store");
httpResponse.setDateHeader("Expires",0);
httpResponse.setHeader("Pragma","no-cache");
12.文件上传漏洞 。
前台仅使用JS对文件后缀做了过滤,这只能针对普通的用户,而恶意攻击者完全可以修改表单去掉JS校验 。
13.Java WEB容器默认配置漏洞 。
如TOMCAT后台管理漏洞,默认用户名及密码登录后可直接上传war文件获取webshell 。
解决方案:最好删除,如需要使用它来管理维护,可更改其默认路径,口令及密码 。
用java编的程序如何让用户看不到源代码啊如果是web程序就发布,自然看不到
如果是应用程序,打成exe就OK了
怎么样才能写出安全的Java代码?不被黑客攻击?在本文中,我们讨论了对付 13 种不同静态暴露的技巧 。对于每种暴露,我们解释了不处理这些安全性问题所造成的影响 。我们还为您推荐了一些准则,要开发不受这些静态安全性暴露威胁的、健壮且安全的 Java 应用程序 , 您应该遵循这些准则 。一有合适的时机 , 我们就提供代码样本(既有暴露的代码也有无暴露的代码) 。
对付高严重性暴露的技巧
请遵循下列建议以避免高严重性静态安全性暴露:
限制对变量的访问
让每个类和方法都成为 final , 除非有足够的理由不这样做
不要依赖包作用域
使类不可克隆
使类不可序列化
使类不可逆序列化
避免硬编码敏感数据
查找恶意代码
限制对变量的访问
如果将变量声明为 public,那么外部代码就可以操作该变量 。这可能会导致安全性暴露 。
影响
如果实例变量为 public,那么就可以在类实例上直接访问和操作该实例变量 。将实例变量声明为 protected 并不一定能解决这一问题:虽然不可能直接在类实例基础上访问这样的变量,但仍然可以从派生类访问这个变量 。
清单 1 演示了带有 public 变量的代码,因为变量为 public 的,所以它暴露了 。
清单 1. 带有 public 变量的代码
class Test {
public int id;
protected String name;
Test(){
id = 1;
name = "hello world";
}
//code
}
public class MyClass extends Test{
public void methodIllegalSet(String name){
this.name = name; // this should not be allowed
}
public static void main(String[] args){
Test obj = new Test();
obj.id = 123; // this should not be allowed
MyClass mc = new MyClass();
mc.methodIllegalSet("Illegal Set Value");
}
}
建议
一般来说,应该使用取值方法而不是 public 变量 。按照具体问题具体对待的原则,在确定哪些变量特别重要因而应该声明为 private 时,请将编码的方便程度及成本同安全性需要加以比较 。清单 2 演示了以下列方式来使之安全的代码:
清单 2. 不带有 public 变量的代码
class Test {
private int id;
private String name;
Test(){
id = 1;
name = "hello world";
}
public void setId(int id){
this.id = id;
}
public void setName(String name){
this.name = name;
}
public int getId(){
return id;
}
public String getName(){
return name;
}
}
让每个类和方法都为 final
不允许扩展的类和方法应该声明为 final 。这样做防止了系统外的代码扩展类并修改类的行为 。
影响
仅仅将类声明为非 public 并不能防止攻击者扩展类,因为仍然可以从它自己的包内访问该类 。
建议
让每个类和方法都成为 final,除非有足够的理由不这样做 。按此建议 , 我们要求您放弃可扩展性,虽然它是使用诸如 Java 语言之类的面向对象语言的主要优点之一 。在试图提供安全性时,可扩展性却成了您的敌人;可扩展性只会为攻击者提供更多给您带来麻烦的方法 。
不要依赖包作用域
没有显式地标注为 public、private 或 protected 的类、方法和变量在它们自己的包内是可访问的 。
影响
如果 Java 包不是封闭的,那么攻击者就可以向包内引入新类并使用该新类来访问您想保护的内容 。诸如 java.lang 之类的一些包缺省是封闭的,一些 JVM 也让您封闭自己的包 。然而 , 您最好假定包是不封闭的 。
建议
从软件工程观点来看,包作用域具有重要意义,因为它可以阻止对您想隐藏的内容进行偶然的、无意中的访问 。但不要依靠它来获取安全性 。应该将类、方法和变量显式标注为 public、private 或 protected 中适合您特定需求的那种 。
使类不可克隆
克隆允许绕过构造器而轻易地复制类实例 。
影响
即使您没有有意使类可克?。?外部源仍然可以定义您的类的子类,并使该子类实现 java.lang.Cloneable 。这就让攻击者创建了您的类的新实例 。拷贝现有对象的内存映象生成了新的实例;虽然这样做有时候是生成新对象的可接受方法,但是大多数时候是不可接受的 。清单 3 说明了因为可克隆而暴露的代码:
清单 3. 可克隆代码
class MyClass{
private int id;
private String name;
public MyClass(){
id=1;
name="HaryPorter";
}
public MyClass(int id,String name){
this.id=id;
this.name=name;
}
public void display(){
System.out.println("Id =" id "
" "Name=" name);
}
}
// hackers code to clone the user class
public class Hacker extends MyClass implements Cloneable {
public static void main(String[] args){
Hacker hack=new Hacker();
try{
MyClass o=(MyClass)hack.clone();
o.display();
}
catch(CloneNotSupportedException e){
e.printStackTrace();
}
}
}
建议
要防止类被克隆 , 可以将清单 4 中所示的方法添加到您的类中:
清单 4. 使您的代码不可克隆
public final Object clone()
throws java.lang.CloneNotSupportedException{
throw new java.lang.CloneNotSupportedException();
}
如果想让您的类可克隆并且您已经考虑了这一选择的后果,那么您仍然可以保护您的类 。要做到这一点,请在您的类中定义一个为 final 的克隆方法,并让它依赖于您的一个超类中的一个非 final 克隆方法,如清单 5 中所示:
清单 5. 以安全的方式使您的代码可克隆
public final Object clone()
throws java.lang.CloneNotSupportedException {
super.clone();
}
类中出现 clone() 方法防止攻击者重新定义您的 clone 方法 。
使类不可序列化
序列化允许将类实例中的数据保存在外部文件中 。闯入代码可以克隆或复制实例,然后对它进行序列化 。
影响
序列化是令人担忧的 , 因为它允许外部源获取对您的对象的内部状态的控制 。这一外部源可以将您的对象之一序列化成攻击者随后可以读取的字节数组,这使得攻击者可以完全审查您的对象的内部状态,包括您标记为 private 的任何字段 。它也允许攻击者访问您引用的任何对象的内部状态 。
建议
要防止类中的对象被序列化 , 请在类中定义清单 6 中的 writeObject() 方法:
清单 6. 防止对象序列化
private final void writeObject(ObjectOutputStream out)
throws java.io.NotSerializableException {
throw new java.io.NotSerializableException("This object cannot
be serialized");
}
通过将 writeObject() 方法声明为 final,防止了攻击者覆盖该方法 。
使类不可逆序列化
通过使用逆序列化,攻击者可以用外部数据或字节流来实例化类 。
影响
不管类是否可以序列化,都可以对它进行逆序列化 。外部源可以创建逆序列化成类实例的字节序列 。这种可能为您带来了大量风险,因为您不能控制逆序列化对象的状态 。请将逆序列化作为您的对象的另一种公共构造器 — 一种您无法控制的构造器 。
建议
要防止对对象的逆序列化,应该在您的类中定义清单 7 中的 readObject() 方法:
清单 7. 防止对象逆序列化
private final void readObject(ObjectInputStream in)
throws java.io.NotSerializableException {
throw new java.io.NotSerializableException("This object cannot
be deserialized");
}
通过将该方法声明为 final,防止了攻击者覆盖该方法 。
避免硬编码敏感数据
您可能会尝试将诸如加密密钥之类的秘密存放在您的应用程序或库的代码 。对于你们开发人员来说,这样做通常会把事情变得更简单 。
影响
任何运行您的代码的人都可以完全访问以这种方法存储的秘密 。没有什么东西可以防止心怀叵测的程序员或虚拟机窥探您的代码并了解其秘密 。
建议
可以以一种只可被您解密的方式将秘密存储在您代码中 。在这种情形下,秘密只在于您的代码所使用的算法 。这样做没有多大坏处 , 但不要洋洋得意,认为这样做提供了牢固的保护 。您可以遮掩您的源代码或字节码 — 也就是 , 以一种为了解密必须知道加密格式的方法对源代码或字节码进行加密 — 但攻击者极有可能能够推断出加密格式,对遮掩的代码进行逆向工程从而揭露其秘密 。
这一问题的一种可能解决方案是:将敏感数据保存在属性文件中,无论什么时候需要这些数据 , 都可以从该文件读取 。如果数据极其敏感,那么在访问属性文件时,您的应用程序应该使用一些加密/解密技术 。
查找恶意代码
从事某个项目的某个心怀叵测的开发人员可能故意引入易受攻击的代码 , 打算日后利用它 。这样的代码在初始化时可能会启动一个后台进程,该进程可以为闯入者开后门 。它也可以更改一些敏感数据 。
这样的恶意代码有三类:
类中的 main 方法
定义过且未使用的方法
注释中的死代码
影响
入口点程序可能很危险而且有恶意 。通常 , Java 开发人员往往在其类中编写 main() 方法,这有助于测试单个类的功能 。当类从测试转移到生产环境时,带有 main() 方法的类就成为了对应用程序的潜在威胁,因为闯入者将它们用作入口点 。
请检查代码中是否有未使用的方法出现 。这些方法在测试期间将会通过所有的安全检查,因为在代码中不调用它们 — 但它们可能含有硬编码在它们内部的敏感数据(虽然是测试数据) 。引入一小段代码的攻击者随后可能调用这样的方法 。
避免最终应用程序中的死代码(注释内的代码) 。如果闯入者去掉了对这样的代码的注释 , 那么代码可能会影响系统的功能性 。
可以在清单 8 中看到所有三种类型的恶意代码的示例:
清单 8. 潜在恶意的 Java 代码
public void unusedMethod(){
// code written to harm the system
}
public void usedMethod(){
//unusedMethod(); //code in comment put with bad intentions,
//might affect the system if uncommented
// int x = 100;
// x=x 10;//Code in comment, might affect the
//functionality of the system if uncommented
}
建议
应该将(除启动应用程序的 main() 方法之外的)main() 方法、未使用的方法以及死代码从应用程序代码中除去 。在软件交付使用之前,主要开发人员应该对敏感应用程序进行一次全面的代码评审 。应该使用“Stub”或“dummy”类代替 main() 方法以测试应用程序的功能 。
对付中等严重性暴露的技巧
请遵循下列建议以避免中等严重性静态安全性暴露:
不要依赖初始化
不要通过名称来比较类
不要使用内部类
不要依赖初始化
您可以不运行构造器而分配对象 。这些对象使用起来不安全,因为它们不是通过构造器初始化的 。
影响
在初始化时验证对象确保了数据的完整性 。
例如,请想象为客户创建新帐户的 Account 对象 。只有在 Account 期初余额大于 0 时,才可以开设新帐户 。可以在构造器里执行这样的验证 。有些人未执行构造器而创建 Account 对象 , 他可能创建了一个具有一些负值的新帐户 , 这样会使系统不一致,容易受到进一步的干预 。
建议
在使用对象之前,请检查对象的初始化过程 。要做到这一点,每个类都应该有一个在构造器中设置的私有布尔标志 , 如清单 9 中的类所示 。在每个非 static 方法中 , 代码在任何进一步执行之前都应该检查该标志的值 。如果该标志的值为 true,那么控制应该进一步继续;否则,控制应该抛出一个例外并停止执行 。那些从构造器调用的方法将不会检查初始化的变量,因为在调用方法时没有设置标志 。因为这些方法并不检查标志,所以应该将它们声明为 private 以防止用户直接访问它们 。
清单 9. 使用布尔标志以检查初始化过程
public class MyClass{
private boolean initialized = false;
//Other variables
public MyClass (){
//variable initialization
method1();
initialized = true;
}
private void method1(){ //no need to check for initialization variable
//code
}
public void method2(){
try{
if(initialized==true){
//proceed with the business logic
}
else{
throw new Exception("Illegal State Of the object");
}
}catch(Exception e){
e.printStackTrace();
}
}
}
如果对象由逆序列化进行初始化,那么上面讨论的验证机制将难以奏效,因为在该过程中并不调用构造器 。在这种情况下,类应该实现 ObjectInputValidation 接口:
清单 10. 实现 ObjectInputValidation
interface java.io.ObjectInputValidation {
public void validateObject() throws InvalidObjectException;
}
所有验证都应该在 validateObject() 方法中执行 。对象还必须调用 ObjectInputStream.RegisterValidation() 方法以为逆序列化对象之后的验证进行注册 。RegisterValidation() 的第一个参数是实现 validateObject() 的对象,通常是对对象自身的引用 。注:任何实现 validateObject() 的对象都可能充当对象验证器,但对象通常验证它自己对其它对象的引用 。RegisterValidation() 的第二个参数是一个确定回调顺序的整数优先级,优先级数字大的比优先级数字小的先回调 。同一优先级内的回调顺序则不确定 。
当对象已逆序列化时,ObjectInputStream 按照从高到低的优先级顺序调用每个已注册对象上的 validateObject() 。
不要通过名称来比较类
有时候,您可能需要比较两个对象的类,以确定它们是否相同;或者,您可能想看看某个对象是否是某个特定类的实例 。因为 JVM 可能包括多个具有相同名称的类(具有相同名称但却在不同包内的类),所以您不应该根据名称来比较类 。
影响
如果根据名称来比较类,您可能无意中将您不希望授予别人的权利授予了闯入者的类,因为闯入者可以定义与您的类同名的类 。
例如,请假设您想确定某个对象是否是类 com.bar.Foo 的实例 。清单 11 演示了完成这一任务的错误方法:
清单 11. 比较类的错误方法
if(obj.getClass().getName().equals("Foo"))// Wrong!
// objects class is named Foo
}else{
// object's class has some other name
}
建议
在那些非得根据名称来比较类的情况下 , 您必须格外小心 , 必须确保使用了当前类的 ClassLoader 的当前名称空间,如清单 12 中所示:
清单 12. 比较类的更好方法
if(obj.getClass() == this.getClassLoader().loadClass("com.bar.Foo")){
// object's class is equal to
//the class that this class calls "com.bar.Foo"
}else{
// object's class is not equal to the class that
// this class calls "com.bar.Foo"
}
然而,比较类的更好方法是直接比较类对象看它们是否相等 。例如,如果您想确定两个对象 a 和 b 是否属同一个类,那么您就应该使用清单 13 中的代码:
清单 13. 直接比较对象来看它们是否相等
if(a.getClass() == b.getClass()){
// objects have the same class
}else{
// objects have different classes
}
尽可能少用直接名称比较 。
不要使用内部类
Java 字节码没有内部类的概念,因为编译器将内部类转换成了普通类,而如果没有将内部类声明为 private,则同一个包内的任何代码恰好能访问该普通类 。
影响
因为有这一特性,所以包内的恶意代码可以访问这些内部类 。如果内部类能够访问括起外部类的字段,那么情况会变得更糟 。可能已经将这些字段声明为 private,这样内部类就被转换成了独立类,但当内部类访问外部类的字段时,编译器就将这些字段从专用(private)的变为在包(package)的作用域内有效的 。内部类暴露了已经够糟糕的了,但更糟糕的是编译器使您将某些字段成为 private 的举动成为徒劳 。
建议 如果能够不使用内部类就不要使用内部类 。
对付低严重性暴露的技巧
请遵循下列建议以避免低严重性静态安全性暴露:
避免返回可变对象
检查本机方法
避免返回可变对象
Java 方法返回对象引用的副本 。如果实际对象是可改变的,那么使用这样一个引用调用程序可能会改变它的内容,通常这是我们所不希望见到的 。
影响
请考虑这个示例:某个方法返回一个对敏感对象的内部数组的引用,假定该方法的调用程序不改变这些对象 。即使数组对象本身是不可改变的,也可以在数组对象以外操作数组的内容,这种操作将反映在返回该数组的对象中 。如果该方法返回可改变的对象,那么事情会变得更糟;外部实体可以改变在那个类中声明的 public 变量,这种改变将反映在实际对象中 。
清单 14 演示了脆弱性 。getExposedObj() 方法返回了 Exposed 对象的引用副本 , 该对象是可变的:
清单 14. 返回可变对象的引用副本
class Exposed{
private int id;
private String name;
public Exposed(){
}
public Exposed(int id, String name){
this.id = id;
this.name = name;
}
public int getId(){
return id;
}
public String getName(){
return name;
}
public void setId(int id){
this.id=id;
}
public void setName(String name){
this.name = name;
}
public void display(){
System.out.println("Id = "id" Name = "name);
}
}
public class Exp12{
private Exposed exposedObj = new Exposed(1,"Harry Porter");
public Exposed getExposedObj(){
return exposedObj;//returns a reference to the object.
}
public static void main(String[] args){
Exp12 exp12 = new Exp12();
exp12.getExposedObj().display();
Exposed exposed = exp12.getExposedObj();
exposed.setId(10);
exposed.setName("Hacker");
exp12.getExposedObj().display();
}
}
建议
如果方法返回可改变的对象 , 但又不希望调用程序改变该对象,请修改该方法使之不返回实际对象而是返回它的副本或克隆 。要改正清单 14 中的代码,请让它返回 Exposed 对象的副本,如清单 15 中所示:
清单 15. 返回可变对象的副本
public Exposed getExposedObj(){
return new Exposed(exposedObj.getId(),exposedObj.getName());
}
或者 , 您的代码也可以返回 Exposed 对象的克隆 。
检查本机方法
本机方法是一种 Java 方法,其实现是用另一种编程语言编写的,如 C 或 C。有些开发人员实现本机方法 , 这是因为 Java 语言即使使用即时(just-in-time)编译器也比许多编译过的语言要慢 。其它人需要使用本机代码是为了在 JVM 以外实现特定于平台的功能 。
影响
使用本机代码时,请小心,因为对这些代码进行验证是不可能的 , 而且本机代码可能潜在地允许 applet 绕过通常的安全性管理器(Security Manager)和 Java 对设备访问的控制 。
建议
如果非得使用本机方法,那么请检查这些方法以确定:
它们返回什么
它们获取什么作为参数
它们是否绕过安全性检查
它们是否是 public、private 等等
它们是否含有绕过包边界从而绕过包保护的方法调用
结束语
编写安全 Java 代码是十分困难的,但本文描述了一些可行的实践来帮您编写安全 Java 代码 。这些建议并不能解决您的所有安全性问题 , 但它们将减少暴露数目 。最佳软件安全性实践可以帮助确保软件正常运行 。安全至关重要和高可靠系统设计者总是花费大量精力来分析和跟踪软件行为 。只有通过将安全性作为至关紧要的系统特性来对待 — 并且从一开始就将它构建到应用程序中,我们才可以避免亡羊补牢似的、修修补补的安全性方法 。
参考资料
请通过单击文章顶部或底部的讨论来参加本文的论坛 。
了解关于 Java 安全性 API 的更多知识 。
developerWorks 安全专题上通常含有有关计算机安全性的优秀资源 。
Larry Koved、 Anthony J. Nadalin、Don Neal 和 Tim Lawson 合作编写的 “The evolution of Java security”(developerWorks,1998 年)对 Java 语言的安全性模型早期开发进行了深入探讨 。
Sing Li 在他的 Java 安全性系列文章(由两部分组成的)(developerWorks , 2001 年 2 月)中向开发人员显示:尽管社区可能不得不重新考虑 Java 2 中的安全性设计,还是出现了只对开发人员有帮助 , 可以满足他们的需求的一致的进展:
第一部分
第二部分
John Viega、Tom Mutdosch、 Gary McGraw 和 Ed Felten 合著的 “Statically scanning Java code for security vulnerabilities” (IEEE Software,2000 年 9 月)介绍了一种 Java 工具,可以使用该工具来检查您的 Java 代码中的安全性漏洞 。
G. McGraw 和 E. Felten 合作编写的 Securing Java: Getting Down to Business with Mobile Code(John Wiley 和 Sons , 1998 年)深入涵盖了 Java 安全性 。(文档是 PDF 格式的 。)
定期检查 IBM 研究 Java 安全页面以便 IBM 在安全性领域的创新有重要发展时能够跟踪这一创新 。
如果您的 Java 代码运行在 S/390 系统上,那么您将需要查阅 S/390 Java 安全页面以获取额外的信息 。
关于作者
Bijaya Nanda Sahu 是就职于印度 IBM Global Services 的软件工程师 。他从事过各种因特网技术和框架(J2EE、WSBCC、JADE)、 WebSphere 相关技术、UML 和 OOAD 方面的工作 。目前,他从事因特网银行安全性问题方面的工作 , 重点在 WebSphere Application Server 和 Portal Server 上 。可以通过 bijaya.sahu@in.ibm.com 和他联系
怎么防止java代码被看的介绍就聊到这里吧,感谢你花时间阅读本站内容 , 更多关于java如何开启防止抓包、怎么防止java代码被看的信息别忘了在本站进行查找喔 。
推荐阅读
- 安庆手机会议直播价格,手机会议直播软件
- u盘大白菜怎么装系统,u盘大白菜怎么装系统图解
- 什么是区块链一文读懂区块,你知道什么是区块链吗?
- linux红帽命令提示符,linux的红帽认证
- linux光盘开启命令行 linux光盘文件系统
- 小程序如何调用jquery,小程序如何调用数据库
- linux命令行的使用,linux的命令行指的是什么
- 有趣的软件毕业设计,软件毕设题目新颖
- 包含windows系统制造员的词条