Port 80 is open. You have a browser tab showing a login page, no credentials, and no idea what is running behind it. Learning how to use Nikto is how you turn that blank page into a list of things worth looking at, in about the time it takes to read the source of the homepage.
Nikto is a web server scanner. It fires thousands of requests at known-bad paths, reads the responses, and tells you which ones came back interesting. It is one of the oldest tools in the recon phase of penetration testing, and it is still the first thing a lot of people run against a web port. Open the Backup Hunter lab in another tab while you read: it is a web server with a forgotten file on it, which is exactly the kind of thing Nikto exists to find.
TL;DR: Nikto is an open source web server scanner written in Perl that checks a target against a database of over 8,000 known-risky files and paths. Install it with sudo apt install nikto (Kali ships 2.6.1), then run nikto -h http://target. A default scan sends roughly 8,000 requests and finishes in seconds against a lab box. The skill is not running it, it is reading the output: half of what Nikto reports is missing security headers, and the version checks throw false positives constantly.
What Is Nikto?
Nikto is an open source scanner that tests a web server against a database of known dangerous files, outdated software versions and common misconfigurations. It requests each path in its database, compares the response to a set of match rules, and prints the ones that look like a finding.
Chris Sullo has maintained it since 2001. It is written in Perl, built on the LibWhisker HTTP library, and licensed under GPLv3, though the check databases carry their own separate licence and cannot be reused in other tools. The official project page at cirt.net puts the coverage at "over 8,000 potentially dangerous or interesting files and programs" plus outdated versions of thousands of servers and components. If you clone the repo and count, the main db_tests file in 2.6.1 has 7,288 lines, with the rest of the coverage spread across a dozen other database files.
Here is the thing nobody tells you on day one, and it explains most of the disappointment people have with the tool.
Nikto does not crawl. It never reads a link on your target and follows it. It has a list of paths it already knows about, and it asks for every one of them. That is a fundamentally different job from a web application scanner, which maps the app first and then attacks what it found.
So Nikto is excellent at finding the things everybody leaves lying around: /.env, /phpinfo.php, /backup/, an admin console on a default path, a server banner that gives away the stack. It is useless at finding the broken authorisation check in /api/v2/orders/1041, because nothing in its database has ever heard of that URL.
Installing Nikto and Checking Your Version
On Kali it is already installed, and the current Kali package is 2.6.1. On Debian or Ubuntu it is one command:
sudo apt update
sudo apt install nikto
Check what you actually got before anything else:
nikto -Version
Nikto 2.6.1 (LW 2.5)
That "LW 2.5" is the LibWhisker version underneath. Version 2.6.1 shipped on 31 July 2024 and is worth having: it added TLS keep-alive connections for roughly 18% faster scans, switched to a static Chrome user agent by default instead of rotating one per request, and added the sqld output format that writes findings straight into MySQL or PostgreSQL.
If your distribution packages something older, run it from the source tree instead:
git clone https://github.com/sullo/nikto
cd nikto/program
perl nikto.pl -Version
In practice that clone fails on a clean machine with ERROR: Required module not found: XML::Writer and nothing else. Nikto checks its Perl dependencies before it prints anything, so a missing module looks like a broken tool. Install it and the same command works:
sudo apt install libxml-writer-perl
There is also an official container if you would rather not touch Perl at all:
docker pull ghcr.io/sullo/nikto:latest
Your First Nikto Scan
One flag does the work. -h takes a hostname, an IP or a full URL:
nikto -h http://127.0.0.1:8000/
Here is a real scan against a deliberately sloppy Python web server, trimmed only where the same finding repeats:
- Nikto v2.6.1
---------------------------------------------------------------------------
+ Target IP: 127.0.0.1
+ Target Hostname: 127.0.0.1
+ Target Port: 8000
+ Start Time: 2026-09-08 07:20:21 (GMT0)
---------------------------------------------------------------------------
+ Server: SimpleHTTP/0.6 Python/3.11.15
+ No CGI Directories found (use '-C all' to force check all possible dirs).
+ [013587] /: Suggested security header missing: content-security-policy.
+ [013587] /: Suggested security header missing: strict-transport-security.
+ [013587] /: Suggested security header missing: x-content-type-options.
+ [600720] SimpleHTTP/0.6 appears to be outdated (current is at least 1.2).
+ [600652] Python/3.11.15 appears to be outdated (current is at least 3.14.6).
+ [001578] /backup/: This might be interesting.
+ [007226] /.env: .env file found. The .env file may contain credentials.
+ 8143 requests: 4 errors and 11 items reported on the remote host
+ End Time: 2026-09-08 07:20:50 (GMT0) (11 seconds)
Eight thousand requests in eleven seconds, because the target is on localhost. Against a real host over the internet, the same scan takes several minutes.
The bracketed numbers are Nikto's own test IDs, one per line in the check database. They replaced the OSVDB references that older tutorials still show, because OSVDB shut down in 2016. They are useful for one thing: grepping the database to see exactly what a check tested.
Two lines in that output are findings. The rest is context.
Reading Nikto Output Without Fooling Yourself
Nikto reports everything it matched and leaves the judgement to you. That is the right design, and it means the output above contains one genuine finding, one lead, and a pile of noise.
The real finding is /.env. A publicly readable environment file usually holds database credentials, API keys and a framework secret. That single line is worth more than the rest of the scan combined, and it is the first thing to open.
The lead is /backup/. "This might be interesting" is Nikto's way of saying a directory exists that people often leave open. It is not a vulnerability. It is a place to point your next tool.
The noise is the security header block. Five lines telling you a Python test server has no Content-Security-Policy. In a client report those belong in the low-severity section. In a capture the flag, they belong in the bin.
Then there are the version checks, and this is where beginners get burned:
+ [600720] SimpleHTTP/0.6 appears to be outdated (current is at least 1.2).
That is wrong. SimpleHTTP is Python's standard library server and there is no version 1.2 of it. Nikto matched the banner against an entry in db_outdated for an unrelated product with a similar name, and reported it with total confidence. The Python 3.11 line above it is technically true and still tells you nothing about whether the box is exploitable.
Every version finding Nikto reports is a string comparison against a banner the server chose to send. Servers lie about banners. Reverse proxies rewrite them. Backported security patches leave the version number alone on purpose, which is why a fully patched Debian Apache reports a version that looks years old. Confirm the software and version yourself before you write it down, and never chain straight to an exploit on the strength of a Nikto banner match.
A triage order that works: credentials and config files first, then directories worth enumerating, then software identification, then headers.
The Flags That Change the Scan
Nikto has around fifty options. These are the ones that change what happens rather than how it looks.
Cutting the Scan Down with -Tuning
-Tuning selects which categories of check run. The codes are single characters and you concatenate them:
1interesting files,2misconfiguration and default files,3information disclosure4injection (XSS, script, HTML),9SQL injection,0file upload5and7remote file retrieval, inside the web root and server wide6denial of service,8command execution,aauthentication bypassbsoftware identification,cremote source inclusion,dweb services,eadministrative consolesxinverts the selection, so-Tuning x6runs everything except the denial of service checks
The recon-only combination is the one to memorise:
nikto -h http://target -Tuning 123b
Files, misconfigurations, information disclosure and software identification. On the same target as above, that dropped the scan from 8,143 requests to 4,297 and found every one of the same eleven items. Half the traffic, none of the loss, because the injection and denial of service categories were never going to fire on a static file server.
Always cut category 6 on anything you did not build yourself. Those checks look for denial of service conditions by triggering them.
Pointing It at the Right Thing
-p 80,443,8080,8443scans several ports in one run. Nikto handles the HTTP and HTTPS switch on its own.-root /app/prepends a path to every request. Essential when the application lives in a subdirectory and a scan of/returns nothing.-vhost dev.acme.examplesets the Host header while connecting to the IP you gave it. Shared hosting and Kubernetes ingresses serve different sites by hostname, so scanning the IP without this often tests the wrong site entirely.-C allforces the CGI directory checks that the default scan skips. Worth one run on anything old.-maxtime 5mcaps the run. Useful when a slow target would otherwise leave the scan going all afternoon.-useproxy http://127.0.0.1:8080routes everything through a proxy, which puts the whole scan in your Burp Suite history where you can replay individual requests.
Saving Results
nikto -h http://target -o scan.json -Format json
nikto -h http://target -o report.html -Format htm
JSON gives you a vulnerabilities array with id, url, method, msg and references per finding, which is what you want if anything downstream is going to parse it. The HTML report is the one to attach to a ticket. Formats can be combined with commas, and if you leave -Format off, Nikto guesses from the file extension.
When Every Path Comes Back as a Hit
Some servers answer 200 OK for URLs that do not exist, which makes every check in the database look like a finding. Nikto tries to detect this by requesting random paths at startup, and when that fails you tell it what a failure looks like:
nikto -h http://target -404string "Page not found"
nikto -h http://target -404code 302
If a scan returns hundreds of findings on a modern single page application, this is almost always why.
Where Nikto Fits in a Real Recon Workflow
Nikto is one step, not a methodology. The order that works on a CTF box and on a client engagement is the same:
- Port scan first. You cannot scan a web server you have not found. An Nmap service scan tells you which ports are speaking HTTP. Nikto parses Nmap's greppable output, so a scan saved with
-oG ports.gnmapcan be handed straight to-hand every open web port gets queued:+ Nmap Input Queued: 127.0.0.1:8000. XML output does not work, only greppable. - Look at the site yourself. Thirty seconds in the browser and in view-source beats any scanner. Frameworks announce themselves in comments, script paths and cookie names.
- Run Nikto in the background. Start
nikto -h http://target -Tuning 123b -o nikto.txtin one pane and keep reading in another. It costs you nothing to have it running. - Brute force what Nikto cannot know. Nikto only asks for paths in its database. Custom directories need a wordlist, which is what Gobuster and ffuf are for. The two tools overlap far less than people assume: one asks about known-bad files, the other guesses names.
- Take the leads into a proxy. Every finding worth chasing gets opened in Burp and tested by hand.
The mistake to avoid is treating a clean Nikto scan as a clean target. On a modern application, a scan with zero findings is the normal result. It means nobody left an old admin panel lying around, not that the app is secure.
When Nikto Is the Wrong Tool
Honest limits, so you stop reaching for it in situations where it cannot help:
- Modern web applications. No crawling, no session handling, no JavaScript. An API-driven single page app is close to invisible to it. Use a proxy and your own reading of the traffic.
- Anything behind a WAF or a CDN. Thousands of requests for
/phpinfo.phpand friends is textbook scanner behaviour. Cloudflare and its peers block or challenge the scan, and every finding after that point is meaningless. - Authenticated areas.
-id user:passhandles HTTP Basic and NTLM, and nothing else. There is no support for logging into a form, so everything past the login page is out of reach. - Business logic and access control. Broken authorisation is the top item in the OWASP Top 10, and no path-based scanner will ever find it. That is manual work.
- Confirming a vulnerability. Nikto tells you something looks wrong. Proving it, and proving the impact, is on you.
One flag deserves a note because tutorials misrepresent it. -evasion applies request encoding tricks such as self-referencing directories and alternate URL casing. Its honest use is on the defensive side: run the same scan with and without it and see whether your own monitoring still catches it. As a way to get a scan past somebody else's controls it is twenty year old technology, and current defences handle it comfortably.
Where Nikto still earns its place is legacy and internal infrastructure, and CTF boxes built to be enumerated. The intranet app nobody has redeployed since 2018, the printer web interface, the staging server with directory listing on: that is where a few thousand automated requests turn up something in the first minute and save you an hour.
Legal and Ethical Considerations
Critical reminder: Always get explicit written authorization before testing any system. Nikto sends thousands of requests for files associated with attacks, all of it in the target's access logs under your IP address. Running it against a host you do not own or have permission to test is unauthorised access under the Computer Fraud and Abuse Act in the US, the Computer Misuse Act in the UK, and equivalent law nearly everywhere else.
- Scan only hosts named in a signed scope document, or lab environments you built yourself
- Exclude tuning category
6unless denial of service testing is explicitly in scope and in writing - Shared hosting means one IP can serve hundreds of sites. Confirm the target with
-vhostrather than scanning an address and hoping - Credentials found in an exposed config file go in the report, not into a login form, unless the scope says otherwise
- Tell the client before you start. A scanner in the logs looks identical to an attack, and blue teams have opened incidents over less
CTF platforms and deliberately vulnerable targets exist so you can run this without any of the above hanging over you. Use them.
Frequently Asked Questions
What is Nikto used for?
Scanning a web server for known dangerous files, outdated software and common misconfigurations. It requests thousands of paths from its own database and reports which ones answered in an interesting way. Penetration testers use it early in recon, and CTF players use it the moment they find an open web port.
Is Nikto still worth using in 2026?
Yes, for what it is good at. Version 2.6.1 is actively maintained and finds exposed config files, forgotten backups and default admin consoles faster than any manual process. It will not help you against a modern JavaScript application behind a CDN, and it was never designed to.
Does Nikto find SQL injection and XSS?
Only in the crudest way. Tuning categories 9 and 4 test a handful of known-vulnerable paths for specific products, not the parameters in your target's own application. For real injection testing you need a proxy and either manual work or a dedicated tool such as sqlmap.
Why does Nikto say my server is outdated when it is fully patched?
Because it compares the banner string to a version database and nothing more. Distributions backport security fixes without changing the version number, reverse proxies rewrite banners, and near-matching product names produce nonsense such as reporting Python's SimpleHTTP/0.6 as outdated. Verify the version by hand before acting on it.
How do I make a Nikto scan faster?
Cut the checks rather than the timeouts. -Tuning 123b keeps files, misconfigurations, information disclosure and software identification, and roughly halves the request count. Add -maxtime 5m to cap the run, and -p with only the ports you know are open.
Nikto, Nmap or Gobuster: which one do I need?
All three, in that order. Nmap finds which ports are open and what is listening. Nikto asks a web server about paths that are known to be risky. Gobuster and ffuf guess paths that no database could know, using a wordlist. They answer different questions and none of them replaces the others.
Your Next Steps
Knowing how to use Nikto is mostly knowing what to ignore. nikto -h http://target gets you a scan, -Tuning 123b gets you a faster and quieter one, -vhost and -root make sure you are scanning the site you meant to, and -o report.html -Format htm gives you something to hand over. Everything after that is triage: config files first, directories second, banners treated as rumours.
The part you cannot get from reading is what a real finding feels like when it appears in the output. Run the Backup Hunter lab and watch a forgotten file turn into credentials, then work through the vulnerability scanning chapter of our network penetration testing course for how scanner output becomes a finding you can defend. Keep the Nikto cheat sheet open next to your terminal for the flags you have not memorised yet. Everything runs in the browser on HackerDNA's free tier, no credit card and no local install needed.
Part of the Penetration Testing series
Related articles: