外卖O2O App安全性分析:App漏洞评估平台技术细节

外卖O2O App安全性分析:App漏洞评估平台技术细节

0×00、业务需求

在移动互联网和O2O大潮的席卷下,外卖市场逐渐进入的白领的视野,在BAT三巨头砸钱培育市场的情况下,白领的已经更改就餐习惯。只要是坐班的小白领基本上不会到周边商圈购物中心进餐的习惯。外加这个夏天比较热。

根据权威数据分析:

外卖O2O App安全性分析:App漏洞评估平台技术细节

那么,这个市场到底有多大,目前,根据媒体披露,美团外卖2015年上半年业绩:42.5亿。如果按照1/4市场计算,那么,外卖市场有200亿RMB。 怪不得BAT要抢占这块市场,当然分析用户的饮食习惯也是他们的另外一个目的。

然后,我们再看看中国外卖O2O鼻祖饿了么融资情况。

外卖O2O App安全性分析:App漏洞评估平台技术细节

2015年8月份占市场份额为38.75%,累计投资大约10亿美金。

那么,我们关心的是,这么大笔投资,真正使用在IT基础设施建设上面和业务系统搭建的投入是多少?业务系统搭建中,具体的安全投入是多少?如果按照涉及到IT基础设施业务系统搭建占比1%(总投资额计算),安全投入咱以上IT投资的1%的话,那就是安全相当10万美金的投入。

但是,如果你是一个极客,当然是想通过客户端漏洞用Scrapy 爬出大约每天多少单,每单赚多少钱。存储到Mongodb中,然后使用python脚本写大数据报告,用数据说话麽,大家都信,呵呵。

那么基于业务系统App安全评估如何具体做呢?下面着重描述一下。

0×01、App评估方法论

其实网上有很多方法论的东西,这里我站在自由测评人的角度上分析。

首先确定只对Android App APK进行分析,因为Android系统比较开放,模拟器比较多,业务逻辑ipa和Apk是一样的。

在网络上在线评估网站比比皆是,其实其App漏洞评估平台技术都差不多。

外卖O2O App安全性分析:App漏洞评估平台技术细节

一个Android程序上传后首先要判断其是否可以反编译。如果可以,那么就能分析到更多的数据,包括java写的源代码。

那么怎么判断是是否可以被反编译呢?其实可以通过多种方式实施,静态分析是最直接有效的办法,它主要是利用 apktol、dex2jar、jd-gui、smali2dex 等静态分析工具对应用进行反编译,并对反编译后的 java 文件、xml 文件等文件进行静态扫描分析

具体流程图如下:

外卖O2O App安全性分析:App漏洞评估平台技术细节

当然,如果反静态编译失败,就需要动态分析的方法。动态分析技术是对应用软件安装、运行过程的行为监测和分析。检测的方式使用虚拟机方式通过建立与Android手机终端软件运行环境几乎一样的虚拟执行环境,手机应用软件在其中独立运行,从外界观察应用程序的执行过程和动态,进而记录应用程序可能表现出来的恶意行为。

最后,在通过虚拟机分析线上App程序的时候,可能会遇到模拟器检查、root检测等或者IMEI标识判断等高级防调试的功能,这时候就需要人工去分析,也就是说在真实Android手机上安装App进行实地的安全评估。

那么,下面我们以到家美食汇App作为安全评估对象进行评估:

(1)是否被反编译

测试方法使用含有Apktool开源软件的发编译IDE工具测试,Android killer/ ApkIDE改之理 。本文使用Android killer。

外卖O2O App安全性分析:App漏洞评估平台技术细节

从这张图可以看出apk被编译成smali(java虚拟机文件)然后又被反编译成Java class的源代码。

(2)内置组件和外部第三方SDK评估

通过java Decompiler查看源代码发现:

2.1、内置组件:

Com.alibaba.fastjson 阿里巴巴开源高性能JSON开发包  com.android.volley  Android官方通信框架Volley  com.nostra13.universalimageloader 开源 图片库加载。  com.sina.sso 新浪微博登陆SSO组件  com.squareup.okhttp 高效http客户端 (网络拥堵)  okio 开源基本工具库

使用开源组件包,好处是可以提高开发效率,但是如果是开源组件安全性令人担忧,但是目前为止漏洞库中还没有以上组件安全问题。这时不时的让我想起来去年的AFNetworking组件当时引发的中间人攻击的案例。

2.2、第三方SDK组件

com.baidu.mapapi 百度地图  com.baidu.android.pushservice 百度消息推送服务  com.google.analytics google分析API让我们知道用户如何与我们的应用进行交互  com.tencent 访问腾讯openapi 认证等功能  com.umeng.analytics 应用统计分析

那么,外包第三方组件主要搜索重点是APPKey等,可能被黑客利用:

友盟:

<meta-data android:name="UMENG_APPKEY" android:value="528187ac56240bee3803bc39" />  <meta-data android:name="UMENG_CHANNEL" android:value="daojiaweb" />

百度推送:可以获取到推送服务key值以及推送消息等信息,通过修改源码,使开发商利益受到损失。

<service android:name="com.baidu.android.pushservice.CommandService" android:exported="true" />  <meta-data android:name="api_key" android:value="2qoGQfsfg5CcB9cU9PXHNBGX" />

百度地图:

<meta-data android:name="com.baidu.lbsapi.API_KEY" android:value="jGY5Ft6EuDv9gKWT9dg51UOl" />

(3)不安全的数据存储

3.1、SharedPreferences

首先检查的是SharedPreferences,这是一个可以全局访问的数据结构。经过源码查找发现。

但是,到家使用了混淆类处理:ObscuredSharedPreferences,这个类有对SharedPreferences的加解密函数,但是在源代码被反编译后,没有任何保护力度,黑客可以直接拿解密函数破解其加密数据

public class ObscuredSharedPreferences    implements SharedPreferences  {    private static final char[] SEKRIT = { 23, 45, 79, 65, 98, 21, 13, 18, 64, 28 };    protected static final String UTF8 = "utf-8";    protected Context context;    protected SharedPreferences delegate;       protected String decrypt(String paramString)    {      if (paramString != null) {}      for (;;)      {        try        {          arrayOfByte = Base64.decode(paramString, 0);          SecretKey localSecretKey =   SecretKeyFactory.getInstance("PBEWithMD5AndDES").generateSecret(new   PBEKeySpec(SEKRIT)); // 使用java相关加密算法解密,秘钥是SEKRIT          Cipher localCipher = Cipher.getInstance("PBEWithMD5AndDES");          localCipher.init(2, localSecretKey, new   PBEParameterSpec(Settings.Secure.getString(this.context.getContentResolver(),   "android_id").getBytes("utf-8"), 20)); //UTF-8编码          return new String(localCipher.doFinal(arrayOfByte), "utf-8");        }        catch (Exception localException)        {          byte[] arrayOfByte;          throw new RuntimeException(localException);        }        arrayOfByte = new byte[0];      }    }         protected String encrypt(String paramString)    {      if (paramString != null) {}      for (;;)      {        try        {          arrayOfByte = paramString.getBytes("utf-8");          SecretKey localSecretKey =   SecretKeyFactory.getInstance("PBEWithMD5AndDES").generateSecret(new   PBEKeySpec(SEKRIT)); // 使用java相关加密算法加密,秘钥是SEKRIT          Cipher localCipher = Cipher.getInstance("PBEWithMD5AndDES");          localCipher.init(1, localSecretKey, new   PBEParameterSpec(Settings.Secure.getString(this.context.getContentResolver(),   "android_id").getBytes("utf-8"), 20)); //UTF-8编码          return new String(Base64.encode(localCipher.doFinal(arrayOfByte), 2), "utf-8");        }        catch (Exception localException)        {          byte[] arrayOfByte;          throw new RuntimeException(localException);        }        arrayOfByte = new byte[0];      }    }

3.2、ContentProvider

ContentProvider是android组件之一,可以提供数据的跨应用程序访问,针对其搜索关键字为:ContentResolver。因为这个函数是解析ContentProvider存储的数据的。

外卖O2O App安全性分析:App漏洞评估平台技术细节

但是里面没有什么有价值的数据,pass.

3.3、sqlite

所有的Android数据存储都是使用轻量级的sqlite数据库,在源码中有很多地方都能找到,我就不一一列举了。 同样也没什么有价值的数据 pass.

(4)敏感信息安全评估

4.1、敏感信息检测>>获取设备信息

该app中使用了获取设备信息的权限,窃取用户隐私。

DaojiaApp:  {        Utils.initSomeThing(); //获取GPS数据        Globals.instance().currentVersion = getPackageManager().getPackageInfo(getPackageName(), 0).versionName; //获取App程序版本        Globals.instance().manufacturer = Build.MANUFACTURER;      //Build.MANUFACTURER // 硬件制造商            Globals.instance().model = Build.MODEL; // Build.MODEL // 版本          Globals.instance().os_version = Build.VERSION.RELEASE;   //获取android系统的版本信息->版本字符串   Build.VERSION.RELEASE         WifiInfo localWifiInfo = ((WifiManager)getSystemService("wifi")).getConnectionInfo();        Globals.instance().mac = localWifiInfo.getMacAddress();  //获取wifi MAC地址        TelephonyManager localTelephonyManager = (TelephonyManager)getSystemService("phone"); //获得手机号        Globals.instance().imei = localTelephonyManager.getDeviceId(); //获取IMEI        DisplayMetrics localDisplayMetrics = new DisplayMetrics(); //屏幕大小        getWindowManager().getDefaultDisplay().getMetrics(localDisplayMetrics);        Globals.instance().w = localDisplayMetrics.widthPixels;        Globals.instance().h = localDisplayMetrics.heightPixels;        Globals.instance().resolution = (localDisplayMetrics.widthPixels + "_" + localDisplayMetrics.heightPixels);        ObscuredSharedPreferences localObscuredSharedPreferences = new   ObscuredSharedPreferences(this, getSharedPreferences("daojia", 0));        if (localObscuredSharedPreferences.getInt("CityID", 0) != 0) {          Globals.instance().cityID = localObscuredSharedPreferences.getInt("CityID", 0);      }

4.2、敏感信息检测>>App服务器地址

外卖O2O App安全性分析:App漏洞评估平台技术细节

后来通过http抓包发现,这个地址只是一个获取服务器地址的中间环节,真正的服务器地址是在这个地址中存储,并且检测其连接App的属性。

4.3、敏感信息检测>>字符串初始化检测

//针对服务器提交的翻译命令    public static final String DELETEHISTORYADDRESSREQUEST = "DeleteHistoryAddress";    public static final String DELETEHISTORYORDERREQUEST = "DeleteHistoryOrder";    public static final String DOACTIVEUSER = "DoActiveUser";    public static final String DOCOMPLAINTREQUEST = "DoComplaint";    public static final String DOLOGINREQUEST = "DoLogin";    public static final String DOLOGOUT = "DoLogout";    public static final String DOREGISTERREQUEST = "DoRegister";    public static final String DOREGISTERREQUESTRESP = "DoRegisterResp";    public static final String DOURGENTREQUEST = "DoUrgent";    public static final String GETADVERTISELISTREQUEST = "GetAdvertiseList";    public static final String GETAREAANNOUNCEMENTLISTREQUEST = "GetAreaAnnouncementList";    public static final String GETAREALISTREQUEST = "GetAreaList";    public static final String GETAUTHORIZATIONCODEREQUEST = "GetAuthorizationCode";    public static final String GETCARDLISTSREQUEST = "GetCardList";    public static final String GETCITYLISTREQUEST = "GetCityList";    public static final String GETCOUPONLISTREQUEST = "GetCouponList";    public static final String GETFOODCATAGORYLISTREQUEST = "GetFoodCatagoryList";    public static final String GETFOODLISTREQUEST = "GetFoodList";    public static final String GETHISTORYADDRESSREQUEST = "GetHistoryAddress";    public static final String GETHISTORYORDERLISTREQUEST = "GetHistoryOrderList";    public static final String GETHISTORYRESTAURANTLISTREQUEST = "GetHistoryRestaurantList";    public static final String GETHOTFOODLISTREQUEST = "GetHotFoodList";    public static final String GETORDERDETAILSREQUEST = "GetOrderDetails";    public static final String GETPROFILEREQUEST = "GetProfile";    public static final String GETPROFILEREQUESTRESP = "GetProfileResp";    public static final String GETRESTAURANTCATAGORYLISTREQUEST = "GetRestaurantCatagoryList";    public static final String GETRESTAURANTLISTREQUEST = "GetRestaurantList";    public static final String GETRESTAURANTMESSAGELISTREQUEST = "GetRestaurantMessageList";    public static final String GETTODAYORDERLISTREQUEST = "GetTodayOrderList";

4.4、敏感信息检测>>密码管理

登陆密码保存使用ObscuredSharedPreferences同样的数据密码加密形式。

private void doLogin()    {      if (Upgrade.hasUpgrade(this.frameActivity)) {        return;      }      new Server(this.frameActivity, getResources().getString(2131034313))      {        protected Integer doInBackground(String… paramAnonymousVarArgs)        {          ArrayList localArrayList1 = new ArrayList();          localArrayList1.add("DoLogin");          int i = Globals.instance().interactWithServer(localArrayList1, null, null);          if (i != 0) {            return Integer.valueOf(i);          }          ArrayList localArrayList2 = new ArrayList();          localArrayList2.add("GetHistoryAddress");          localArrayList2.add("GetProfile");          localArrayList2.add("GetCardList");          return Integer.valueOf(Globals.instance().interactWithServer(localArrayList2, null, null));        }               protected void onPostExecute(Integer paramAnonymousInteger)        {          super.onPostExecute(paramAnonymousInteger);          if (paramAnonymousInteger.intValue() != 0)          {            Globals.instance().isLogined = false;            SharedPreferences.Editor localEditor = DaojiaApplication.getInstance().getSharedPreferences("token", 0).edit();            localEditor.putString("terminalToken", "");            localEditor.commit();            EditText localEditText1 = Login.this.accountEditText;            Globals.instance().mobile = "";            localEditText1.setText("");            EditText localEditText2 = Login.this.passwordEditText;            Globals.instance().passwd = "";            localEditText2.setText("");            new   AlertDialog.Builder(Login.this.frameActivity).setMessage(Globals.instance().error(paramAnonymousInteger.intValue(),     Login.this.frameActivity.getResources())).setNegativeButton(Login.this.frameActivity.getResources().getString(2131034125),   null).show().setCanceledOnTouchOutside(false);            return;          }          ObscuredSharedPreferences localObscuredSharedPreferences =   new ObscuredSharedPreferences(Login.this.frameActivity,   Login.this.frameActivity.getSharedPreferences("daojia", 0));          localObscuredSharedPreferences.edit().putString("Account", Globals.instance().mobile).commit();          localObscuredSharedPreferences.edit().putString("Passwd",   Globals.instance().passwd).commit(); //直接使用ObscuredSharedPreferences   加密方式处理          Globals.instance().isStroll = false;          int i = Globals.instance().todayOrderTotal;          if (i != 0) {            Login.this.frameActivity.tabActivity.showBadge(1, i);          }          for (;;)          {            EasyTracker localEasyTracker = EasyTracker.getInstance(Login.this.frameActivity);            localEasyTracker.set("&cd", "登录成功");            localEasyTracker.set(Fields.customDimension(1), "Yes");            localEasyTracker.send(MapBuilder.createAppView().build());            try            {              Login.this.frameActivity.getSupportFragmentManager().popBackStack();              return;            }            catch (Exception localException)            {              Login.this.isBack = true;              return;            }            Login.this.frameActivity.tabActivity.hideBadge(1);          }        }      }.execute(new String[] { "" });    }

(5)HTTP(s)分析

测试方法,在Android手机,安装到家美食汇App,然后手机上安装Fiddler证书,设置wifi代理获取http(s)数据流量

5.1、登录数据分析

Json值完全没加密

外卖O2O App安全性分析:App漏洞评估平台技术细节

建议在使用工具分析HTTP(s)的数据时,如果可以反编译java源代码的话,就可以更直观的了解其整个登录流程。

由于登录源代码在以上密码分析部分已经说过,这次看注册函数:

在daojia.fragment.Register 下,onClick动作下面。

同时,还发现在输入内容上没有做任何过滤,有SQL injection的风险。

public void onClick(View paramView)    {      if (paramView.getId() == 2131492865)      {        localView = this.frameActivity.getWindow().getCurrentFocus();        if (localView != null) {          ((InputMethodManager)this.frameActivity.getSystemService("input_method")).hideSoftInputFromWindow(localView.getWindowToken(), 0);        }        this.frameActivity.getSupportFragmentManager().popBackStack();      }      while (paramView.getId() != 2131492906)      {        View localView;        return;      }      if ((this.linkman1EditText.getText().toString().trim().length() == 0) && (this.linkman2EditText.getText().toString().trim().length() == 0))      {        new AlertDialog.Builder(this.frameActivity).setMessage(getResources().getString(2131034159)).setPositiveButton(getResources().getString(2131034125), null).show().setCanceledOnTouchOutside(false);        return;      }      if (this.mobileEditText.length() == 0)      {        new AlertDialog.Builder(this.frameActivity).setMessage(getResources().getString(2131034160)).setPositiveButton(getResources().getString(2131034125), null).show().setCanceledOnTouchOutside(false);        return;      }      if (!this.mobileEditText.getText().toString().matches("^1[3,4,5,8,7]//d{9}$"))      {        new AlertDialog.Builder(this.frameActivity).setMessage(getResources().getString(2131034161)).setPositiveButton(getResources().getString(2131034125), null).show().setCanceledOnTouchOutside(false);        return;      }      if (this.passwdEditText.length() == 0)      {        new AlertDialog.Builder(this.frameActivity).setMessage(getResources().getString(2131034162)).setPositiveButton(getResources().getString(2131034125), null).show().setCanceledOnTouchOutside(false);        return;      }      if (this.passwdEditText.length() < 6)      {        new AlertDialog.Builder(this.frameActivity).setMessage(getResources().getString(2131034163)).setPositiveButton(getResources().getString(2131034125), null).show().setCanceledOnTouchOutside(false);        return;      }      if (this.passwdEditText.getText().toString().compareTo(this.confirmEditText.getText().toString()) != 0)      {        new AlertDialog.Builder(this.frameActivity).setMessage(getResources().getString(2131034164)).setPositiveButton(getResources().getString(2131034125), null).show().setCanceledOnTouchOutside(false);        return;      }      MobclickAgent.onEvent(this.frameActivity, "Step2ForRegistration");      Log.e("main", "step2ForRegistration");      Globals.instance().mobile = this.mobileEditText.getText().toString();      doGetCode();    }       public View onCreateView(LayoutInflater paramLayoutInflater, ViewGroup paramViewGroup, Bundle paramBundle)    {      super.onCreateView(paramLayoutInflater, paramViewGroup, paramBundle);      this.rootLayout = ((ViewGroup)paramLayoutInflater.inflate(2130903096, paramViewGroup, false));      this.linkman1EditText = ((EditText)this.rootLayout.findViewById(2131492984));      this.linkman1EditText.addTextChangedListener(this);      this.linkman2EditText = ((EditText)this.rootLayout.findViewById(2131492985));      this.linkman2EditText.addTextChangedListener(this);      ((InputMethodManager)this.frameActivity.getSystemService("input_method")).toggleSoftInput(2, 0);      this.mobileEditText = ((EditText)this.rootLayout.findViewById(2131493014));      this.passwdEditText = ((EditText)this.rootLayout.findViewById(2131492994));      this.confirmEditText = ((EditText)this.rootLayout.findViewById(2131493035));      ((TextView)this.rootLayout.findViewById(2131492866)).setText(2131034143);      ImageView localImageView = (ImageView)this.rootLayout.findViewById(2131492865);      localImageView.setVisibility(0);      localImageView.setOnClickListener(this);      ((Button)this.rootLayout.findViewById(2131492906)).setOnClickListener(this);      return this.rootLayout;    }

5.2、下单业务流程

Json没加密是不是就可以刷单了,或者篡改数据了?

外卖O2O App安全性分析:App漏洞评估平台技术细节

5.3、重放攻击

这个问题,先在这里说明一下,如果要抵制App重放攻击,需要在每个请求包总添加包序列号,每次提交自动加一,如果收到的包相同就认为是重放攻击。目前到家美食汇App是做到的,虽然没有后台的源程序,但是从客户端源代码(com.daojia.ds)中可以发现:

private int getUrl()    {      Object localObject1 = "";      for (;;)      {        int j;        try        {          JSONObject localJSONObject1 = new JSONObject();          try          {            localJSONObject1.put("Command", "LookupServer");            localJSONObject1.put("SequenceID", "0");            localJSONObject1.put("CheckDigit", "0");            JSONObject localJSONObject3 = new JSONObject();            localJSONObject3.put("CityID", this.cityID);            localJSONObject1.put("Body", localJSONObject3);            JSONArray localJSONArray3 = new JSONArray();            localJSONArray3.put(localJSONObject1);            String str3 = localJSONArray3.toString();            localObject1 = str3;          }          catch (JSONException localJSONException)          {  ***  continue;          }          localHttpPost = new HttpPost(DAOJIASERVER);          Log.e("afei", "request body is ===" + (String)localObject1);          localStringEntity = new StringEntity((String)localObject1, "UTF-8");          localStringEntity.setContentType("application/x-www-form-urlencoded");          localHttpPost.setEntity(localStringEntity);          localHttpPost.addHeader("Accept-Encoding", "gzip, deflate");          List localList = ((BasicCookieStore)this.localContext.getAttribute("http.cookie-store")).getCookies();          bool = localList.isEmpty();          int i = 0;          int k;          StringBuilder localStringBuilder;          String str2;          JSONArray localJSONArray1;          if (!bool)          {            k = 0;            if (k < localList.size()) {}          }          else          {            if (i == 0)            {              str1 = DaojiaApplication.getInstance().getSharedPreferences("token", 0).getString("terminalToken", "");              if (!TextUtils.isEmpty(str1)) {                localHttpPost.addHeader("Cookie", "token=" + str1 + ";");              }            }            localHttpResponse = this.httpClient.execute(localHttpPost, this.localContext);            localHttpEntity = localHttpResponse.getEntity();            localObject2 = localHttpResponse.getEntity().getContent();            localHeader = localHttpResponse.getFirstHeader("Content-Encoding");            if ((localHeader != null) && (localHeader.getValue().equalsIgnoreCase("gzip"))) {              localObject2 = new GZIPInputStream((InputStream)localObject2);            }            localInputStreamReader = new InputStreamReader((InputStream)localObject2);            localBufferedReader = new BufferedReader(localInputStreamReader, 8192);            localStringBuilder = new StringBuilder();            str2 = localBufferedReader.readLine();            if (str2 != null) {              continue;            }            localHttpEntity.consumeContent();            localJSONArray1 = new JSONArray(localStringBuilder.toString());            j = 0;            if (j < localJSONArray1.length()) {              continue;            }            return -1;          }          if (((Cookie)localList.get(k)).toString().contains("token"))          {            i = 1;            break label640;            localStringBuilder.append(str2);            continue;          }          JSONObject localJSONObject2;          JSONArray localJSONArray2;          k++;        }        catch (Exception localException)        {  ***          }          localJSONArray2 = localJSONObject2.getJSONArray("Servers");          Globals.instance().host0 = localJSONArray2.optString(0, "");          Globals.instance().host1 = localJSONArray2.optString(1, "");          Globals.instance().mapping = localJSONObject2.getString("Mapping");          if (getCityV(Globals.instance().mapping) == 0) {            LOOKUPS = Globals.instance().host0;          } else {            LOOKUPS = Globals.instance().host1;          }        }        catch (ConnectTimeoutException localConnectTimeoutException)        {          return -1;        }        label640:        continue;        label646:        j++;      }    }

(6)SQL injection分析

有关App SQL注入的攻击测试方法可以参考

原理:就是用burpsuite 设置代理记录log文件,然后,狂点App上的界面,然后通过提交的post数据,进行sqlmap测试。

sqlmap -r "/root/desktop/daojia.txt" --threads=3 --risk=3 --level=3 --random-agent --time-sec=15 --timeout=15 --beep –dbs

外卖O2O App安全性分析:App漏洞评估平台技术细节

但是经过测试目前还没有注入漏洞。

(7)签名校验

签名作用

1.发送者的身份认证:由于开发商可能通过使用相同的 Package Name 来混淆替换已经安装的程序,以此保证签名不同的包不被替换。
2.保证信息传输的完整性:签名对于包中的每个文件进行处理,以此确保包中内容不被替换。

PackageInfo packageInfo = getPackageManager().getPackageInfo(    "com.daojia.xxx", PackageManager.GET_SIGNATURES);    Signature[] signs = packageInfo.signatures;

使用关键字“PackageInfo”搜索。Signature 太多,第三方和开源组件基本上都有签名校验。

外卖O2O App安全性分析:App漏洞评估平台技术细节

主程序没有做签名校验,使用resign工具可以直接打包。。

最后,还是向大家介绍一下online检测工具。具有检测内容我就不在文章中列举了。大家可以自己上传看看,星多漏洞多。

外卖O2O App安全性分析:App漏洞评估平台技术细节

这里想向大家详细介绍一下Mobile security Framework,这个用python写的开源的评估程序,这个工具加快了App程序漏洞评估速度,当然,自动化的程序特别是开源的很容易被App厂商和谐掉,还是要使用手工分析方法。或者是使用自动化分析工具先看看有什么详细漏洞,然后使用手工分析。

个人觉得MobSF在建立动态分析环境方面很快,本人通过翻墙才下载到ova虚拟化文件(oracle Virtualbox)。实现了动态分析,其实就是一个google android手机操作系统模拟器,通过python把各个手工测试工具连接起来做成自动化分析程序。

外卖O2O App安全性分析:App漏洞评估平台技术细节

外卖O2O App安全性分析:App漏洞评估平台技术细节

0×02、结论

经过检测发现美团外卖做的相对比较好,到家美食汇做的相对差一点。我想这和在安全上的投入有关系,在残酷的市场竞争环境下,首先要解决生存的问题,然后才能考虑安全的问题,当然了,如果你是互联网巨头BAT也会有先天的优势,安全性的研究会有N多NB人才立助你业务系统安全,对付开源检测工具还是绰绰有余的。那么对于创业掌门人的你,在App业务系统安全性问题上,你会选择传统互联网安全公司(爱加密、梆梆等)对你的业务系统做企业级的加固,还是建立自己SRC团队做安全运营?或者采用众测的形式花钱买漏洞?

* 作者:bt0sea,本文属FreeBuf原创奖励计划文章,未经许可禁止转载。

发表评论