1.測試工具通過隨機或是半隨機的方式生成大量數據。2.測試工具將生成的數據發送給被測試的系統(輸入)。3.測試工具檢測被測系統的狀態(如是否能夠響應,響應是否正確等)。4.根據被測系統的狀態判斷是否存在潛在的安全漏洞。
模糊測試(Fuzzing),是一種通過向目標系統提供非預期的輸入并監視異常結果來發現軟件漏洞的方法。我個人理解,這是一種隨機或伴隨機的測試方法,與Monkey等隨機測試工具有異曲同工之妙,只是其關注點不同。
模糊測試的執行過程:
1.測試工具通過隨機或是半隨機的方式生成大量數據。
2.測試工具將生成的數據發送給被測試的系統(輸入)。
3.測試工具檢測被測系統的狀態(如是否能夠響應,響應是否正確等)。
4.根據被測系統的狀態判斷是否存在潛在的安全漏洞。
模糊測試工具IntentFuzzer
介紹一種模糊測試工具,IntentFuzzer。
主界面
應用列表
測試組件列表
簡介
這個工具是針對Intent的Fuzzer。它通常可以發現能夠導致系統崩潰的bug,部分安全漏洞,以及設備、應用程序或者是定制平臺的運行中的問題。該工具能夠針對一個簡單組件或者是所有安裝組件進行fuzz測試。它也適用于BroadcastReceiver,但針對Service只有較少的覆蓋,Service通常更加廣泛地應用Binder接口而不是針對IPC的Intent。原版的工具只能針對一個Activity進行fuzz測試,一次不能針對所有的Activity進行測試。另外,也能應用這個接口來啟動Instrumentation,雖然列出了ContentProvider,但是它們不是一個基于Intent的IPC機制,因此并不能應用該工具進行fuzz測試。MindMac在此基礎上進行了一些修改,使其能夠針對一個應用的一個簡單組件或者是所有組件進行fuzz測試,同時具有區分系統應用和非系統應用的能力。MindMac修改后的版本僅針對Activity、BroadcastReceiver、Service。
原理
列舉出系統上所有公開的、能夠從應用獲取到的Activity、BroadcastReceiver、Service、Instrumentation、ContentProvider。工具將通過Intent嘗試啟動所有可以獲取到的組件,從而觸發某些難以發掘的漏洞。觸發一般有兩類漏洞,一類是拒絕服務,一類的權限提升。拒絕服務危害性比較低,更多的只是影響應用服務質量;而權限提升將使得沒有該權限的應用可以通過Intent觸發擁有該權限的應用,從而幫助其完成越權行為。如果該工具能夠輕易從外部啟動特定應用的內部組件,尤其是有較高權限的組件時,很可能在此處發現漏洞。
功能
對某個組件或某個應用的某類組件發起Fuzz,分為Null Fuzz和Serialize
代碼
獲取所有應用及其組件
public static List<AppInfo> getPackageInfo(Context context, int type){
List<AppInfo> pkgInfoList = new ArrayList<AppInfo>();
List<PackageInfo> packages = context.getPackageManager().getInstalledPackages(
PackageManager.GET_ACTIVITIES
| PackageManager.GET_RECEIVERS
| PackageManager.GET_INSTRUMENTATION
| PackageManager.GET_SERVICES);
for(int i=0;i<packages.size();i++) {
PackageInfo packageInfo = packages.get(i);
if (type == SYSTEM_APPS) {
if((packageInfo.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) == 1) {
pkgInfoList.add(fillAppInfo(packageInfo, context));
}
}else if(type == NONSYSTEM_APPS){
if((packageInfo.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) == 0) {
pkgInfoList.add(fillAppInfo(packageInfo, context));
}
}else {
pkgInfoList.add(fillAppInfo(packageInfo, context));
}
}
構建Intent
private void initView(){
typeSpinner = (Spinner) findViewById(R.id.type_select);
cmpListView = (ListView) findViewById(R.id.cmp_listview);
fuzzAllNullBtn = (Button) findViewById(R.id.fuzz_all_null);
fuzzAllSeBtn = (Button) findViewById(R.id.fuzz_all_se);
cmpListView.setOnItemClickListener(new OnItemClickListener(){
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
ComponentName toSend = null;
Intent intent = new Intent();
String className = cmpAdapter.getItem(position).toString();
for (ComponentName cmpName : components) {
if (cmpName.getClassName().equals(className)) {
toSend = cmpName;
break;
}
}
intent.setComponent(toSend);
if (sendIntentByType(intent, currentType)) {
Toast.makeText(FuzzerActivity.this, "Sent Null " + intent, Toast.LENGTH_LONG).show();
} else {
Toast.makeText(FuzzerActivity.this, "Send " + intent + " Failed!", Toast.LENGTH_LONG).show();
}
}
});
cmpListView.setOnItemLongClickListener(new OnItemLongClickListener(){
@Override
public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
ComponentName toSend = null;
Intent intent = new Intent();
String className = cmpAdapter.getItem(position).toString();
for (ComponentName cmpName : components) {
if (cmpName.getClassName().equals(className)) {
toSend = cmpName;
break;
}
}
intent.setComponent(toSend);
intent.putExtra("test", new SerializableTest());
if (sendIntentByType(intent, currentType)) {
Toast.makeText(FuzzerActivity.this, "Sent Serializeable " + intent, Toast.LENGTH_LONG).show();
} else {
Toast.makeText(FuzzerActivity.this, "Send " + intent + " Failed!", Toast.LENGTH_LONG).show();
}
return true;
}
});
fuzzAllNullBtn.setOnClickListener(new OnClickListener(){
@Override
public void onClick(View v) {
for(ComponentName cmpName : components){
Intent intent = new Intent();
intent.setComponent(cmpName);
if (sendIntentByType(intent, currentType)) {
Toast.makeText(FuzzerActivity.this, "Sent Null " + intent, Toast.LENGTH_LONG).show();
} else {
Toast.makeText(FuzzerActivity.this, R.string.send_faild, Toast.LENGTH_LONG).show();
}
}
}
});
fuzzAllSeBtn.setOnClickListener(new OnClickListener(){
@Override
public void onClick(View v) {
for(ComponentName cmpName : components){
Intent intent = new Intent();
intent.setComponent(cmpName);
intent.putExtra("test", new SerializableTest());
if (sendIntentByType(intent, currentType)) {
Toast.makeText(FuzzerActivity.this, "Sent Serializeable " + intent, Toast.LENGTH_LONG).show();
} else {
Toast.makeText(FuzzerActivity.this, R.string.send_faild, Toast.LENGTH_LONG).show();
}
}
}
});
}
發送請求
private boolean sendIntentByType(Intent intent, String type) {
try {
switch (ipcNamesToTypes.get(type)) {
case Utils.ACTIVITIES:
startActivity(intent);
return true;
case Utils.RECEIVERS:
sendBroadcast(intent);
return true;
case Utils.SERVICES:
startService(intent);
return true;
default:
return true;
}
} catch (Exception e) {
return false;
}
}