Android security知识点总结

本文详细介绍了Linuxsepolicy在Android系统中的应用,包括IPK包管理、SecureBoot流程、AVB(AndroidVerifiedBoot)验证、SELinux策略及其权限检查,以及如何使用Audit2allow工具生成sepolicy。还涵盖了AVB的启用与禁用、加密技术和安全设置,如dm-verity和SELinux的作用与配置方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Linux sepolicy uses ipk package, each binary has three sepolicy files, they are if (interface), fc (file context), te. opkg install selinux.ipk

1 Android selinux
1.1 How to compile Android sepolicy
restorecon -v /path/to/test
chcon u:object_r:xxx_exec:s0 /path/to/test

/system/bin/secilc \
/system/etc/selinux/plat_sepolicy.cil \
-m -M true -G -c 33 \
/system/etc/selinux/mapping/33.0.cil \
-o /dev/precompiled_sepolicy \
/system_ext/etc/selinux/system_ext_sepolicy.cil \
/system_ext/etc/selinux/mapping/33.0.cil \
/product/etc/selinux/product_sepolicy.cil \
/product/etc/selinux/mapping/33.0.cil \
/vendor/etc/selinux/vendor_sepolicy.cil \
/vendor/etc/selinux/plat_pub_versioned.cil

Get version from /sys/fs/selinux/policyvers
Get mapping version from /vendor/etc/selinux/plat_sepolicy_vers.txt
/vendor/etc/selinux/precompiled_sepolicy will be written into /sys/fs/selinux/load

1.2 selinux权限检查原理
Linux系统先做DAC(Discretionary Access Control,自主访问控制,Linux传统权限)检查。如果没有通过DAC权限检查,则操作直接失败。通过DAC检查之后,再做MAC(Mandatory Access Control,selinux)权限检查。

编译时强制打开selinux。
BOARD_KERNEL_CMDLINE += androidboot.selinux=enforcing

1.3 struct security_hook_heads
struct security_hook_list selinux_hooks[]
security_add_hooks()
security_delete_hooks()
找到selinux_hooks的地址,使用ARRAY_SIZE算出有多少个element,每个element都是一个链表,是同一个hook对象的结合,譬如当检查file_open时,那么这个链表的所有节点的回调函数都要运行一次。使用security_delete_hooks()可以反注册selinux_hooks。

1.4 查看设备节点的selinux权限
ls -alZ /dev/kmsg
getprop -Z persist.sys.usb.config
ps -AZ
restorecon -v /vendor/bin/xxx

1.5 打开关闭sepolicy
需要Android版本是usereng/eng

adb root
adb shell

关闭:
# setenforce 0
打开:
# setenforce 1

1.6 添加到启动脚本中禁止security
on nonencrypted
    # A/B update verifier that marks a successful boot.
    exec - root cache -- /system/bin/update_verifier nonencrypted
    class_start main
    class_start late_start

in late_start script, add [setenforce 0]

1.7 根据avc log生成sepolicy
1)提取所有的avc log
adb shell "cat /proc/kmsg | grep avc" > avc_log.txt

or

adb shell
dmesg | grep avc > /dev/avc_log.txt
adb pull /dev/avc_log.txt .

2)使用audit2allow直接生成policy
sudo apt-get install policycoreutils
audit2allow -i avc_log.txt -o output_pol.te
vi output_pol.te

3)
external/selinux/prebuilts/bin/audit2allow \
-i abc.txt > abc.te

1.8 Android 8.0 adb root sepolicy
CTS SELinuxNeverallowRulesTest.java
private - not visible to OEM
public - visible to OEM

CIL: SELinux Common Intermediate Language
/system/bin/secilc
-N: disable neverallow check before build

1) extract adbd.cil and su.cil from userdebug /system/etc/selinux/plat_sepolicy.cil
2) before pack system image, write adbd.cil and su.cil to user /system/etc/selinux/plat_sepolicy.cil
- function build-systemimage-target, pass 3 args to build/tools/releasetools/build_image.py
- add the following 5 commands to function build-systemimage-target
  # Use the following command to add su to typeattributeset coredomain and typeattributeset mlstrustedsubject.
  # @sed -i "s#abcdzcb(.∗abcdzcb(.∗ xxx#\1 su xxx#" 1.txt
  @sed -i -e '/neverallow \
  adbd/d' /path/to/plat_sepolicy.cil
  @cat /path/to/adbd.cil >> \
  /path/to/plat_sepolicy.cil
  @cat /path/to/su.cil >> \ 
  /path/to/plat_sepolicy.cil
3) Android init process will call /system/bin/secilc compile CIL files to binary, then write binary to kernel.

mmm system/sepolicy
out/target/product/<ppp>
/system/etc/selinux - AOSP
/vendor/etc/selinux - OEM

2 Chain of Trust
2.1 qcom efuse
对bootloader签名,熔丝文件:sec.dat

1)烧写signed bootloader
2)将密匙文件sec.dat烧写入efuse
3)重启设备,设备的bootROM会读取efuse中的密匙pubk验证bootloader
4)bootloader验证通过,启动,开始基于信任链(chain of trust)的AVB验证流程

2.2 编译时关闭AVB
BoardConfig.mk
BOARD_AVB_ENABLE := false
BOARD_BUILD_DISABLED_VBMETAIMAGE := true

Android 8.0之后没有独立的recovery.img,boot.img根据cmdline参数来决定mount哪个ramdisk。
如果有skip_initramfs参数,那么mount打包在system.img(system-as-root)中的normal ramdisk;否则mount打包在boot.img中的recovery ramdisk。

参数BOARD_BUILD_SYSTEM_ROOT_IMAGE的配置决定是将normal ramdisk打包到boot.img中还是打包到system.img中。
打包到boot.img中:
BOARD_BUILD_SYSTEM_ROOT_IMAGE := false

打包到system.img中(system-as-root):
BOARD_BUILD_SYSTEM_ROOT_IMAGE := true

2.3 AVB验证流程
需要提前挂载分区的fstab来自于commandline的androidboot.android_dt_dir
1)bootloader使用内置的OEM pubk验证vbmeta.img,验证通过后用vbmeta.img中的boot pubk验证boot.img,如果验证通过就启动boot.img
2)init启动后,init/fs_mgr使用vbmeta.img中的vendor pubk、system pubk、odm pubk验证vendor.img、system.img、odm.img,验证通过就mount,否则不会mount

编译生成Metadata流程:
@ build/core/Makefile
->
@ build/tools/releasetools/build_image.py
->
BuildVerityTree() - 用来生成dm_verity需要的签名数据
BuildVerityMetadata() - 生成Metadata数据
->
@ system/extras/verity/build_verity_metadata.py
->
build_verity_metadata()

2.4 dm-verity
可以使用内核配置CONFIG_DM_VERITY_HASH_PREFETCH_MIN_SIZE(默认大小为128)来启用dm-verity哈希预提取大小,该修改可提升启动速度。

2.5 Android 8.0 userdebug版本刷机时禁止dm-verity
Android 8.0 dm-verity disable flag存在于vbmeta.img(keystore分区)中;而老版本是放置在system.img分区的dm-verity metadata中。
1)在设置中打开OEM unlocking选项
2)在设置中打开USB debugging选项
3)adb reboot bootloader
4)fastboot flashing unlock和fastboot oem unlock
5)fastboot --disable-verity --disable-verification flash vbmeta vbmeta.img
6)fastboot reboot
7)adb root
8)adb remount

2.6 vbmeta for AVB disabled
# commands from zcat out/verbose.log.gz
# PEM: Privacy Enhanced Mail
#!/bin/sh

MY_PATH=${PWD}
TARGET_DIR=${MY_PATH}/out/target/product/${TARGET_PRODUCT}
AVB_TOOL=${MY_PATH}/external/avb/avbtool
# or your own xxx_rsa4096.pem file
TESTKEY=${MY_PATH}/external/avb/test/data/testkey_rsa4096.pem

# in x86_64 platform, replace dtbo.img with tos.img
python ${AVB_TOOL} make_vbmeta_image --output ${TARGET_DIR}/vbmeta_disabled.img \
    --include_descriptors_from_image ${TARGET_DIR}/boot.img \
    --include_descriptors_from_image ${TARGET_DIR}/system.img \
    --include_descriptors_from_image ${TARGET_DIR}/vendor.img \
    --include_descriptors_from_image ${TARGET_DIR}/dtbo.img \
    --setup_rootfs_from_kernel ${TARGET_DIR}/system.img \
    --algorithm SHA256_RSA4096 \
    --key ${TESTKEY} \
    --padding_size 4096 \
    --set_hashtree_disabled_flag

2.7 EXT4 Encryption
FBE:加密的仅仅是文件内容和文件名,其他的信息比如文件大小,权限等都没有加密,这些内容就是filesystem metadata
Metadata分区:加密文件大小,权限等除了文件内容和文件名之外的文件信息,/metadata/vold/metadata_encryption/key
QSEE: Qualcomm Security Executing Environment

github ext4-crypt
add_key() - e4crypt add_key
keyctl_search()
keyctl_unlink()

setenforce 0
# erase RPMB
qseecom_sample_client -v sampleapp 15 1
# program RPMB
qseecom_sample_client -v sampleapp 14 1

adb push keybox.xml /data
adb shell
cd /data
LD_LIBRARY_PATH=/vendor/lib/hw KmInstallKeybox keybox.xml <dev_id> true

2.8 lpunpack
lp: Logical Partition images

make lpunpack

simg2img super.img super_ext4.img
mkdir super_ext4
out/host/linux-x86/bin/lpunpack super_ext4.img super_ext4/

3 audit2allow python
#
# audit2allow, translate avc log to .te file
# Author: George Tso
#
# usage
# dmesg | grep "avc" > /dev/avc.log
# adb pull /dev/avc.log .
# audit2allow avc.log avc.te

import re
import string
import sys

def write_outfile(outfile, hashmap):
    for (hm_key, hm_value) in hashmap.items():
    #{
        allow_value = ''
        hm_value.sort()

        if (len(hm_value) == 1):
            allow_line = hm_key +
                ' ' + hm_value[0] + ';' + '\n'
        else:
            for value in hm_value:
                allow_value += ' ' + value
            allow_line = hm_key +
                ' {' + allow_value + ' };' + '\n'

        outfile.writelines(allow_line)
    #}

def has_proc(line, proc):
    e_list = line.split()
    for e in e_list:
    #{
        if (e.find('scontext') > -1):
            sub = e.split(':')
            if (proc == sub[2]):
                return True
            else:
                return False
    #}
    return False

def _generate_te(proc_list):
    src = ''
    tgt = ''
    tclass = ''
    got_tclass = False
    hashmap = {}
    got_key = False
    repeat = False

    outfile = open(sys.argv[2], 'w')
    for proc in proc_list:
    #{
        outfile.writelines('\n\n===============' +
            proc + '================\n')
        file = open(sys.argv[1], 'r')
        for line in file.readlines():
        #{
            line = line.strip()
            if not len(line) or line.startswith('#'):
                 continue

            if (has_proc(line, proc) == False):
                # not this process, continue
                continue

            # regular expression to extract {}
            perm = re.findall(r'[{](.*?)[}]', line)
            #print(perm[0].strip())

            e_list = line.split()
            for e in e_list:
            #{
                if (e.find('scontext') > -1):
                    sub = e.split(':')
                    src = sub[2]
                elif (e.find('tcontext') > -1):
                    sub = e.split(':')
                    tgt = sub[2]
                elif (e.find('tclass') > -1):
                    sub = e.split('=')
                    tclass = sub[1]
                    got_tclass = True

                if (got_tclass == True):
                    got_tclass = False

                    allow_key = 'allow' + ' ' + src +
                        ' ' + tgt + ':' + tclass.strip()
                    allow_value = perm[0].lstrip().rstrip()
                    hm_key = ''
                    hm_value = []

                    for (hm_key, hm_value) in \
                        hashmap.items():
                    #{
                        if (hm_key == allow_key):
                            got_key = True
                            break;
                    #}

                    if (got_key == True):
                        got_key = False

                        for value in hm_value:
                        #{
                            if (value == allow_value):
                                repeat = True
                                break;
                        #}
                        if (repeat == False):
                            hm_value.append(allow_value)
                            hashmap[allow_key] = \
                                hm_value
                        repeat = False
                    else:
                        hm_value = []
                        hm_value.append(allow_value)
                        hashmap[allow_key] = hm_value
            #} end of for e in e_list
        #} end of for line in file.readlines()

        write_outfile(outfile, hashmap)
        hashmap.clear()
        file.close()
    #} for proc in proc_list
    outfile.close()

def generate_te():
    # STEP 1 - FIND ALL THE PROCESSES
    proc_list = []
    repeat = False

    file = open(sys.argv[1], 'r')
    for line in file.readlines():
    #{
        line = line.strip()
        if not len(line) or line.startswith('#'):
             continue

        e_list = line.split()
        for e in e_list:
        #{
            if (e.find('scontext') > -1):
                sub = e.split(':')
                for proc in proc_list:
                #{
                    if (proc == sub[2]):
                        repeat = True;
                        break;
                #}
                if (repeat == False):
                    proc_list.append(sub[2])
                repeat = False
                break
        #}
    #}
    file.close()
    proc_list.sort()
    print proc_list

    # STEP 2 - GENERATE OUTPUT FILE
    _generate_te(proc_list)

if __name__ == '__main__':
    if (len(sys.argv) < 3):
        print(sys.argv[0] +
            ' ' + '<input_file.log>' +
            ' ' + '<output_file.te>')
        exit(0)
    generate_te()

4 Abbreviations
avb:Android Verified Boot,用dm-verify验证system分区的完整性,用在Android 8.0之后的fstab中
AVC:Access Vector Cache
cmnlib.mbn: qcom trustzone commonlib, qseecom_sample_client
DAC:Discretionary Access Control,自主访问控制
devcfg.mbn: qcom QUP访问权限控制,SPI片选和时钟线分别对应I2C的SDA和SCL
FRP:Factory Reset Protection
km41.mbn: qcom keymaster v4.1
LSM:Linux Security Module
seccomp: Android 8.1 secure computing
TE:Type Enforcement

Android Security: Attacks and Defenses is for anyone interested in learning about the strengths and weaknesses of the Android platform from a security perspective. Starting with an introduction to Android OS architecture and application programming, it will help readers get up to speed on the basics of the Android platform and its security issues. Explaining the Android security model and architecture, the book describes Android permissions, including Manifest permissions, to help readers analyze applications and understand permission requirements. It also rates the Android permissions based on security implications and covers JEB Decompiler. The authors describe how to write Android bots in JAVA and how to use reversing tools to decompile any Android application. They also cover the Android file system, including import directories and files, so readers can perform basic forensic analysis on file system and SD cards. The book includes access to a wealth of resources on its website: www.androidinsecurity.com. It explains how to crack SecureApp.apk discussed in the text and also makes the application available on its site. The book includes coverage of advanced topics such as reverse engineering and forensics, mobile device pen-testing methodology, malware analysis, secure coding, and hardening guidelines for Android. It also explains how to analyze security implications for Android mobile devices/applications and incorporate them into enterprise SDLC processes. The book’s site includes a resource section where readers can access downloads for applications, tools created by users, and sample applications created by the authors under the Resource section. Readers can easily download the files and use them in conjunction with the text, wherever needed. Visit www.androidinsecurity.com for more information.
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值