惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Cisco Talos Blog
Cisco Talos Blog
V
V2EX
C
Check Point Blog
GbyAI
GbyAI
D
Docker
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
B
Blog RSS Feed
H
Hackread – Cybersecurity News, Data Breaches, AI and More
N
Netflix TechBlog - Medium
T
Troy Hunt's Blog
博客园 - Franky
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
Microsoft Security Blog
Microsoft Security Blog
P
Privacy & Cybersecurity Law Blog
WordPress大学
WordPress大学
The Cloudflare Blog
S
SegmentFault 最新的问题
Latest news
Latest news
Microsoft Azure Blog
Microsoft Azure Blog
P
Proofpoint News Feed
I
InfoQ
博客园 - 【当耐特】
NISL@THU
NISL@THU
A
About on SuperTechFans
T
Tailwind CSS Blog
酷 壳 – CoolShell
酷 壳 – CoolShell
The Hacker News
The Hacker News
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
Scott Helme
Scott Helme
雷峰网
雷峰网
C
CXSECURITY Database RSS Feed - CXSecurity.com
Security Latest
Security Latest
V
Vulnerabilities – Threatpost
Security Archives - TechRepublic
Security Archives - TechRepublic
A
Arctic Wolf
Hacker News: Ask HN
Hacker News: Ask HN
N
News and Events Feed by Topic
IT之家
IT之家
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
aimingoo的专栏
aimingoo的专栏
T
Threat Research - Cisco Blogs
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
阮一峰的网络日志
阮一峰的网络日志
SecWiki News
SecWiki News
大猫的无限游戏
大猫的无限游戏
S
Security Affairs
The Register - Security
The Register - Security
www.infosecurity-magazine.com
www.infosecurity-magazine.com
L
LINUX DO - 热门话题
T
Tor Project blog

Black Hills Information Security, Inc.

Bad Habits: An ANTISOC Operation Same Problem, Different Angles: When Red Team and Blue Team Actually Talk to Each Other How to Identify and Exploit New Vulnerabilities Swapper – A Pure Regex Match/Replace Burp Extension A Practical Guide to BloodHound Data Collection Network Engineering Basics Signed, Trusted, and Abused: Proxy Execution via WebView2 Getting Started In Pentesting – Advice From The BHIS Pentest Lead Cloud Security: Tips and Resources for Securing the Cloud Lessons From A Chatbot Incident How to Lead Effective Tabletops Understanding GRC: How to Navigate Risks and Compliance Standards The “P” in PAM is for Persistence: Linux Persistence Technique Malware Analysis: How to Analyze and Understand Malware OSINT: How to Find, Use, and Control Open-Source Intelligence What to Do with Your First Home Lab When the SOC Goes to Deadwood: A Night to Remember Social Engineering and Microsoft SSPR: The Road to Pwnage is Paved with Good Intentions Common Cyber Threats Finding the Right Penetration Testing Company Deceptive-Auditing: An Active Directory Honeypots Tool The Curious Case of the Comburglar How to Set Smart Goals (That Actually Work For You) Inside the BHIS SOC: A Conversation with Hayden Covington Abusing Delegation with Impacket (Part 3): Resource-Based Constrained Delegation Why You Got Hacked – 2025 Super Edition Abusing Delegation with Impacket (Part 2): Constrained Delegation Abusing Delegation with Impacket (Part 1): Unconstrained Delegation GoSpoof – Turning Attacks into Intel Model Context Protocol (MCP) Bypassing WAFs Using Oversized Requests Getting Started with AI Hacking Part 2: Prompt Injection Wrangling Windows Event Logs with Hayabusa & SOF-ELK (Part 2) DomCat: A Domain Categorization Tool Wrangling Windows Event Logs with Hayabusa & SOF-ELK (Part 1) Microsoft Store and WinGet: Security Risks for Corporate Environments Default Web Content MailFail Commonly Abused Administrative Utilities: A Hidden Risk to Enterprise Security Stop Spoofing Yourself! Disabling M365 Direct Send Bypassing CSP with JSONP: Introducing JSONPeek and CSP B Gone Offensive Tooling Cheatsheets: An Infosec Survival Guide Resource DNS Triage Cheatsheet GraphRunner Cheatsheet Burp Suite Cheatsheet Impacket Cheatsheet Wireshark Cheatsheet Hashcat Cheatsheet EyeWitness Cheatsheet Nmap Cheatsheet Netcat (nc) Cheatsheet Hunt for Weak Spots in Your Wireless Network with Airodump-ng from the Aircrack-ng Suite Detecting ADCS Privilege Escalation Vulnerability Scanning with Nmap Getting Started with NetExec: Streamlining Network Discovery and Access How to Use Dirsearch Augmenting Penetration Testing Methodology with Artificial Intelligence – Part 3: Arcanum Cyber Security Bot How to Design and Execute Effective Social Engineering Attacks by Phone Abusing S4U2Self for Active Directory Pivoting Why Use a Macro Pad? Espanso: Text Replacement, the Easy Way Caging Copilot: Lessons Learned in LLM Security Augmenting Penetration Testing Methodology with Artificial Intelligence – Part 2: Copilot Augmenting Penetration Testing Methodology with Artificial Intelligence – Part 1: Burpference Intercepting Traffic for Mobile Applications that Bypass the System Proxy How to Root Android Phones Communicating Security to the C-Suite: A Strategic Approach Offline Memory Forensics With Volatility Getting Started with AI Hacking: Part 1 Go-Spoof: A Tool for Cyber Deception How to Test Adversary-in-the-Middle Without Hacking Tools Canary in the Code: Alert()-ing on XSS Exploits How to Hack Wi-Fi with No Wi-Fi Why Your Org Needs a Penetration Test Program Burp Suite Extension: Copy For Light at the End of the Dark Web Wi-Fi Forge: Practice Wi-Fi Security Without Hardware Avoiding Dirty RAGs: Retrieval-Augmented Generation with Ollama and LangChain Gone Phishing: Installing GoPhish and Creating a Campaign 5 Things We Are Going to Continue to Ignore in 2025 John Strand’s 5 Phase Plan For Starting in Computer Security Questions From a Beginner Threat Hunter GRC for Security Managers: From Checklists to Influence AI Large Language Models and Supervised Fine Tuning Attack Tactics 9: Shadow Creds for PrivEsc w/ Kent & Jordan One Active Directory Account Can Be Your Best Early Warning Introduction to Zeek Log Analysis Indecent Exposure: Your Secrets are Showing Creating Burp Extensions: A Beginner’s Guide Pitting AI Against AI: Using PyRIT to Assess Large Language Models (LLMs) The Top Ten List of Why You Got Hacked This Year (2023/2024) ICS Hard Knocks: Mitigations to Scenarios Found in ICS/OT Backdoors & Breaches Intro to Data Analytics Using SQL Finding Access Control Vulnerabilities with Autorize The Detection Engineering Process Cyber Risk Lessons We Can Learn From Hurricane Preparedness Intro to Desktop Application Testing Methodology What Is Penetration Testing? Adversary in the Middle (AitM): Post-Exploitation Pentesting, Threat Hunting, and SOC: An Overview
Auditd Field Spoofing: Now You Auditd Me, Now You Auditdon’t
BHIS · 2023-05-11 · via Black Hills Information Security, Inc.

moth //

Introduction 

One fateful night in June of 2022, Ethan sent a message to the crew: “Anyone know ways to fool Auditd on Linux? I’m trying to figure out how to change the auid (audit user id) field. This field remains the same even if you use su or sudo (there are other user id fields that track these changes).” 

Ethan also helpfully sent a reference link to describe what he was looking at. 

Now, do I know Auditd well enough to warrant looking into this myself? No. Am I a big enough fan of Linux (and a big enough fool) to throw my hat in the ring anyway? Most definitely. 

So, what was Ethan’s original goal here? In short, the SOC team was working on building a “canary” script for spoofing a given auid as well as determining whether the auid value is a reliable source of truth when writing detections for Linux systems. If the auid field keeps track of users as they switch users (su) or run commands with elevated permissions (sudo), the ability to change this field could be potentially lucrative to attackers. 

Primer

With that introduction out of the way, we’re ready to start researching. First things first, what is the auid field, how is it accessed, and — crucially — how can it be modified?  

From reading the documentation link that Ethan posted, it would seem that the auid field is derived from the uid (user identifier) field and is meant to remain consistent across a process’s children, even if the uid of the child process is modified. For context, a uid of 0 represents the root user, uid values under 1000 are typically system accounts, and uid values from 1000 onward represent standard user accounts. The etc/passwd file contains the mapping between uids and usernames. This information can also be viewed with the getent passwd command.

Now, we get to do something that I Iove having an excuse to do: looking at kernel code. To do so, I’ll be using elixir.bootlin.com to browse the kernel source code. First, let’s look for where the auid field is used, what initially sets it, and where it may be changed. From the search results, the auid field is logged starting on line 1600 (as of kernel version 6.0.19) of /kernel/audit.c. The auid field is retrieved with a function call, audit_getloginuid(current)

Location of “auid” Field in Audit Logging

Now that we know how the auid field is retrieved by logging services, let’s look for the audit_get_loginuid function. The function is defined and implemented in the audit header file, at /include/linux/audit.h. From the function implementation starting on line 199, the function accepts a pointer to a task structure (task_struct) and returns a field called loginuid from it. 

Contents of “audit_get_loginuid” Function

We’re getting closer to the bottom now, so it’s time to find that field in the task structure definition. The task structure can be found in /include/linux/sched.h and is used to contain process information. The loginuid field is defined as a structure field, but only if CONFIG_AUDIT is defined, which makes sense — we don’t need the loginuid field (or related fields) if the system isn’t configured for auditing. 

Audit-Specific “loginuid” Task Structure Field

From here, I began formulating ways that we could write to this field. Kernel patching and even a loadable kernel module felt a little too hardcore given the context of this task, so I figured it was worth trying to tackle the problem from userspace. Unfortunately, that marks the end of the kernel source spelunking portion of this adventure. Please remember to fill out the tour guide review survey. 

After gaining some insight into the auid field, I set out to find a way to modify it. I eventually landed on a GitHub commit detailing how (and under what conditions) the field can be modified. 

Auditd Commit Detailing Login UID Mutability

Putting everything together from that commit, the current process’s auid field should be mutable via /proc/self/loginuid as long as permissions are valid, the CAP_AUDIT_CONTROL Linux capability is set, and the AUDIT_FEATURE_LOGINUID_IMMUTABLE and AUDIT_FEATURE_ONLY_UNSET_LOGINUID kernel configuration options are not set. With all of that information, we should be ready to start tackling the problem. 

Now You Auditd Me 

The initial kernel exploration was illuminating, but overall lacking in context. To get some context, let’s take a look at how audit entries are logged. Note that the contents shown below have been slightly modified to omit unrelated surrounding log entries in order to make the output cleaner and easier to follow. 

Log file information can be found in /var/log/audit/audit.log (at least on RHEL systems). I first run sudo ls followed by a command to print the last six lines from the log file. Note that the executable logged is /usr/bin/sudo and the relevant command is ls, which makes sense given what we just ran. 

Sudo Usage Logged with Consistent UID and AUID 

So now, what gets logged when we run sudo su? Well, as we might expect, the audit log shows an entry for the command execution. A few entries down, we see that the uid field has updated to 0 (root), but the auid field remains the same as the original user. 

Sudo Usage Logged with Changed UID and Consistent AUID 

And here, we arrive at the task: A simple program that, assuming we have sudo permissions, allows us to manually set the auid field via the /proc/$pid/loginuid pseudofile. 

Now You Auditdon’t 

Now that we have our task well and truly researched, let’s start with the easy ideas first. If we can write to the pseudofile, do we even need to program anything? As much as I love throwing code at a problem, this wasn’t my problem to begin with, so I’ll be proceeding with a bit of care (for once). 

The Easy Way? 

First, what happens if we write to the file directly? We should have requisite permissions to write to our own process, right? 

Write Operation Not Permitted

Apparently not. Granted this isn’t a permission denied error, which would indicate an access error. Let’s shelve that for now. What if we echo the new value and then write that content to the file as sudo

Unsuccessful Write Attempt

No error that time, but still no dice. 

Yet Another Unsuccessful Write Attempt 

Quick sidebar: You might be wondering if /proc/self is reliable when different processes are spawned per most commands and per user context when using sudo. I can say that, from testing, the behavior was the same when using the specific PID of the current terminal. 

What’s even more interesting is that the root user can modify its own loginuid files, but not those owned by other user processes. Ethan also confirmed that attempting to give cat or tee the CAP_AUDIT_CONTROL capability did not work any better. All of this indicates that I’m going to get to throw code at the problem after all. 

With that, it’s finally time to start slinging some code. Here’s a fun “drinking game” for this next section: take a little tiny sip of water every time you read the words “capability” or “capabilities” to make sure you stay well hydrated… 

The Hard Fun Way! 

Quick aside before we get coding: You need to make sure that the libcap-dev (Debian) or libcap-devel (RHEL) package is installed on your system before continuing, otherwise a requisite header file will not exist. 

Outside of some preliminary argument validation, the code I came up with largely boils down to the following five primary components, several of which are mainly just error detection and short-circuiting if something goes wonky on us: 

  1. Get process capabilities, make sure CAP_AUDIT_CONTROL is supported. 
  1. Set process capabilities to enable the CAP_AUDIT_CONTROL capability. 
  1. Write new auid field to /proc/self/loginuid pseudofile. 
  1. Verify that new auid field was written properly. 
  1. Spawn shell. 

Given that we require specific capabilities to modify the auid field, the first step is to retrieve our process capabilities and also determine whether the CAP_AUDIT_CONTROL capability is enabled in our process. How do we accomplish this? Without an immediate familiarity of programming with capabilities, I ran apropos capability in my terminal and received a handful of results. 

Searching for Relevant Manual Pages 

Checking the manual page for one of the results, it appears that most of them point to the header file sys/capabilities.h. The “see also” section of the page for cap_clear includes a reference to cap_get_proc, which is the function I ultimately ended up using to retrieve the process capabilities. It is crucial to note here that including sys/capabilities.h requires that the code be compiled with -lcaps so it links against the capabilities library. 

Now that we know what to use to retrieve our process capabilities, it would be useful to check whether the CAP_AUDIT_CONTROL capability is supported on my system. Conveniently, the manual page for cap_get_proc includes a macro predictably named CAP_IS_SUPPORTED. The manual page describes it as follows: “CAP_IS_SUPPORTED(cap_value_t cap) is provided that evaluates to true (1) if the system supports the specified capability, cap. If the system does not support the capability, this function returns 0.” 

With those pieces of information at our disposal, we can construct the first main chunk of the program: store the process capabilities in a variable named caps and check for CAP_AUDIT_CONTROL support. 

Segment 1 – Capability Retrieval and Enumeration

At this point in the code, we now have good confidence that the required capability is at least supported on the system. The next step involves us creating a new capability list containing CAP_AUDIT_CONTROL, using the cap_set_flag() function to enable it, and then writing the updated capabilities to the process using the cap_set_proc() function. 

Segment 2 – Capability Construction and Writing 

With our capabilities written, it’s time to get and write the new auid value to /proc/self/loginuid. To do so, we use standard file I/O functions to open the file and write our first and only command argument to the file. 

Segment 3 – File Opening and New AUID Writing 

You may have noticed that we didn’t close the file used in the previous segment. That’s because the next segment involves reading back the new value from the file to make sure things were written successfully. This step isn’t strictly required but given how much trouble we were running into trying to modify the value without code, I figured better safe than sorry. Once we validate that the value was properly set, we close the file and release any memory allocated for the caps variable using the cap_free() function. 

Segment 4 – File Content Validation and Memory Management 

Finally, we spawn a simple /bin/bash shell using the execve() function. Nothing glamorous or especially safe, but it gets the job done. 

Segment 5 – Shell Spawning

That’s pretty much all there is to the code. You get all that? Good. 

Demo 

After compiling the code with gcc -lcaps capybara.c -o capybara, we can see that it’s working by using it like so: 

Successful Modification of AUID Field 

Alright, that’s fine and all, but updating the number as seen by a process is only the first half of our task here. What we’re really here to do is change the value that gets logged to our audit file! 

After running the code one more time and running sudo whoami (for demonstration purposes), we can then output some of the contents of /var/log/audit/audit.log, with a cheeky little Perl regex for added flavor. Looking at the first of two highlighted audit log lines, we can see something that I failed to notice during my initial development of this with Ethan: There’s an old-auid field! That field only appears to be present when the field is modified. On the second highlighted log file entry, we see that the whoami command was executed with the “correct” auid value of “12345”, with no mention of the old auid value. 

Parsed Auditd Log Entries Showing “old-auid” Field 

So, there’s a pathway available for analysts to detect Auditd tomfoolery: Check for a changing old-auid field to keep track of user IDs as they may be changing. That said, Ethan later mentioned to me that LOGIN events weren’t being surfaced in this particular environment’s SIEM, adding another wrinkle to the issue of log visibility. 

Conclusion 

I suppose we should start wrapping this up with some parting thoughts. 

In terms of detection, make sure your SIEM is receiving LOGIN events from Auditd so you can be aware of any tampering. In terms of possible remediation, note that the GitHub commit shown earlier also discusses configuration options named AUDIT_FEATURE_LOGINUID_IMMUTABLE and AUDIT_FEATURE_ONLY_UNSET_LOGINUID which prevent overwriting and unsetting of the auid field respectively. From an enterprise Linux standpoint, I would imagine those would be good configurations to enable. That being said, I’ve looked through configuration options on kernel versions as recent as Linux 6.1.3, and I was unable to find either of those configuration options in a cursory search. 

Apparently, there are auditctl commands to set kernel immutability (-e 2) and regular loginuid immutability (–login-immutability), but I have so far been unsuccessful in getting either command to do anything to prevent this technique from working. 

All told, this work doesn’t represent much of a groundbreaking discovery but seemed to yield satisfactory results for Ethan and the rest of the SOC team. What’s more, this should serve as a reason to be cautious when writing detections around the Auditd facility. Depending on how a given organization writes detections or monitors the audit information, an attacker could potentially leverage a similar strategy to effectively disappear from view in environments that aren’t equipped to detect a changing auid value. 



Ready to learn more?

Level up your skills with affordable classes from Antisyphon!

Pay-What-You-Can Training

Available live/virtual and on-demand