Re: delaying ptrace(2)'ing a process about to change credentials

2023-07-22 Thread Peter J. Philipp
On Sat, Jul 22, 2023 at 12:40:46PM -0700, Philip Guenther wrote:
> On Sat, 22 Jul 2023, p...@delphinusdns.org wrote:
> > >Synopsis:  delaying ptrace(2)'ing a process about to change credentials
> > >Category:  kernel
> > >Environment:
> > System  : OpenBSD 7.3
> > Details : OpenBSD 7.3 (GENERIC.MP) #2080: Sat Mar 25 14:20:25 MDT 
> > 2023
> >  
> > dera...@arm64.openbsd.org:/usr/src/sys/arch/arm64/compile/GENERIC.MP
> > 
> > Architecture: OpenBSD.arm64
> > Machine : arm64
> > >Description:
> > In many scenarios it's possible to attach to a root owned process
> > with ptrace(2) after it changes credentials to non-root.
> 
> Is this something you've managed to implement?
> 
> As is, I'm not seeing how this will happen:
>  * initially, the target process has ruid==0
>  * during the set*uid syscall, it holds the kernel lock across the update 
>of ps_ucred and setting PS_SUGID in its ps_flags
>  * the process doing ptrace(PT_ATTACH) holds the kernel lock across the 
>check you quoted, so it can't see target_ruid==my_ruid without also 
>seeing PS_SUGID set
> 
> 
> What am I missing?
> 
> 
> Philip Guenther

No I haven't implemented this.  Thanks for clarifying that the PS_SUGID flag
is set here.  I had thought that this is a flag that is associated with
setuid/setgid binaries (ie. 04000/02000 mode).

Is it possible for the attacking process to deliver a SIGABRT to the target
process without doing the ptrace() though?  It's a different thing though.
It also is highly unlikely due to the random pids, so I'll let it rest.

Thanks for clarifying Philip!

Best Regards,
-peter

-- 
Over thirty years experience on Unix-like Operating Systems starting with QNX.



Re: delaying ptrace(2)'ing a process about to change credentials

2023-07-22 Thread guenther
On Sat, 22 Jul 2023, p...@delphinusdns.org wrote:
> >Synopsis:delaying ptrace(2)'ing a process about to change credentials
> >Category:kernel
> >Environment:
>   System  : OpenBSD 7.3
>   Details : OpenBSD 7.3 (GENERIC.MP) #2080: Sat Mar 25 14:20:25 MDT 
> 2023
>
> dera...@arm64.openbsd.org:/usr/src/sys/arch/arm64/compile/GENERIC.MP
> 
>   Architecture: OpenBSD.arm64
>   Machine : arm64
> >Description:
>   In many scenarios it's possible to attach to a root owned process
> with ptrace(2) after it changes credentials to non-root.

Is this something you've managed to implement?

As is, I'm not seeing how this will happen:
 * initially, the target process has ruid==0
 * during the set*uid syscall, it holds the kernel lock across the update 
   of ps_ucred and setting PS_SUGID in its ps_flags
 * the process doing ptrace(PT_ATTACH) holds the kernel lock across the 
   check you quoted, so it can't see target_ruid==my_ruid without also 
   seeing PS_SUGID set


What am I missing?


Philip Guenther



delaying ptrace(2)'ing a process about to change credentials

2023-07-22 Thread pjp
>Synopsis:      delaying ptrace(2)'ing a process about to change credentials
>Category:  kernel
>Environment:
System  : OpenBSD 7.3
Details : OpenBSD 7.3 (GENERIC.MP) #2080: Sat Mar 25 14:20:25 MDT 
2023
 
dera...@arm64.openbsd.org:/usr/src/sys/arch/arm64/compile/GENERIC.MP

Architecture: OpenBSD.arm64
Machine : arm64
>Description:
In many scenarios it's possible to attach to a root owned process
with ptrace(2) after it changes credentials to non-root.  One would have to 
repeat the attach effort over and over (speed is what counts).  There may be 
data in a small window that is not wiped clean and the attacker wants this
data.  He or she stops the process with a ptrace attach and sends a coredump
signal.  Perhaps stalling EPERM returns with a timeout would be good, just
like the backup algorithm in login program, would prevent successful use of
this.
>How-To-Repeat:
Code reading this part in /sys/kern/sys_process.c

/*
 *  (5) it's not owned by you, or the last exec
 *  gave us setuid/setgid privs (unless
 *  you're root), or...
 * 
 *  [Note: once PS_SUGID or PS_SUGIDEXEC gets set in
 *  execve(), they stay set until the process does
 *  another execve().  Hence this prevents a setuid
 *  process which revokes its special privileges using
 *  setuid() from being traced.  This is good security.]
 */
if ((tr->ps_ucred->cr_ruid != p->p_ucred->cr_ruid ||
ISSET(tr->ps_flags, PS_SUGIDEXEC | PS_SUGID)) &&
(error = suser(p)) != 0)
goto fail;

at fail it returns immediately from the kernel.
>Fix:
A small time delay perhaps random too would work.


dmesg:
OpenBSD 7.3 (GENERIC.MP) #2080: Sat Mar 25 14:20:25 MDT 2023
dera...@arm64.openbsd.org:/usr/src/sys/arch/arm64/compile/GENERIC.MP
real mem  = 8432840704 (8042MB)
avail mem = 8139239424 (7762MB)
random: good seed from bootblocks
mainbus0 at root: ACPI
psci0 at mainbus0: PSCI 1.1, SMCCC 1.2
cpu0 at mainbus0 mpidr 0: ARM Cortex-A72 r0p3
cpu0: 48KB 64b/line 3-way L1 PIPT I-cache, 32KB 64b/line 2-way L1 D-cache
cpu0: 1024KB 64b/line 16-way L2 cache
cpu0: CRC32,ASID16
cpu1 at mainbus0 mpidr 1: ARM Cortex-A72 r0p3
cpu1: 48KB 64b/line 3-way L1 PIPT I-cache, 32KB 64b/line 2-way L1 D-cache
cpu1: 1024KB 64b/line 16-way L2 cache
cpu1: CRC32,ASID16
cpu2 at mainbus0 mpidr 2: ARM Cortex-A72 r0p3
cpu2: 48KB 64b/line 3-way L1 PIPT I-cache, 32KB 64b/line 2-way L1 D-cache
cpu2: 1024KB 64b/line 16-way L2 cache
cpu2: CRC32,ASID16
cpu3 at mainbus0 mpidr 3: ARM Cortex-A72 r0p3
cpu3: 48KB 64b/line 3-way L1 PIPT I-cache, 32KB 64b/line 2-way L1 D-cache
cpu3: 1024KB 64b/line 16-way L2 cache
cpu3: CRC32,ASID16
efi0 at mainbus0: UEFI 2.7
efi0: https://github.com/pftf/RPi4 rev 0x1
smbios0 at efi0: SMBIOS 3.3.0
smbios0: vendor https://github.com/pftf/RPi4 version "UEFI Firmware v1.21" date 
11/13/2020
smbios0: Raspberry Pi Foundation Raspberry Pi 4 Model B
apm0 at mainbus0
ampintc0 at mainbus0 nirq 256, ncpu 4 ipi: 0, 1, 2: "interrupt-controller"
agtimer0 at mainbus0: 54000 kHz
acpi0 at mainbus0: ACPI 6.3
acpi0: sleep states
acpi0: tables DSDT FACP CSRT DBG2 GTDT IORT APIC PPTT BGRT
acpi0: wakeup devices
acpiiort0 at acpi0
"BCM2849" at acpi0 not configured
"BCM2835" at acpi0 not configured
"BCM2854" at acpi0 not configured
"ACPI0004" at acpi0 not configured
xhci0 at acpi0 XHC0 addr 0x6/0x1000 irq 175, xHCI 1.0
usb0 at xhci0: USB revision 3.0
uhub0 at usb0 configuration 1 interface 0 "Generic xHCI root hub" rev 3.00/1.00 
addr 1
"ACPI0007" at acpi0 not configured
"ACPI0007" at acpi0 not configured
"ACPI0007" at acpi0 not configured
"ACPI0007" at acpi0 not configured
"ACPI0004" at acpi0 not configured
"BCM2848" at acpi0 not configured
"BCM2850" at acpi0 not configured
"BCM2856" at acpi0 not configured
"BCM2845" at acpi0 not configured
"BCM2841" at acpi0 not configured
"BCM2841" at acpi0 not configured
"BCM2838" at acpi0 not configured
"BCM2839" at acpi0 not configured
"BCM2844" at acpi0 not configured
pluart0 at acpi0 URT0 addr 0xfe201000/0x1000 irq 153
"BCM2836" at acpi0 not configured
"BCM2EA6" at acpi0 not configured
"MSFT8000" at acpi0 not configured
sdhc0 at acpi0 SDC1 addr 0xfe30/0x100 irq 158
sdhc0: base clock frequency unknown
"BCM2855" at acpi0 not configured
bse0 at acpi0 ETH0 addr 0xfd58/0x1 irq 189: address dc:a6:32:cc:db:a7
brgphy0 at bse0 phy 1: BCM54210E 10/100/1000baseT PHY, rev. 2
"PNP0C06&q