Skip to main content

13.6 Credentialed scanning, and why it looks like an attack

The scan in 13.5 stood outside your machines and guessed from what it could see. This lesson gives it a key to the front door, and the difference in what it can tell you is the largest single jump in this module.

It is also the lesson where Module 12 comes back and bites you, on purpose.

What changes​

An unauthenticated scan sees listening services and version banners. A credentialed scan logs in and reads the machine's own package database, its configuration files, its running services.

That turns the network-surface scan from lesson 13.1 into something much closer to the accurate package scan you ran in 13.2, except across every machine at once and including configuration.

Three concrete consequences:

  • Far more findings, and better ones. It sees the vulnerable library that nothing exposes to the network, which the outside view is blind to.
  • Far fewer false positives. It reads the installed version rather than inferring it from a banner, so the backported-fix problem from 13.5 mostly disappears.
  • Configuration findings appear, the third scan type from lesson 13.1, because now it can read sshd_config rather than guess from a handshake.

This is why, in the industry, "did you run a credentialed scan?" is the first question anybody asks about a clean report. An uncredentialed clean report often means the scanner could not see anything, which is not the same as there being nothing to see.

The account you scan with​

Here is where a principle you have practised since lesson 5.6 gets tested, because credentialed scanning creates real pressure to do the wrong thing.

The scanner works better the more it can read. The path of least resistance is to hand it Domain Admin and never think about it again. Plenty of real organisations have done exactly that, and it is how a scanner becomes the most dangerous account in the building.

Think about what you would be creating: a set of credentials with total control over every machine, stored in a web application, used automatically on a schedule, logging into every host in the estate in sequence. If an attacker gets that one account, they do not need to move laterally. They have already been given everything.

The right shape is a dedicated account with read access, used for nothing else, whose privileges you can describe in a sentence.

For your lab, create one on UBNT01 rather than reusing yours:

# A dedicated scanning account. --disabled-password means no
# password login; the scanner will use an SSH key.
sudo adduser --disabled-password --gecos "" scanner

How you know it worked:

# The account exists and has a home directory.
id scanner
ls -ld /home/scanner

On the privilege question, be deliberate. A read-only account misses some checks that need root. The professional answer is usually a narrowly scoped sudo rule for specific read commands rather than full sudo, and the honest lab answer is that you should know which you chose and why. Write your choice in your journal with one sentence of reasoning; that sentence is the thing an auditor asks for in Module 16.

Least privilege

This is the same trade as the wireshark group in lesson 4.7 and the two accounts in 5.6, arriving at a bigger scale.

The question has not changed: what could this account do if somebody else were driving it? For a scanner with Domain Admin, the answer is "everything, from a machine that is allowed to talk to everything, on a schedule nobody watches."

That is not a hypothetical objection. It is one of the standard paths in real intrusions, precisely because the credentials are powerful, stored, and boring enough that nobody reviews them.

Now run it, and watch your own alarm go off​

Configure the credential in Greenbone (Configuration > Credentials), attach it to your target, and run the task again.

Before you do, open your Wazuh dashboard from lesson 12.9 next to it.

You are about to watch a single account log into every machine on your network in quick succession, run commands on each, and move on. Look at what your detections make of that.

This is the lesson from 12.6, from the other side​

In lesson 12.6 you scanned DC01, saw the alert, triaged it, and concluded it was you. Then you wrote a rule to suppress it, with a comment. Here is what you wrote:

<!--
KALI01 (10.10.10.50) is this lab's authorised testing host.
Scanning FROM it is expected and is dropped to level 3.

Deliberately narrow: this only covers this one source address.
The same activity from anywhere else still alerts at full level,
which is the property that makes this tuning rather than blindness.
-->

And I told you: "you are creating a blind spot on purpose... an attacker who compromises KALI01 now has a quiet place to work from."

Today's scan comes from UBNT01, at 10.10.10.20, not from KALI01. So it should alert at full severity. Check whether it did:

  • If your dashboard lit up: your tuning was correctly narrow. The exception covered exactly the one host it named and nothing else. That is the property you were told to check for, verified by an event you did not arrange for the purpose.
  • If it stayed quiet: something is broader than you intended, and finding that out now is the entire reason this lesson is placed here.

Either way, write down what happened. This is the single best piece of evidence in your journal that you can reason about detection coverage rather than just configure it.

And the thing nobody tells you​

That alert is correct and it will fire every month forever, because you will scan every month forever.

You now face the real version of the tuning problem from lesson 12.5. Your options, and none of them is free:

  1. Suppress the scanner's source address, exactly as you did for KALI01. Cheap, and it creates a second quiet place for an attacker to work from.
  2. Suppress it only during the scan window. Better, more work, and it requires the scan to actually run on schedule.
  3. Leave it alerting and let the analyst recognise it. Honest, and it is how alert fatigue starts.

There is no correct answer, and being able to argue the trade-offs is worth more than picking one. What you must not do is suppress it broadly and forget, which is option 1 without the comment explaining it.

Pick one, do it, and write the reasoning next to it in Git, the way 12.5 taught you.

What you take from this​

The difference between guessing from outside and reading from inside, a scanning account you scoped deliberately instead of by convenience, and a live test of whether the blind spot you created in Module 12 was as narrow as you intended.