実際には、セキュリティ上の問題は、多くのプログラマが簡単に問題を無視するということですが、私たちはあなたのアプリケーションのセキュリティを向上させるために、それに注意を払う必要があります。多くの場合、セキュリティ上の問題を含んで表示され、プログラムは、認証されていないユーザー、ネットワーク接続、および他の信頼できないソースからデータを受け取ることができるデータ検証プログラムを受け取っていない場合、それはセキュリティ上の問題につながる可能性があり、そうではなく、特定のこれは、次のエリアに分けることができます。
- データ検証
- 機密情報
- 暗号化アルゴリズム
- シリアライズとデシリアライズ
- I / O操作
- マルチスレッドセーフで
- フレームワークとコンポーネント
記事では、セキュリティの開発仕様:開発者は、(a)は安全規制の開発を理解する必要があります(と同様に、セキュリティ上の問題を含むソリューションやコードの実装) 、私たちはデータ検証に関するいくつかの安全性の問題を設定し、その後、我々は他の部分の安全性に疑問を続けます分析と解決。
データ検証 - 権限の管理
規則1.10:クライアントの要求に、データの検証を追加、削除、変更するデータをプログラムしないでくださいオーバー自信を持って許可を脱漏決意
縦の不正の脆弱性:権限昇格と呼ばれるが、抜け穴「URLベースのアクセス制御」の設計不良です。Webアプリケーションのみメニューの制御または権限がないので限り、他の管理ページのURLとして、あなたがアクセスしたり制御データを、または他の役割のページを持って、システム特権を達成することができます推測する悪意のあるユーザーにつながる、アクセス制御を行いました。
レベル越権の脆弱性:「データベースのアクセス制御」を活用し、設計の欠陥。要求を受信すると、サーバーは、データが不正なデータ・アクセス孔から得た個人データを操作するために属していると判定されなかったからです。リクエストパラメータが(ユーザがデータを制御することができる)、ユーザID、変換による悪意のある攻撃者ID要求値を得るために、クライアントからサーバーに送信され、それはデータを表示または変更するために属していません。
反例:
@RequestMapping(value = "delete")
public String delete(HttpServletRequest request, @RequestParam long id) throws Exception{
try {
userManage.delete(id);
request.setAttribute("msg","delete user success");
}catch (Exception e){
request.setAttribute("msg","delete user failure");
}
return list(request);
}
@RequestMapping(value = "/delete/{addrId}")
public Object remove(@RequestParam long addrId) {
Map<String,Object> resMap=new HashMap<>();
if(WebUtils.isLogged){
this.addressService.removeUserAddress(addrId);
resMap.put(Constans.RESP_STATUS_CODE_KEY,Constans.RESP_STATUS_CODE_SUCCESS);
resMap.put(Constans.MESSAGE,"remove user address success");
}else {
resMap.put(Constans.RESP_STATUS_CODE_KEY,Constans.RESP_STATUS_CODE_FAIL);
resMap.put(Constans.MESSAGE,"user is not login ,remove user address failure");
}
return resMap;
}
复制代码
正例:垂直越権の脆弱性:該当する機能(推奨フィルタ、統一された権限の検証)を呼び出すためのアクセス許可を持っている、現在のユーザーの身元を確認するために、関数を呼び出す前に、
public void doPost(HttpServletRequest request, HttpServletResponse response)throws ServletException ,IOException{
if(request.getSession(true).getAttribute("manager")==null){
response.sendRedirect("noright.html");
return;
}
UserManagerService userManagerService=new UserManagerService();
request.setCharacterEncoding("utf-8");
response.setCharacterEncoding("utf-8");
String action=request.getParameter("action");
if("add".equals(action)){
String id=request.getParameter("userId");
String name=request.getParameter("userName");
String sex=request.getParameter("userSex");
}
//todo do somethings
}
复制代码
データ検証 - 権限の管理
- フィルタはグローバルなユーザーによって検出されたかどうかは、リソースへのアクセスかどうか、ログオンします。
- データベースに保存されているアクセスルール
- フィルタ設定のweb.xml
パブリッククラスPriviegeFilterはフィルター{@AutowiredプライベートUserManagerService userManagerServiceを実装します。
@Override
public void init(FilterConfig filterConfig) throws ServletException {
List<UserAuthorization> userAuthorizationS=userManagerService.getUserAuthorizationInfo();
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
for(UserAuthorization userAuthorization: userAuthorizationS){
// 从数据库中获取用户授权信息
if(!authen){
throw new RuntimeException("您无权访问页面,请以合适身份登陆后查看");
}
filterChain.doFilter(servletRequest,servletResponse);
}
}
@Override
public void destroy() {
}
}
复制代码
データ検証 - 権限の管理
-
SpringMVC:春のセキュリティは、「URLベースのアクセス制御」を提供し、「のベースのアクセス制御方式。」
-
ユーザがセッションからユーザIDを取得する操作を行うと、ユーザに渡されるパラメータの識別は、結合チェックを行います。
<sec:http> <sec:intercept-url parttern="/persident_portal/*" access="RILE_PERSIDENT"/> <sec:intercept-url parttern="/manager_portal/*" access="RILE_MANAGER"/> <sec:intercept-url parttern="/**" access="RILE_USER"/> <sec:form-login /> <sec:logout /> </sec:http> 复制代码
データチェック - 安全でないネットワーク伝送
httpプロトコルはクリアテキスト転送プロトコル、相互作用およびデータ転送は、通信当事者も任意の認証を暗号化されていないが、通信プロセスでも、改ざん、重症例では、悪意のあるトラフィックの乗っ取りやその他の問題を引き起こす可能性がハイジャック、監視、に非常に脆弱ですおよびその他の深刻なセキュリティ上の問題(例えばクレジットカードの番号やパスワードの漏洩など)個人のプライバシーの開示になります。
HTTPに基づくHTTPS追加SSLプロトコルは、SSLサーバの身元を確認し、ブラウザとサーバ間の通信を暗号化するために、証明書に依存しています。
対称暗号化****
非対称暗号化
HTTPSプロトコル(HTTP + SSLプロトコル)、その接続プロセスを以下に示します:
中間者攻撃デジタル証明書:中間者攻撃を解きます
デジタル証明書は、認証局のデジタルクライアントファイルによって署名された後、公開鍵と証明書を取得するには、公開鍵の所有者情報、法に基づいて証明書が含まれている場合は、第三者に自分の秘密鍵で証明書番号を生成し、証明書と自身が生成した証明書の数に同じ証明書番号は、その証明書が本物であること。同時に、自身がパケットを転送された証明書番号、その暗号化を避けるためです。
要約したもので
、クライアントとサーバー側のセキュリティを保証し、使用する必要があります対称暗号化アルゴリズムが、協議プロセス対称暗号化アルゴリズムを作るための通信処理HTTPSを、しかし、直接の非対称暗号化プロセス自体を確保するために、非対称暗号化アルゴリズムを使用する必要があります不安は、証明書を確実にするために、公開鍵仲介の改ざんので、クライアントとサーバが直接公開鍵を使用していない可能性が、自分自身の安全を確保するために、非対称暗号化プロセスによって発行された証明機関(CA)によって発行されたデジタル証明書を使用することがあるでしょうデジタル署名の導入は、クライアントが証明書の信頼性を確認するために同じ対称暗号化アルゴリズムを使用して、改ざん、およびので、最終的には、クライアントとサーバ間の通信のセキュリティ問題を解決されていません。
データチェック - 安全でないネットワーク伝送
規則1.11:暗号化された伝送を使用して、信頼ドメイン間で署名の間で機密性の高いデータ転送
盗難や改ざんを防ぐために、機密性の高いデータ転送プロセス。データ転送オブジェクトを保護するために、安全な暗号化アルゴリズムを使用します。これは、オブジェクトが封入されていると呼ばれています。シールされたオブジェクトがデジタル署名されている間、オブジェクトは、の完全性は残って不正改竄を防止することができます
public static void main(String[] args) throwsIOException,ClassNotFoundException{
// Build map
SerializableMap<String, Integer> map = buildMap();
// Serialize map
ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("data"));
out.writeObject(map);
out.close();
// Deserialize map
ObjectInputStream in = new ObjectInputStream(new FileInputStream("data"));
map = (SerializableMap<String, Integer>) in.readObject();
in.close();
// Inspect map
InspectMap(map);
}
复制代码
反例:
public static void main(String[] args) throwsIOException,GeneralSecurityException, ClassNotFoundException{
// Build map
SerializableMap<String, Integer> map = buildMap();
// Generate sealing key & seal map
KeyGenerator generator = KeyGenerator.getInstance("AES");
generator.init(newSecureRandom());
Key key= generator.generateKey();
Cipher cipher= Cipher.getInstance("AES");
cipher.init(Cipher.ENCRYPT_MODE, key);
SealedObject sealedMap= new SealedObject(map, cipher);
// Serialize map
ObjectOutputStreamout = new ObjectOutputStream(newFileOutputStream("data"));
out.writeObject(sealedMap);
out.close();
// Deserialize map
ObjectInputStream in = newObjectInputStream(newFileInputStream("data"));
sealedMap= (SealedObject) in.readObject();
in.close();
// Unseal map
cipher = Cipher.getInstance("AES");
cipher.init(Cipher.DECRYPT_MODE, key);
map = (SerializableMap<String, Integer>) sealedMap.getObject(cipher);
// Inspect map
InspectMap(map);
}
public static void main(String[] args) throwsIOException, GeneralSecurityException, ClassNotFoundException{
SerializableMap<String, Integer> map = buildMap();
KeyGenerator generator = KeyGenerator.getInstance("AES");
generator.init(newSecureRandom());
Key key= generator.generateKey();
Cipher cipher= Cipher.getInstance("AES");
cipher.init(Cipher.ENCRYPT_MODE, key);
SealedObjectsealedMap= newSealedObject(map, cipher);
KeyPairGeneratorkpg= KeyPairGenerator.getInstance("RSA");
KeyPair kp= kpg.generateKeyPair();
Signature sig = Signature.getInstance("SHA256withRSA");
SignedObject signedMap= newSignedObject(sealedMap, kp.getPrivate(), sig);
ObjectOutputStreamout = newObjectOutputStream(newFileOutputStream("data"));
out.writeObject(signedMap);
out.close();
ObjectInputStream in = newObjectInputStream(newFileInputStream("data"));
signedMap= (SignedObject)
in.readObject();
in.close();
if(!signedMap.verify(kp.getPublic(), sig)){
throw new GeneralSecurityException("Map failed verification");
}
sealedMap= (SealedObject) signedMap.getObject();
cipher = Cipher.getInstance("AES");
cipher.init(Cipher.DECRYPT_MODE, key);
map = (SerializableMap<String, Integer>) sealedMap.getObject(cipher);
InspectMap(map);
}
复制代码
正例:
public static void main(String[] args) throws IOException, GeneralSecurityException, ClassNotFoundException{
SerializableMap<String, Integer> map = buildMap();
KeyPairGenerator kpg= KeyPairGenerator.getInstance("RSA");
KeyPair kp= kpg.generateKeyPair();
Signature sig = Signature.getInstance("SHA256withRSA");
SignedObject signedMap= new SignedObject(map, kp.getPrivate(), sig);
KeyGenerator generator = KeyGenerator.getInstance("AES");
generator.init(new SecureRandom());
Key key= generator.generateKey();
Cipher cipher= Cipher.getInstance("AES");
cipher.init(Cipher.ENCRYPT_MODE, key);
SealedObject sealedMap = new SealedObject(signedMap, cipher);
ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("data"));
out.writeObject(sealedMap);
out.close();
// Deserialize map
ObjectInputStream in = new ObjectInputStream(new FileInputStream("data"));
sealedMap= (SealedObject) in.readObject();
in.close();
// Unseal map
cipher = Cipher.getInstance("AES");
cipher.init(Cipher.DECRYPT_MODE, key);
signedMap= (SignedObject) sealedMap.getObject(cipher);
// Verify signature and retrieve map
if(!signedMap.verify(kp.getPublic(), sig)){
throw new GeneralSecurityException("Map failed verification");
}
map = (SerializableMap<String, Integer>) signedMap.getObject();
// Inspect map
InspectMap(map);
}
复制代码
機密情報
機密情報 - 共通の機密情報
規則2.1:明示的に保存ユーザーは、ログ内の機密データを禁止します
そのようなプレーンテキスト、容易な操作および保守要員などの機密データが格納されている攻撃者のユーザログは、漏れまたはシステムを破壊します
2.2ルール:プログラムにハードコードされた機密情報を禁止
(パスワードや暗号化キーを含む)機密情報がプログラムにハードコードされている場合、攻撃者に機密情報を暴露することがあります。クラスファイルへのアクセス権を持つユーザーは、クラスファイルを逆コンパイルし、これらの機密情報ことを見つけることができます
...
DriverManager.getConnection(url,"soctt","tiger")
...
复制代码
Javaの逆コンパイラ
てjavap C Connmngr.class
LDC#36://文字列はjdbc:mysqlの://ixne.com/rxsql
//文字列スコット:LDC#38
#17 LDC://文字列の虎
反例:
public class IPaddress{
private String ipAddress= "172.16.254.1";
public static voidmain(String[] args){
//...
}
}
复制代码
正例:
public class IPaddress{
public static void main(String[] args) throws IOException{
char[] ipAddress= new char[100];
BufferedReader br= new BufferedReader(newInputStreamReader(newFileInputStream("serveripaddress.txt")));
// Reads the server IP address into the char array,
// returns the number of bytes read
intn = br.read(ipAddress);
// Validate server IP address
// Manually clear out the server IP address
// immediately after use
for(inti= n -1; i>= 0; i--){
ipAddress[i] = 0;
}
br.close();
}
}
复制代码
規則2.3:メッセージの暗号化伝送-ネットワークスニファにユーザーデータに攻撃者がメッセージ転送を送信するときに、セキュリティプロトコルのSSL / TLS暗号化を使用しないようにする必要が反例:TLSプロトコルメッセージの転送を使用していません
public class SendMailTLS{
public static void main(String[] args) {
final String username="[email protected]";
final String password="password";
Properties props=new Properties();
//使用TLS
//props.put("mail.smtp.auth","true");
//props.put("mail.smtp.startls.enable","true");
//使用SSL
//props.put("mail.smtp.socketFactory,port","465");
//props.put("mail.smtp.socketFactory.class","javax.net.ssl.SSLSocketFactory");
//props.put("mail.smtp.auth","true");
props.put("mail.smtp.host","smtp.gmail.com");
props.put("mail.smtp.port","587");
Session session=Session.getInstance(props,new javax.mail.Authenticator){
protected PasswordAuthentication getPasswordAuthentication(){
return new PasswordAuthentication(username,password);
}
});
}
}
复制代码
正例:TLSプロトコルを使用して暗号化
public class SendMailTLS{
public static void main(String[] args) {
final String username="[email protected]";
final String password="password";
Properties props=new Properties();
//使用TLS
props.put("mail.smtp.auth","true");
props.put("mail.smtp.startls.enable","true");
//做服务器证书校验
props.put("mail.smtp.ssl.checkserveridentity","true");
//添加信任的服务器地址,多个地址之间用空格分开
props.put("mail.smtp.ssl.trust","smtp.gmail.com");
props.put("mail.smtp.host","smtp.gmail.com");
props.put("mail.smtp.port","25");
Session session=Session.getInstance(props,new javax.mail.Authenticator){
protected PasswordAuthentication getPasswordAuthentication(){
return new PasswordAuthentication(username,password);
}
});
}
}
复制代码
規則2.4:保存されたパスワードハッシュアルゴリズムに基づいて、標準的な反復PBKDF2を塩(塩)、および使用する必要があります
塩がなければ、同じハッシュ値を取得するために同じパスワードを引き起こす可能性があります
public class PasswordHash{
public static final String PBKDF2_ALGORITHM="PBKDF2WithHmacSHA1";
public static final int SALT_BYTE_SIZE=24;
public static final int HASH_BYTE_SIZE=24;
public static final int PBKDF2_ITERATIONS=1000;
public static String createHash(char[] password)
throws NoSuchAlgorithmException,InvalidKeySpecException{
//Generate a random salt
SecureRandom random =new SecureRandom();
byte[] salt =new btye[SALT_BYTE_SIZE];
random.nextBytes(salt);
// Hash the password
byte[] hash =pbkdf2(password,salt,PBKDF2_ITERATIONS,HASH_BYTE_SIZE);
//format iterations:salt:hash
return PBKDF2_ITERATIONS+":"+toHex(hash);
}
}
复制代码
暗号化アルゴリズム
暗号化アルゴリズム - 暗号化アルゴリズムの概要
3.1安全でない暗号化アルゴリズムをルール - 安全でない暗号化アルゴリズムDES \ 3DESの使用を禁止
暗号化アルゴリズムはAESの攻撃者は、機密情報へのアクセスを暗号化アルゴリズムの不安をクラックすることができ、安全な暗号化アルゴリズムを使用する必要があります
カウンター例:安全でないDESアルゴリズムを使用して、
byte[] result = DES.encrypt(str.getBytes(),password);
//直接将如上内容解密
try{
byte[] decryResult =DES.decrypt(result,password);
System.out.println("解密后:"+new String(decryResult));
}catch(Excption e1){
e1.printStackTrace();
}
复制代码
3.3ルール:対称暗号化アルゴリズムはAES-ECB AESだけではなく、推奨危険なパケットモードの使用を禁止暗号化を提供し、また整合性AES-GCMをチェックを提供
また、AESブロック暗号方式:AES-CBC \ AES-CFB \ AES-OFB \ AES-CTR(AES-CTRエネルギー計算するので、最も効率的な)
反例:危険なECBにAESを使用してパケットモード
pubilc class AES{
//加密
public static String Encrypt(String sSrc,String sKey) throws Excetion{
if(sKey==null){
System.out.print("key为空null");
return null;
}
//判断key是否为16位
if(key.length()!=16){
System.out.print("key长度不是16位");
return null;
}
byte[] raw =sKey.getBytes("UTF-8");
SecreKeySpec skeySpec=new SecreKeySpec(raw,"AES");
Cipher cipher=Cipher.getInstance("AES/ECB/PKCS5Padding");//算法/模式/补码方式
cipher.init(Cipher.ENCRYPT_MODE,skeySpec);
byte[] encrypted= cipher.doFinal(sScr.getByte("utf-8"));
return new Base64().encodeToString(encrypted);//此处使用Base64做转码功能,同时能起到2次加密作用
}
}
复制代码
正例:CBCモードパケットのセキュリティ・アルゴリズムにAESを使用して
pubilc class AES{
//加密
public static String Encrypt(String sSrc,String sKey) throws Excetion{
if(sKey==null){
System.out.print("key为空null");
return null;
}
//判断key是否为16位
if(key.length()!=16){
System.out.print("key长度不是16位");
return null;
}
byte[] raw =sKey.getBytes("UTF-8");
SecreKeySpec skeySpec=new SecreKeySpec(raw,"AES");
Cipher cipher=Cipher.getInstance("AES/ECB/PKCS5Padding");//算法/模式/补码方式
IvParameterSpec iv =new IvParameterSpec(sKey.getByte());//使用CBC模式,需要一个向量iv
//可增加加密算法的强度
cipher.init(Cipher.ENCRYPT_MODE,skeySpec,iv);
byte[] encrypted= cipher.doFinal(sScr.getByte("utf-8"));
return new Base64().encodeToString(encrypted);//此处使用Base64做转码功能,同时能起到2次加密作用
}
}
复制代码
規則3.4:非対称暗号化アルゴリズムRSA非対称暗号化アルゴリズムを使用してRSA-は、少なくとも2048の長さに注意が必要です
RSAキーの長さが2048未満である、安全基準を満たしていないだけで1024のRSAアルゴリズムキーの長さ:反例を
public static HashMap<String,Object>getKeys()throws NoSuchAlgorithmException{
HashMap<String,Object> map=new HashMap<String,Object>;
KeyPairGenerator keyPairGen=KeyPairGenerator.getInstance("RSA");
keyPairGen.initialize(1024);
KeyPair keyPair=keyPairGen.generateKeyPair();
RSAPublicKey pubilcKey=(RSAPublicKey) keyPair.getPublic();
RSAPrivateKey privateKey =(RSAPrivateKey) keyPair.getPrivate();
map.put("public",pubilcKey);
map.put("private",privateKey);
return map;
}
复制代码
正例:少なくとも2048年のRSAアルゴリズムのキーの長さ
public static HashMap<String,Object>getKeys()throws NoSuchAlgorithmException{
HashMap<String,Object> map=new HashMap<String,Object>;
KeyPairGenerator keyPairGen=KeyPairGenerator.getInstance("RSA");
keyPairGen.initialize(2048);
KeyPair keyPair=keyPairGen.generateKeyPair();
RSAPublicKey pubilcKey=(RSAPublicKey) keyPair.getPublic();
RSAPrivateKey privateKey =(RSAPrivateKey) keyPair.getPrivate();
map.put("public",pubilcKey);
map.put("private",privateKey);
return map;
}
复制代码
規則3.5:強力な乱数を使用して機密データを暗号化
擬似乱数生成器攻撃者がシステムのセキュリティの脆弱性の数を監視することができ、携帯性及び再現性を有し、そして機密データが予測に関連するように、予測するために使用され、対応するルックアップテーブルのシードを構成する
擬似乱数例:
import java.util.Random;
public class RandomDemo{
Random random1=new Random(100);
System.out.println(random1.nextInt());
System.out.println(random1.nextFloat());
System.out.println(random1.nextBoolean());
Random random2=new Random(100);
System.out.println(random2.nextInt());
System.out.println(random2.nextFloat());
System.out.println(random2.nextBoolean());
}
import java.io.UnsupporedEncodeingException;
import java.util.Random;
public class SecureRandom{
public static void main(String[] args)throws UnsupporedEncodeingException{
Random ranGen=new Random();
byte[] aesKey=new byte[20];
ranKey.nextBytes(aesKey);
StringBuffer hexString =new StringBuffer();
for (int i=0;i<aesKey.length;i++){
String hex=Integer.toHexString(0xff&aesKey[i]);
if(hex.length()==1)
hexString.append(''0);
hexString.append(hex);
}
System.out.println(hexString);
}
}
复制代码
強力な乱数例:
import java.io.UnsupporedEncodeingException;
import java.util.Random;
import java.security.SecureRandom;
public class SecureRandom{
public static void main(String[] args)throws UnsupporedEncodeingException{
Random ranGen=new SecureRandom();
byte[] aesKey=new byte[20];
ranKey.nextBytes(aesKey);
StringBuffer hexString =new StringBuffer();
for (int i=0;i<aesKey.length;i++){
String hex=Integer.toHexString(0xff&aesKey[i]);
if(hex.length()==1)
hexString.append(''0);
hexString.append(hex);
}
System.out.println(hexString);
}
}
复制代码
シリアライズとデシリアライズ
-
Javaのシリアライゼーションは、メモリ、ファイル、データベース、のwriteObject ObjectOutputStreamのクラス()メソッドを実装することができるシリアライゼーション内のバイトの処理手順を容易にするために、Javaオブジェクトを変換するための手段。
-
デシリアライズJavaバイトシーケンスは、Javaオブジェクトの回収プロセスを指し、readObjectメソッドObjectInputStreamのクラス()メソッドは、デシリアライゼーションが使用されます。
public class Test{ public static void main(String[] args) throws Exception{ //定义myObj对象 MyObject myObj=new MyObject(); //创建一个包含对象进行反序列化信息的“object”数据文件 FileOutputStream fos=new FileOutputStream("object"); ObjectOutputStream os =new ObjectOutputStream(fos); //writeObject()方法将myObj对象写入objct文件中 os.writeObject(myObj); os.close(); //从文件中反序列化obj对象 FileInputStream fis=new FileInputStream("object"); ObjectInputStream ois =new ObjectInputStream(fis); //恢复对象 MyObject objectFromDisk=(MyObject)ois.readObject(); System.out.println(objectFromDisk.name); ois.close; } } class MyObject implements Serializable{ public String name; //重写readObject()方法 private void readObject(java.io.ObjectInputStream in) throws IOExeption{ //执行默认的readObject()方法 in.defaultReadObject(); //执行打开计算器程序命令 Runtime.getRuntime().exec("open /Application/Calcultor.app") } } 复制代码
シリアライズとデシリアライズ - デシリアライゼーションの脆弱性
ObjectInputStreamのクラスデシリアライズ、制限がないの結果の型のオブジェクト
アンチ例:危険なデシリアライズ、任意のコマンドの実行、管理サーバ
ServerSocket serverSocket =new ServerSocket(Integer,parseInt("9999"));
while(true){
Socket socket=serverSocket.accpet();
ObjectInputStream objectInputStream=new ObjectInputStream(socket.getInputStream());
try{
Object object=objectInputStream.readObject();
}catch(Exception e){
e.printStackTrace();
}
}
复制代码
規則4.1:生成されたオブジェクトの種類のクラスObjectInputStreamの直列化復元メイク制限
public final class SecureObjectInputStram extends ObjectInputStream{
public SecureObjectInputStram() throws IOException{
super();
}
public SecureObjectInputStram( InputStream in) throws IOException{
super(in);
}
portected Class<?>resolveClass(ObjectStreamClass desc) throws ClassNotFoundException,IOException{
if(!desc.getName().equals("java.security.Person")){
throws new ClassNotFoundException(desc.getName()+"not found");
}
return super.resolveClass(desc);
}
}
复制代码
シリアライズとデシリアライズ - 直列化復元危険な脆弱性ソリューション
ソリューション:
- 業界のための安全なデシリアライゼーションのプラグを使用してプラグインとパッチを更新するために、逆シリアル化の脆弱性を破りました。
- データ伝送は、データが改ざんされていないことを確認するために、暗号化、およびバックグラウンドでデータ検証されなければなりません。
- カスタムのObjectInputStream、クラス名のホワイトリストをチェックするための過負荷resolveClassメソッド。
- Java9は、メソッドcheckInputのカスタムフィルタを実装継承したクラスjava.io.ObjectInputFilterを上書きすることができます。
- JVMの禁止を達成するためのSecurityManagerを拡張することによってRuntime.execの外部コマンドを実行します。
I / O操作
ルール5.1:ファイルのアップロードは、ビジネスのファイル形式やニーズの大きさに応じて制限する必要があります
アンチ例:未定義のフォーマット
@RequestMapping(value="/upload",method=RequestMethod.POST)
public String upload(HttpServletRequest request, @RequestParam("description") String description,
@RequestParam("file") MultipartFile file)throws Exception{
if(!file.isEmpty()){
String path=request.getServletContext().getRealPath("/images/");
//上传文件名
String filename=file.getOriginalFilename();
File filepath=new File(path,filename);
//判断路径是否存在,如果不存在就创建一个
if(!filepath.getParentFile().exists()){
filepath.getParentFile.mkdirs();
}
//将文件上传保存到一个目标文件中
file.transferTo(new File(path+File.separator+filename));
return "success"
}else{
return "error";
}
}
复制代码
正例:定義されてアップロードされたファイル形式
@RequestMapping(value="/upload",method=RequestMethod.POST)
public String upload(HttpServletRequest request, @RequestParam("description") String description,
@RequestParam("file") MultipartFile file)throws Exception{
if(!file.isEmpty()){
String path=request.getServletContext().getRealPath("/images/");
//上传文件名
String filename=file.getOriginalFilename();
//还有一种方式filenameUtils.getExtension();
String suffix=filename.substring(filename.lastIndexOf(".")+1)
if(suffix!="jpg"){
File filepath=new File(path,filename);
//判断路径是否存在,如果不存在就创建一个
if(!filepath.getParentFile().exists()){
filepath.getParentFile.mkdirs();
}
//将文件上传保存到一个目标文件中
file.transferTo(new File(path+File.separator+filename));
}
return "success" ;
}else{
return "error";
}
}
复制代码
規則5.2:パストラバーサル - 、ファイルをダウンロードしたファイルに対処するためのパスを確認したり、ファイルのダウンロードファイルにIDマッピングファイルを使用する場所
反例:
protected void doGet(HttpServletRequest request,HttpServeltResponse response)
throws ServeltExceptio,IOException{
//获取项目部署绝对路径下的upload文件夹路径,下载upload目录下的文件
String root =request.getServeltContext().getRealPath("/upload");
//获取文件名
String filename=request.getParameter("filename");
//根据文件路径创建输入流
File file=new File(root+"/"+filename);
FileInputStream fis= new FileInputStream(file);
//设置响应头
response.addHeader("Content-Disposition","attachment;filename="+new String(filename.getBytes()));
response.addHeader("Content-Length",""+file.length());
byte[] b =new byte[fis.availabe()];
fis.read(b);
response.getOutStream().write(b);
}
复制代码
正例:ファイル名を確認するホワイトリストを使用します
protected void doGet(HttpServletRequest request,HttpServeltResponse response)
throws ServeltExceptio,IOException{
//获取项目部署绝对路径下的upload文件夹路径,下载upload目录下的文件
String root =request.getServeltContext().getRealPath("/upload");
//获取文件名
String filename=request.getParameter("filename");
if(filename==FILENAME){
//根据文件路径创建输入流
File file=new File(root+"/"+filename);
FileInputStream fis= new FileInputStream(file);
//设置响应头
response.addHeader("Content-Disposition","attachment;filename="+new String(filename.getBytes()));
response.addHeader("Content-Length",""+file.length());
byte[] b =new byte[fis.availabe()];
fis.read(b);
response.getOutStream().write(b);
}
}
复制代码
規則5.3:未発表ストリームリソースは、リソースを解放するためのイニシアチブ(未発表のリソースは、そのようなストリームファイルの使用として、IOは、データベース接続などのストリーム)
自動的に解放されていないリソースファイルを使用する場合は、IOストリーム、データベース接続などが、それはすぐにキャッチ...試みるべきリソースコードを閉じ、使用後にオフになりません...最後に{場合(FOS!= NULL) {fos.closeは();}}最後に内で行われます
private static void TestCloseFileStream(){
String fileName="";
//声明引用
InputStream inputStream=null;
try{
inputStream=new FileInputStream(filename);
}catch(IOException e){
//do something
}finally{
if(inputStream!=null){
try{
//关闭流
inputStream.close();
}catch(IOException e){
//do something
}
}
}
}
复制代码
規則5.4:一時ファイルは、使用後に削除する必要があります
反例:
public class TempFile{
public static void main(STring[] args) throws IOExcption{
File f =new File("tempnam.tmp");
if(f.exists()){
System.out.println("This file already exists");
return;
}
FileOutputStream fop=null;
try{
fop=new FileOutputStream(f);
String str="Data";
fop.write(str.getBytes());
}finally{
if(fop!=null){
try{
fop.close();
}catch(IOException e){
// handle error
}
}
}
}
}
复制代码
正例:
public class TempFile{
public static void main(STring[] args) throws IOExcption{
File f =new File("tempnam.tmp");
if(f.exists()){
System.out.println("This file already exists");
return;
}
FileOutputStream fop=null;
try{
fop=new FileOutputStream(f);
String str="Data";
fop.write(str.getBytes());
}finally{
if(fop!=null){
try{
fop.close();
}catch(IOException e){
// handle error
}
//delete file when finished
if(!f.delete()){
//log the error
}
}
}
}
}
复制代码
マルチスレッド・セーフ(ダブルチェックロック)
規則6.1:生成されたデッドロック、マルチスレッド操作を防ぐために、マルチスレッドのロック機構を使用します
ダブルロック機構(危険なマルチスレッド)
public class Singleton{
private static Singleton singleton;
private Singleton(){}
public static Singleton getSingleton(){
if(singleton==null){
synchronized (Singleton.class){
if(singleton==null){
singleton=new Singleton();
}
}
}
return singleton;
}
}
singleton = new Singleton()非原子性
1. memory=allocate();//1:分配对象的内存空间
2. ctorInstance(memory);//2:初始化对象
3. singleton=memory;//3:设置instance指向刚分配的内存地址
指令重排后:
1. memory=allocate();//1:分配对象的内存空间
2. singleton=memory;//3:设置instance指向刚分配的内存地址//注意,此时对象还没有被初始化!
3. ctorInstance(memory);//2:初始化对象
复制代码
マルチスレッドセーフ(ダブルチェックロック)
キーワードsynchronizedメソッドを使用して
public class Singleton{
private static Singleton singleton;
private Singleton(){}
public static synchronized Singleton getSingleton(){
if(singleton==null){
singleton=new Singleton();
}
return singleton;
}
}
复制代码
初期化の進行
public class Singleton{
private static class SingletonHolder{
private static final Singleton singleton=new Singleton();
}
private Singleton(){}
public static final Singleton getSingleton(){
return SingletonHolder.INSTANCE;
}
}
复制代码
フレームワークとコンポーネント - フレームとコンポーネントのセキュリティ
規則7.1:フレームワークとコンポーネントの安全なバージョンを使用するには、開示の抜け穴があるかどうかでフレームや部品、最初の行のサーチ掃引を使用して、公式をダウンロード
たとえば、次のように--WebLogic、Struts2の、nginxの--Fastjson、ImageMagickに、Log4jの
規則7.2:原因不明のフレームまたはコンポーネントを使用しないでください。
規則7.3:アップデートフレームワークとコンポーネントのバージョン
異常行動 - 外部に露出して異常情報
規則8.1:例外情報が禁止されているフロントにさらさ
try{
FileInputStream fis =new FileInputStream(System.getenv("APPDATA")+args[0]);
}catch(FileNotFoundException e){
//Log the exception
throws new IOException ("Unable to retrieve file",e);
}
复制代码
分析:異常情報が外部に漏洩していない、固定されたエラーを生成します
最後に、国民は動画受け取るために、毎日を学ぶだけでなく、ドライ貨物のシェア、一緒に学び、数字を心配かもしれません!