Android应用通常使用PF_UNIX、PF_INET、PF_NETLINK等不同domain的socket来进行本地IPC或者远程网络通信,这些暴露的socket代表了潜在的本地或远程攻击面,历史上也出现过不少利用socket进行拒绝服务、root提权或者远程命令执行的案例。特别是PF_INET类型的网络socket,可以通过网络与Android应用通信,其原本用于linux环境下开放网络服务,由于缺乏对网络调用者身份或者本地调用者pid、permission等细粒度的安全检查机制,在实现不当的情况下,可以突破Android的沙箱限制,以被攻击应用的权限执行命令,通常出现比较严重的漏洞。
作为Android安全研究的新手,笔者带着传统服务器渗透寻找开放socket端口的思路,竟然也刷了不少漏洞,下面就对这种漏洞的发现、案例及影响进行归纳。感谢爱加密网站:提供博客思路,Android应用的安全风险依然严峻。游戏外挂、第三方支付漏洞挖掘、充值卡支付漏洞挖掘、内存修改、存档修改、脚本录制、游戏资源文件窃取与篡改、加速器、模拟器运行,这些对游戏商来说都是致命打击。http://www.ijiami.cn/appprotect_mobile_games
简单地利用命令netstat就可以发现Android开放了许多socket端口,如图。但这些开放端口本后的应用却不得而知。
此时可以通过三步定位法进行寻找,支持非root手机。
第一步,利用netstat寻找感兴趣的开放socket端口,如图中的15555。
第二步,将端口转换为十六进制值,查看位于/proc/net/目录下对应的socket套接字状态文件,在其中找到使用该socket的应用的uid。如15555的十六进制表示为1cc3,协议类型为tcp6,那么查看/proc/net/tcp6文件。
注意上面的10115,就是使用该socket的应用的uid。通过这个uid可以得知应用的用户名为u0_a115。
第三步,根据用户名就可以找到应用了
至此,我们就知道开放15555端口的应用为com.qiyi.video,尽管我们还不能分辨出开放该端口的准确进程,但仍然为进一步的漏洞挖掘打下基础。
写一个简单的脚本来自动化的完成此项工作.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
|
importsubprocess,re
deftoHexPort(port):
hexport=str(hex(int(port)))
returnhexport.strip('0x').upper()
deffinduid(protocol, entry):
if(protocol=='tcp'orprotocol=='tcp6'):
uid=entry.split()[-10]
else:# udp or udp6
uid=entry.split()[-6]
uid=int(uid)
if(uid >10000):# just for non-system app
return'u0_a'+str(uid-10000)
else:
return-1
defmain():
netstat_cmd="adb shell netstat | grep -Ei 'listen|udp*'"
#netstat_cmd = "adb shell netstat "
grep_cmd="adb shell grep"
proc_net="/proc/net/"
# step 1, find interesting port
orig_output=subprocess.check_output(netstat_cmd, shell=True)
list_line=orig_output.split('\r\n')
apps=[]
strip_listline=[]
pattern=re.compile("^Proto")# omit the first line
forlineinlist_line:
if(line !='')and(pattern.match(line)==None):
# step 2, find uid in /proc/net/[protocol] based on port
socket_entry=line.split()
protocol=socket_entry[0]
port=socket_entry[3].split(':')[-1]
grep_appid=grep_cmd+' '+toHexPort(port)+' '+proc_net+protocol
net_entry=subprocess.check_output(grep_appid, shell=True)
uid=finduid(protocol, net_entry)
# step 3, find app username based on uid
if(uid==-1):continue
applist=subprocess.check_output('adb shell ps | grep '+uid, shell=True).split()
app=applist[8]
apps.append(app)
strip_listline.append(line)
itapp=iter(apps)
itline=iter(strip_listline)
# last, add app in orig_output of sockets
print("Package Proto Recv-Q Send-Q Local Address Foreign Address State\r\n")
try:
whileTrue:
printitapp.next()+' '+itline.next()
exceptStopIteration:
pass
if__name__=='__main__':
main()
|
运行结果如下
除了PF_INET套接字外,PF_UNIX、PF_NETLINK套接字的状态文件分别位于/proc/net/unix和/proc/net/netlink。
当然,如果手机已root,可直接使用busybox安装目录下带p参数的netstat命令,可以显示pid和不完整的program name。