MacOS钥匙串授权特定应用程序获得密码

3 篇文章 0 订阅
2 篇文章 0 订阅

继续讨论MacOS钥匙串授权应用程序获得密码的那些安全隐患

MacOS钥匙串授权应用程序这个过程的安全隐患,在前一篇博文中讨论过了,参见MacOS钥匙串授权应用程序获得密码(命令行/Python/Objective-C/Swift)

从文章可以看到,授权过程的安全隐患比较隐蔽,在使用阶段的安全隐患更加隐蔽。

授权和使用的安全问题容易混淆,因为几乎所有的互联网网站都是按照登录用户隔离,从用户的操作过程来看,登录之后个人的数据限于自己访问,看不到其他用户的个人数据。此时,安全的关键环节就是授权(authorization),准确的说是鉴权(authentication)。

目前的操作系统也是类似的情况,当用户登录后,只能看到自己的个人文件夹中的文件,看不到其他用户的个人文件夹中的文件。即使有其他用户同时登录同一台电脑,也是都只能看到自己的个人文件夹中的文件,看不到其他用户的个人文件夹中的文件。以各种UNIX为代表的早期的多用户服务器都是如此隔离,只是早期的个人电脑操作系统没有这么区分。

因此,用户往往会忽视登录后的安全隐患,不过个人电脑除了数据安全之外,还有一个隐患就是恶意软件。登录后,相当于用户对所有自己启动的进程授权访问所有自己个人文件夹中的文件,即使像MacOS可以单独控制应用程序访问一些文件夹,但是控制的颗粒度比较粗,例如整个“文档”文件夹。像勒索软件,就可能会欺骗用户授权,然后操作这些文件。对于这种情况,MacOS对程序进行校验是一种防护措施,不过正如MacOS钥匙串授权应用程序获得密码(命令行/Python/Objective-C/Swift)中讨论的,对于像Python这种运行代码的程序而言,在一个场景中授权后,其他场景就可以任意调用了。

即便用户登录授权了,将个人文件夹中的数据暴露给进程,MacOS钥匙串中的密码仍旧需要授权访问,在MacOS钥匙串授权应用程序获得密码(命令行/Python/Objective-C/Swift)中讨论了钥匙串授权特定应用程序获得密码的一些安全隐患,下面以具体例子说明。

命令历史记录中的安全隐患

假设在钥匙串中保存了一台服务器的密码,名称为SurfacePro3VirtualBox,账户为IEUser。那么可以使用如下命令访问密码。

security find-generic-password -l "SurfacePro3VirtualBox" -a "IEUser" -gw

当没有授权security获得密码时,将出现授权提示框。

5c21e02db30c74fecc40f79b9c0dbdcf.png

运行后在命令历史记录中可以看到

history | tail

结果如下

10052  security find-generic-password -l "SurfacePro3VirtualBox" -a "IEUser" -gw

当用户授权了security获得密码后,查看密码信息可以看到。

056932656abda35e947adc871a732427.png

如果有恶意软件从命令历史记录中识别这样的命令,而且用户也授权了security获得密码,那么恶意软件就可以运行相同的命令获取密码。

使用专门的程序访问特定的密码

参照MacOS钥匙串授权应用程序获得密码(命令行/Python/Objective-C/Swift),专门编译程序访问密码可以一定程序避免这种识别。

编辑文件FindGenericPasswordSwiftSurfacePro3VirtualBox.swift

代码为

//
//  FindGenericPasswordSwiftSurfacePro3VirtualBox.swift
//  FindGenericPasswordSwiftSurfacePro3VirtualBox
//
//  Created by 胡争辉 on 2020/5/27.
//  Copyright © 2020 胡争辉. All rights reserved.
//

import Foundation

var service: String = "SurfacePro3VirtualBox"
var account: String = "IEUser"
var pwLength: UInt32 = 0
var pwData: UnsafeMutableRawPointer?
var item: SecKeychainItem?

var status: OSStatus = SecKeychainFindGenericPassword(
    nil,
    UInt32(service.lengthOfBytes(using: String.Encoding.utf8)),
    service.cString(using: String.Encoding.utf8),
    UInt32(account.lengthOfBytes(using: String.Encoding.utf8)),
    account.cString(using: String.Encoding.utf8),
    &pwLength,
    &pwData,
    &item)
if status == errSecSuccess {
    if let myData = pwData {
        let password: String? = String(bytesNoCopy: myData, length: Int(pwLength), encoding: String.Encoding.utf8, freeWhenDone: true)
        if let myPassword = password {
            print(myPassword)
        }
    }
}

简单调用API,把获取密码的参数-l "SurfacePro3VirtualBox" -a "IEUser"编译在代码中。

var service: String = "SurfacePro3VirtualBox"
var account: String = "IEUser"

因为只有一个文件,不需要启动Xcode编译,直接使用命令行编译即可。

swiftc -emit-executable ./FindGenericPasswordSwiftSurfacePro3VirtualBox.swift

运行编译后的程序

./FindGenericPasswordSwiftSurfacePro3VirtualBox

将出现授权提示框

6e98d55fa34edb3dda8fe144b339d628.png

可以看到在授权提示框中显示的是编译后的应用程序名称,不再是security。对FindGenericPasswordSwiftSurfacePro3VirtualBox授权后,查看密码信息可以看到FindGenericPasswordSwiftSurfacePro3VirtualBox程序名称。

6c643445bd58578dd3463c27d62a835d.png

此时如果使用security请求密码,将再次显示授权提示框,因为securityFindGenericPasswordSwiftSurfacePro3VirtualBox是不同的程序。

这个程序可以直接嵌入在使用密码的命令行中。

xfreerdp /u:'IEUser' /p:"$(FindGenericPasswordSwiftSurfacePro3VirtualBox)" /v:192.168.1.51:13389

运行后在命令历史记录中可以看到

history | tail
10088  xfreerdp /u:'IEUser' /p:"$(FindGenericPasswordSwiftSurfacePro3VirtualBox)" /v:192.168.1.51:13389

没有明显的security字样,不过恶意软件仍旧可以(当然,几乎没有这种可能)调用该程序。

修改运行程序的账户

为了避免被未知程序调用,一个直观的想法就是修改运行程序的账户,一般可以改为root,先设置可执行文件的所有者。

sudo chown root ./FindGenericPasswordSwiftSurfacePro3VirtualBox

然而还是能运行,查看可执行文件的信息。

stat -x ./FindGenericPasswordSwiftSurfacePro3VirtualBox

结果为

  File: "./FindGenericPasswordSwiftSurfacePro3VirtualBox"
  Size: 26900        FileType: Regular File
  Mode: (0755/-rwxr-xr-x)         Uid: (    0/    root)  Gid: (   20/   staff)
Device: 1,4   Inode: 104266797    Links: 1
Access: Wed May 27 18:29:20 2020
Modify: Wed May 27 18:29:03 2020
Change: Wed May 27 18:29:48 2020

所有者变了,但是Mode0755/-rwxr-xr-x,其他用户仍可执行。

接下来去掉可执行权限。

sudo chmod 744 ./FindGenericPasswordSwiftSurfacePro3VirtualBox

运行程序

./FindGenericPasswordSwiftSurfacePro3VirtualBox

显示没有权限

zsh: permission denied: ./FindGenericPasswordSwiftSurfacePro3VirtualBox

看上去解决了安全隐患,然而并非如此,这也就是MacOS钥匙串授权应用程序获得密码(命令行/Python/Objective-C/Swift)反复讨论的问题。

下面复制文件,复制文件不需要提权。

cp ./FindGenericPasswordSwiftSurfacePro3VirtualBox ./FindGenericPasswordSwiftSurfacePro3VirtualBox2

查看复制文件后的信息。

stat -x ./FindGenericPasswordSwiftSurfacePro3VirtualBox2

可以看到文件的所有者为当前用户,而且有可执行权限。

  File: "./FindGenericPasswordSwiftSurfacePro3VirtualBox2"
  Size: 26900        FileType: Regular File
  Mode: (0744/-rwxr--r--)         Uid: (  501/huzhenghui)  Gid: (   20/   staff)
Device: 1,4   Inode: 104267947    Links: 1
Access: Wed May 27 18:37:48 2020
Modify: Wed May 27 18:37:48 2020
Change: Wed May 27 18:37:49 2020 

运行命令,也不需要提权。

./FindGenericPasswordSwiftSurfacePro3VirtualBox2

如果之前用户授权原来的程序可以获得密码的话,那么复制后的命令也可以获得密码。

因此,不仅要去掉可执行权限,还需要去掉,读取权限。

sudo chmod 700 ./FindGenericPasswordSwiftSurfacePro3VirtualBox

查看可执行文件的信息。

stat -x ./FindGenericPasswordSwiftSurfacePro3VirtualBox

结果为

  File: "./FindGenericPasswordSwiftSurfacePro3VirtualBox"
  Size: 26900        FileType: Regular File
  Mode: (0700/-rwx------)         Uid: (    0/    root)  Gid: (   20/   staff)
Device: 1,4   Inode: 104266797    Links: 1
Access: Wed May 27 18:29:20 2020
Modify: Wed May 27 18:29:03 2020
Change: Wed May 27 18:42:08 2020

这样不仅不能执行,也不能复制,只有提权才能复制。

当然,直接嵌入在使用密码的命令行中时也需要提权。

xfreerdp /u:'IEUser' /p:"$(sudo FindGenericPasswordSwiftSurfacePro3VirtualBox)" /v:192.168.1.51:13389

如果仅从这个演示案例看,似乎是把钥匙串的授权操作变成了提权操作。在实际应用环境可以结合实际情况相应改进。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值