Trustwave SpiderLabs Exposes Unique Cybersecurity Threats in the Public Sector. Learn More

Trustwave SpiderLabs Exposes Unique Cybersecurity Threats in the Public Sector. Learn More

Managed Detection & Response

Eliminate active threats with 24/7 threat detection, investigation, and response.

Co-Managed SOC (SIEM)

Maximize your SIEM investment, stop alert fatigue, and enhance your team with hybrid security operations support.

Advisory & Diagnostics

Advance your cybersecurity program and get expert guidance where you need it most.

Penetration Testing

Test your physical locations and IT infrastructure to shore up weaknesses before exploitation.

Database Security

Prevent unauthorized access and exceed compliance requirements.

Email Security

Stop email threats others miss and secure your organization against the #1 ransomware attack vector.

Digital Forensics & Incident Response

Prepare for the inevitable with 24/7 global breach response in-region and available on-site.

Firewall & Technology Management

Mitigate risk of a cyberattack with 24/7 incident and health monitoring and the latest threat intelligence.

Offensive Security
Solutions to maximize your security ROI
Microsoft Exchange Server Attacks
Stay protected against emerging threats
Rapidly Secure New Environments
Security for rapid response situations
Securing the Cloud
Safely navigate and stay protected
Securing the IoT Landscape
Test, monitor and secure network objects
Why Trustwave
About Us
Awards and Accolades
Trustwave SpiderLabs Team
Trustwave Fusion Security Operations Platform
Trustwave Security Colony
Technology Alliance Partners
Key alliances who align and support our ecosystem of security offerings
Trustwave PartnerOne Program
Join forces with Trustwave to protect against the most advance cybersecurity threats
SpiderLabs Blog

CVE-2023-29383: Abusing Linux chfn to Misrepresent /etc/passwd

A little bit of background for those not familiar with chfn…

“chfn (change finger) is used to change your finger information. This information is stored in the /etc/passwd file and is displayed by the finger program. The Linux finger command will display four pieces of information that can be changed by chfn; your real name, your work room and phone, and your home phone.” (from

Now for some history. Two years ago, I picked out chfn as a candidate to be reviewed for security bugs. Why chfn I hear you ask? (Thanks for asking.) It is one of a small number of Set owner User ID (SUID) programs loaded with Linux which means it runs with the permissions of the ‘root’ user regardless of the user who executes it, for it needs to modify the /etc/passwd file to do its job. A vulnerability in such a program would mean local privilege escalation, for any command or action we get to inject gets executed in the context of ‘root’. As a normal user, we wouldn’t be able to directly save any changes made to /etc/passwd, but via chfn we can, in a controlled and restricted way – well that’s the plan.

We can change our room number to be 41414141” by either using chfn interactively or using it from the command line with parameters and values. For example: chfn -r 41414141

After executing this command, if we then look at /etc/passwd it will show the following:


We could also change our full name (-f), home phone (-h) and work phone (-w) with other parameters which would change other details within those comma separators, which are referred to as General Electric Computer Operating System (GECOS) fields.

Keep the above in mind while we look under the hood.

I found chfn is part of two Linux packages; util-linux and shadow. In Ubuntu and other Debian-based Linux implementations it is the shadow package which is responsible for the resultant chfn binary and is vulnerable to what I’m about to discuss.

Unwrapping this package and looking at /shadow-4.5/src/chfn.c you’ll find the following treasure inside the check_fields function, namely on lines 585 to 592 with regards to setting the room number field:


We can see that the user input to “roomno” is sent to the valid_field function together with some characters. We can assume that this is likely a blacklist of characters, but let’s go down the valid_field rabbit hole just to confirm.

Digging into /shadow-4.5/lib/fields.c, at the valid_field function, on lines 52 to 81:


So, our assumptions were correct. Each character we provide to “roomno” (or any other GECOS field) is compared against a list of illegal characters and if there is a match then -1 is returned back to “err” which exits out of the chfn program with the invalid room number message.

Two things stick out to me here. First, a bunch of things are not being mentioned in that illegal list of characters (blacklists are not great, who knew?!) and secondly, the handling of non-printable characters and the “1” being returned for them along with a non-exiting warning message – importantly, chfn does not quit. If we look back at the check_fields and valid_field functions, chfn only quits out if “err” is less than 0 - we die, we do not collect $200 and we go directly to jail. But if “err” is greater than 0 we get that red rope unclipped from the silver pole at the front of the chfn club and walked straight on through to our table. Good times.


With this knowledge, I pulled ‘echo’ (with -e) out of the toolbox and started to feed control characters into the roomno (-r) parameter of chfn to see what was going down because these don’t feature in that blacklist. I had lots of fun (I’m really great at parties), but the main takeaway is that the control character CARRIAGE RETURN represented by \r or \xD (in hexadecimal) gave the biggest impact. Let me show you the bottom of /etc/passwd before any madness goes on. The ubuntu user is normal, all good - nothing to see here.


Figure 1: Contents of /etc/password before injection

However, we make the injection with the \r control character into the roomno parameter of our user (ubuntu) and then we view the /etc/passwd file again. WHAAAAAA? Where we go?! roominjection has entered the building!


Figure 2: Modified contents of /etc/password after injection

Fast forward some hours and minutes later and spoiler alert here - I was not able to circumvent the “\n” from the illegal list. The ultimate goal/dream here would have been to start a new line and add another root level user, but I was denied.


I thought, well that was cool. I was curious though, was this blacklist always there? Back to the future we go - 2006 to be exact, to shadow-4.0.13 and guess what? …the “\n” in the blacklist was missing! However, the “:” was still present which stops any new user adding fun as we need to make use of this delimiter. This also applied to full name, home and work phone number, etc. but for illustrative purposes I have just shown the roomno as an example, which is what we’ve been targeting throughout.

chfn.c (in Ubuntu) from back in the day in 2006 (shadow-4.0.13) with “\n” missing:


I went back a further two years to 2004 (shadow-4.0.3) and that “:” is still messing up our plans for adding new users:


It was at this point of digging that I came across this bad boy from 2005 in SuSE Linux; CVE-2005-3503, a local privilege escalation in chfn! ( The exploit happily uses both “\n” and “:” to add a new root user, exactly what I set out to do at the start of this adventure.

I left the research there, poured myself another cup of tea and got on with my life.

Two years went by and one morning while I was eating my toast, I saw a tweet from @trailofbits about exploiting a logic bug in a SUID program. Interesting, tell me more… and they do, with a blog post. (

It’s about chfn of course! This time chfn is loading (and loading badly I might add) an environment variable, resulting in an arbitrary read access bug. This blog post gave me the kick I needed to revisit my old friend chfn.

Two years older/wiser, I picked up my old research in chfn to try a few more things. Still no success in weaponizing it (e.g., the holy grail of adding a new user, 2005 SuSE style) but I stand back and try to think about how it can be abused in other ways. In a way it isn’t really an issue, but in another it is a little bit concerning, concerning that I’m able to mangle the /etc/passwd file and misrepresent it to an administrator perhaps. This made me think of red teaming and how we put together pretexts in our phishing tests to convince victims to click on links or do things for us. If I can’t use this to add a new user, can I use it to fake adding a new user? Stay with me on this.

The majority of work I’ve done over the last two decades has been application security testing, the kind of testing where we need to encode all the things, double encode, find alternative representations of characters, etc. in order to circumvent input validation rules, evade WAFs and ultimately get that alert box with the number 1 popping up. This got me thinking. I can’t put in an actual colon due to that blacklist in chfn, but we got a free pass with non-printables. We can use the CARRIAGE RETURN control character “\r” to start the line again and then be a bit creative and use the Unicode character “\ua789” to get as close a match to a colon as possible, all while injecting into the roomno parameter.

And that’s exactly what I did next.

Spot the difference?


I wanted to support such a pretext where we’ve managed to compromise a local account on the machine, but that we want to pretend to the administrator that we actually have a root privileged user account, so we tell them to check the /etc/passwd file and see for themselves. Maybe this being believed would then invoke another action like them having to log into another box/invoke an IR process which we have other tools waiting for this – Responder, Mimikatz, etc. to grab hashes, tokens, etc. something like that.

Attacker making the injection: 


Administrator does a ‘cat /etc/passwd’:


Here are some screenshots also so you can get a sense of believability of the colon replacement on the screen.

The /etc/passwd before:


Figure 3: /etc/passwd before injection

The injection with the subsequent “hacked” account at the bottom of /etc/passwd, with ‘root’ privileges:


Figure 4: /etc/passwd after injection of the ‘hacked’ root user

That brings us to the end of our story, well nearly.

Remember at the start where I said chfn can be found in util-linux and shadow packages? Well strangely enough, the util-linux version blocks control characters via “iscntrl” in ch-common.c. In addition, it adds the “ character into the blacklist, so perhaps there is a story and some research behind that one too?

From util-linux-2.37.2/login-utils/ch-common.c (used by chfn.c), lines 17 to 34:


Prior to this blog post being published, I got in touch with the shadow package maintainers and showed them the proof of concept. I then followed up with a pull request on GitHub with the following commit which they have now merged into the main shadow repository.


Now, if control characters are detected then -1 is returned to err (quitting out of chfn), treating them the same as the illegal characters. This little bug has been assigned CVE-2023-29383.

Thanks for reading!


TWSL2023-004: Improper input validation in shadow-utils package utility chfn

Latest SpiderLabs Blogs

2024 Public Sector Threat Landscape: Trustwave Threat Intelligence Briefing and Mitigation Strategies

Trustwave SpiderLabs’ 2024 Public Sector Threat Landscape: Trustwave Threat Intelligence Briefing and Mitigation Strategies report details the security issues facing public sector security teams as...

Read More

How to Create the Asset Inventory You Probably Don't Have

This is Part 12 in my ongoing project to cover 30 cybersecurity topics in 30 weekly blog posts. The full series can be found here.

Read More

Guardians of the Gateway: Identity and Access Management Best Practices

This is Part 10 in my ongoing project to cover 30 cybersecurity topics in 30 weekly blog posts. The full series can be found here.

Read More