2016年6月24日星期五

体验了一下Docker的root用户映射

2016/07/01:要想限制容器里用户的权限,有两种方法:

  1. 让你在容器里做个凡人(这个方法对于有些需要root的容器是不适合的)
具体的就是,指定容器里用户的uid:gid,使得容器里压根不存在root用户。
$ docker run -it -u 1000:1000 ubuntu
groups: cannot find name for group ID 1000   #这个错误没关系
I have no name!@fcaadb40ddd0:/$ id     #执行id命令看看结果。
uid=1000 gid=1000 groups=1000
(这里的uid:gid和主机的不一样,具体的怎么关联的不太清楚。一般来说这个就足够了,但是也许会有什么应用需要root权限,这时就需要下一步要说的方法来限制权限了)
  1. 让你在容器里做玉皇大帝, 但是这个玉皇大帝和所有凡人,都只是被映射到茫茫宇宙中一片卑微甚至虚空的身份上
就算容器里有个孙悟空突破了限制做了玉皇大帝,那也翻不出如来佛的手掌。 具体的就是,把容器里的root等用户映射成主机那边的指定的一片uid:gid。

2017/01/20:忽然想起来看看,容器里以root运行的进程,在外面看来到底是什么?是一个进程。那是什么用户身份呢?也是root,只是capabilities受到很多限制,理论上依然危险。

在docker里以root身份运行sleep 12345
docker@somehost:~$ docker run -it busybox
/ # id
uid=0(root) gid=0(root) groups=10(wheel)
/ # sleep 12345
在容器外面查看这个sleep是什么进程,什么用户身份?也是root。
docker@somehost:~$ ps -ef |grep 12345
root      1997  1980  0 09:44 pts/1    00:00:00 sleep 12345
查看该进程的权限信息,就能够发现capabilities是受限制的,但是理论上还是可以钻漏洞影响到容器外的。
docker@somehost:~$ cat /proc/1997/status |grep Cap
...
CapEff:    00000000a80425fb
...
用capsh工具查看00000000a80425fb就明白意思。这个root收到了限制。
最近用的docker-machine版本是0.8.2,docker 1.12.5。发现docker-machine里面已经默认创建好了dockremap这个用户了,连/etc/subuid /etc/subgid里都准备好了。结果,只要修改活着创建/etc/docker/daemon.json,加上{"userns-remap":"default"}就可以了,重启动docker-machine就可以生效。
确认
docker@somehost:~$ cat /etc/subuid 
dockremap:165536:65536
docker@somehost:~$ cat /etc/subgid 
dockremap:165536:65536
准备
docker@somehost:~$ cat /etc/docker/daemon.json
{
  "userns-remap": "default"
}
如果还不存在dockremap用户,那么就运行这个命令生成用户dockremap:
sudo adduser --system dockremap
重启动
docker-machine restart somehost
docker-machine ssh somehost
在docker里以root身份运行sleep 12345
docker@somehost:~$ docker run -it busybox
/ # id
uid=0(root) gid=0(root) groups=10(wheel)
/ # sleep 12345
在容器外面查看这个sleep是什么进程,什么用户身份
docker@somehost:~$ ps -ef |grep 12345
165536    2360  2344  0 09:36 ?        00:00:00 sleep 12345
就是这个165536,说明生效了,用户身份不是以前的0(root)了。

2016/?/?: 我要体验的就是第2种功能,刚出来半年,因为uid映射只能手动做,而且是针对docker daemon设定的,所以默认是不开启的,也无法从普通的docker run命令里指定。

主要是docker daemon加个选项 --userns-remap=test_user:test_group and add /etc/subuid /etc/subgid
如果按照docker官方文档说的--userns-remap=default(就是让docker daemon创建dockremap用户),也会报错说找不到用户,据有的用户反映是tiny core linux里的adduser和普通的linux发行版不一样,我没仔细查。
$ docker-machine ssh rethink   # rethink is my vm name, please change it to yours.
...
docker@rethink:~$ sudo vi /var/lib/boot2docker/profile 
...
EXTRA_ARGS='
--label provider=virtualbox
--userns-remap=test_user:test_group            #####this is what i add#####
'
...
docker@rethink:~$ exit
then restart by docker-machine restart rethink, cause same error Maximum number of retries (10) exceeded(看/var/lib/boot2docker/docker.log能看到错误是说用户找不到), docker daemon is not started,
then add user/group,
docker@rethink:~$ sudo addgroup -g 20 test_group
docker@rethink:~$ sudo adduser -G test_group -SDHu 501 test_user
then prepare uid/gid range for container
docker@rethink:~$ sudo -c "echo test_user:100000:65536 > /etc/subuid"
docker@rethink:~$ sudo  -c "echo test_group:200000:65536 > /etc/subgid"
then start docker daemon
docker@rethink:~$ sudo /usr/local/bin/docker daemon -D -g "/var/lib/docker" -H unix:// -H tcp://0.0.0.0:2376 --label provider=virtualbox \
--userns-remap=test_user:test_group --tlsverify --tlscacert=/var/lib/boot2docker/ca.pem --tlscert=/var/lib/boot2docker/server.pem --tlskey=/var/lib/boot2docker/server-key.pem -s aufs

...
INFO[0000] User namespaces: ID ranges will be mapped to subuid/subgid ranges of: test_user:test_group 
DEBU[0000] Creating user namespaced daemon root: /mnt/sda1/var/lib/docker/100000.200000 
...
Then i run docker container. There are strange thing here: previously used docker image will be treated as "not exist", get downloaded again.
$ docker run -it -v /bin:/xxx busybox
Unable to find image 'busybox:latest' locally
latest: Pulling from library/busybox
8ddc19f16526: Pull complete 
Digest: sha256:a59906e33509d14c036c8678d687bd4eec81ed7c4b8ce907b888c607f6a1e0e6
Status: Downloaded newer image for busybox:latest
/ # id
uid=0(root) gid=0(root) groups=10(wheel)
/ # ls /xxx
VBoxClient     cat            dd             echo           gunzip         ln             mount          printenv       ...
...
/ # echo hi > /xxx/a
sh: can't create /xxx/a: Permission denied
很好, container里的root只能老老实实的以host os里的test_user身份运行了。
不过一旦重启动就泡汤了(还是老错误说用户找不到), 出现问题后,请进去把/var/lib/boot2docker/profile里的改动给恢复就行了。
重启动导致的问题很好理解,八成是因为docker-machine的VM是从关盘(boot2docker.iso)里启动的,我做的修改大部分都是在iso的内存盘里做的,并没保存到iso里,这是docker-machine的一个问题,有人提了建议了。

2016年6月23日星期四

原来fastboot boot custom.img可以无需刷机就以启动定制系统(以root)

知道的太晚了,对于解锁过的android机子,无需刷机就可以启动一个定制系统,同时可以用adb shell以root身份做任意操作。


至少这个有两个好处: 一是 刷机之前启动一下看看行不行,不行就不刷。 二是 有时仅仅为了临时以root做点事儿用这个就很方便, 启动后运行adb shell时就会发现已经是root身份了。不然呢, 即使刷了recovery分区,那么以后官方的更新来的时候会无法更新成功(因为官方更新会把查分文件交给recovery系统来做,需要官方的recovery系统)

这一切的前提是机子已经结果锁了(就是允许对bootloader进行一些操作,具体的方法查查各自的厂商是怎么搞的,有的很诡异,需要拨打一个奇怪的号码)。

2016年6月21日星期二

哈,"broker"这个词害死人,和“分解者”毫无关系,实际是和HUB差不多的意思

汗。。。 不过一定也有人以为和break + er有关系。 例如,Message Broker, RuntimeBroker.exe, ImeBroker.exe, Connection Broker, AtBroker.exe, 每次都很纳闷, 误以为是分解者,为啥需要分解呢。

有一次偶然看到ncat的Connection Brokering功能,还自我宣称是它最强大的功能,

就忍不住看了一下,发现哈哈误会啊,原来是那种转发,代理,广播,集线器差不多的意思。

2016年6月20日星期一

试了一个获取Android系统权限的工具Kingroot,运气不错,取得root了。

看起来做得很精致干净,谢谢!试验的机子是一款没有名气的牌子。2016/07/14补:后来发现有个更干净更管用的工具,名字多了个o,叫KingoRoot。

kingroot 这个公司看来搜罗了很多Android的漏洞,挨个试着破解,运气好的时候,就不用启动就成功了。也有人运气背的,不停的崩溃重启动。这东西谁能保证呢。
安装:显然不能从Google 的Play store里来,只能手动到那个网站下载app,我是下载手机版的,然后adb install ......apk。
然后运行KingRoot里的Root Auth功能,需要联网,它似乎会查询代码库,然后自动的进展,过几分钟,他说好了。
这好了的证据,一个是,我发现这个app无法像一般app那样拖拽到垃圾箱卸载了,app信息里的卸载按钮压根不存在。
然后我adb shell进去一看,/system/xbin/su新生成了!执行su一下就会有Kingroot画面弹出来问允不允许,就和SuperSU那个差不多。
然后随便干什么都行了,只是有一点, /system目录依然是mount成只读的,所以大概需要重新mount一下,我还没试,想来和以往的经验没什么不同。不管怎样,至少id成了0了,/data/data下可以乱搞了,各种不顺眼的process都可以kill了。
追加,试了,可以把/system搞成可写的了。方法google一下到处都有,摘要:
#   mount -o rw,remount /system



2016/06/28:
这个工具毕竟是特殊工具,用时要做好遇难的思想准备。KingRoot有Windows版(通过ADB连接手机进行破解),我在虚拟机里用了(感谢VirtualBox可以安装一个为了ADB的USB扩展: http://forum.xda-developers.com/showthread.php?t=570452),
KingRoot最终报错,但实际上/system/xbin/*su* 已经生成了,其实已经被root了,但是一执行就会爆“no ...ui ...”之类错误,这是手动把KingRoot的apk安装上去(不用执行)就可以了,他就会和su配成对来弹出一个对话框确认来自adb的root请求。
进一步发现,这个工具很可能受到腾讯安全公司的资助,因为它内部包含了Tencent的ADB Server和一个QQ关联的东西,通过工具看到这个ADB Server会往腾讯安全公司发数据。可能存在后门。
手机版的就没确认又无后门。

总之,用这个工具,要在虚拟机里用,并且手机要禁止网络,成功之后在把KingRoot的su换成标准的SuperSU之类的(可笑的是,这东西也不是开源的)。
2016/07/14补:后来发现有个更干净更管用的工具,名字多了个o,叫KingoRoot。这个工具没在Windows上安装什么乱七八糟的(安装时不要同意赞助软件就行了),运行时我观察了,没有起额外的进程,出了自带的adb。也顺利的root成功了,而且手机上安装的东西没有别的功能,只是管理root同意名单,叫做SuperUser,可能是基于一个开源的SuperUser改的。

N年来Mac的lsof总是hang,需要加-n选项。

从Mac OS X 10.7(Lion) 到 10.11.5(EI Capitan),无一例外的一旦执行lsof就导致命令行停顿在那儿了。不管是新机器还是旧机器,怪异的是,网上从来没有人有同样的问题。难道是我的机器特有的问题?
加个-n选项就好了。
lsof -n
原因:就是禁止网络端口号的转换显示就好了。
-n inhibits the conversion of network numbers to host names for network files.  Inhibiting conversion may make  lsof  run faster.  It is also useful when host name lookup is not working properly

2016年6月19日星期日

Android6邪门了,刷机神器TWRP居然在重启动之后消失了,可我没有重装系统啊。

在Nexus 7上遇到的怪事。顺便把TWRP的经验记下来。

我的Nexus 7 (2013 Mobile版),
升级到最新的Android 6.0.1(MOB30M)之后,
为了搞点研究,我再次手动把TWRP刷机神器安装上去了,其实不是完全刷机,只是把平时用不着的一个recovery分区给刷了而已,这样一来启动时就可以按住特殊件选择进入这个分区,什么都可以干了。一如既往的顺利。
先从https://dl.twrp.me/deb/twrp-3.0.2-0-deb.img.html下载到TWRP的映像文件,
然后按住Power+VolumeDown进入bootloader,
然后执行刷机命令
$ fastboot flash recovery /Users/q/Downloads/twrp-3.0.2-0-deb.img 
sending 'recovery' (8860 KB)...
OKAY [  0.285s]
writing 'recovery'...
OKAY [  0.660s]
finished. total time: 0.944s
然后,用Volume上下键选择Recovery mode,
按Power按钮执行选择。这就进入了TWRP的启动界面了。
进入这个TWRP的好处就是,可以任意操作任何文件了,Advanced里面有Mount工具,还有文件管理器工具。
鲜为人知的是,一旦进入了TWRP界面,就可以从PC这边用adb操作了,例如adb shell执行个命令什么的,改个文件什么的。
一切顺利,我用adb进去干了点无关的事儿。
然后我就想重启动到从Android 6.0.1里去,那自然是在TWRP的Reboot菜单里,选择System,就重启动了,
挺好的,到了正常的Android 6.0.1 。
诡异的事,过了一会儿我又想进入TWRP里干点事儿,
发现进去之后,换成了Android自己的Recovery mode的画面了
就是那个安卓太空舱图标,并且显示说"command not specified"(没有准备好系统更新用的文件)。
千真万确,我重新做了一次试验,发现一旦启动了正常的Android 6.0.1,他就会冲掉我刚刚刷过的Recovery分区的内容。
看来这是google故意保护自己的。

2016年6月17日星期五

Mac笔记本电脑 睡眠失败,硬关机之后,启动不了!还好折腾好了

启动时按住Command-S进入单用户模式,然后执行mount -uw把硬盘弄成可写模式,然后用rm -f /private/var/vm/sleepimage命令删除睡眠文件,总算起来了。

今天下载android源码(repo sync命令)时,我像往常一样把鼠标往左上角一挪让屏幕变黑,一般它会过一会儿就睡眠的,
结果过了好一会儿过来一看,电脑风扇呼呼叫,关机按钮按了也无法关闭,也无法启动,就那样黑屏幕气呼呼的。看起来是睡眠失败了,也怪我,命名在疯狂下载的时候不应该让它睡眠的。
过了好久,我不得不强行按住电源按钮10秒钟,强行关机了。
麻烦了,启动后最后一阶段它就自动关机了,再也启动不起来了。
难道运气这么背,碰到SSD闪存寿命到了吗,这次明显是睡眠不成功。
折腾了一阵子,把睡眠文件删除了以后就又起来了。具体的步骤就是
1. 启动式按住Command-S,这就会进入单用户模式,就一个命令行窗口,字特别小。
2. 更具命令行最后现实的提醒文,执行mount -uw命令把硬盘弄成可写模式
3. 然后用rm -f /private/var/vm/sleepimage命令删除睡眠文件
最后exit命令或者Ctrl+D退出,就可以了(居然它就接着启动了,也不用重启)