use xslt!

This commit is contained in:
Adrien MALINGREY 2023-04-09 01:06:01 +02:00
parent c7b85862e6
commit 3a162f4568
10 changed files with 238 additions and 227 deletions

3
.gitignore vendored
View File

@ -1,3 +1,2 @@
confs/*.yaml
!confs/example.yaml
site/
scans/

View File

@ -2,17 +2,18 @@
Scan hosts with nmap and display results in webpage.
* Create a configuration yaml file in confs/ subdirectory (see example below).
* Create a configuration yaml file in site/ subdirectory (see example below).
It may be generated by scanning a network with `init.sh`.
* Scan with `php scan_all.php` (use a cron task!).
* Open index.php to see results.
## Example
```yaml
group1:
host1.local: [ssh, http]
host2.local: [ftp, https, 5432]
group2:
host3: [ssh, ftp, 8006]
site:
group1:
host1.local: [ssh, http]
host2.local: [ftp, https, 5432]
group2:
host3: [ssh, ftp, 8006]
```

View File

@ -1,12 +1,36 @@
<?php
$site = filter_input(INPUT_GET, "site", FILTER_SANITIZE_STRING);
$site = escapeshellcmd($site);
if ($site and file_exists("confs/$site.yaml") and file_exists("scans/$site.xml")) {
$conf = yaml_parse_file("confs/$site.yaml");
$scan = simplexml_load_file("scans/$site.xml");
require("results.php");
} else {
require("ls.php");
}
?>
<!doctype html>
<html lang="fr">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>lanScan</title>
<script src="https://cdn.jsdelivr.net/npm/jquery@3.6.3/dist/jquery.min.js"></script>
<link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/fomantic-ui@2.9.2/dist/semantic.min.css">
<script src="https://cdn.jsdelivr.net/npm/fomantic-ui@2.9.2/dist/semantic.min.js"></script>
<style>
#logo {
margin: 0 -.4rem 0 0;
}
.main.container {
margin-top: 5em;
}
</style>
</head>
<body>
<header class="ui fixed centered blue inverted menu">
<div class="header item">lan<img id="logo" src="logo.svg" alt="S"/>can</div>
</header>
<div class="ui main text container">
<div class="ui link selection list">
<?php foreach (scandir("./site") as $file) {
if (strrpos($file, ".xml")) {
$site = str_replace(".xml", "", $file);
if (file_exists("scans/$site.xml")) {
echo " <a href='site/$site.xml' class='item'>$site</a>\n";
}
}
} ?>
</div>
</div>
</body>
</html>

6
init.sh Normal file → Executable file
View File

@ -7,8 +7,8 @@
###
echo "Nom du site ?"
read name
read site
echo "Plage IP (xxx.xxx.xxx.xxx/xx) ?"
read network
nmap --script smb-enum-shares.nse -oX "confs/$name.xml" $network
xsltproc toyaml.xsl "confs/$name.xml" > "confs/$name.yaml"
nmap --script smb-enum-shares.nse -oX "scans/$site.xml" $network
xsltproc --stringparam site "$site" --stringparam network $network toyaml.xsl "scans/$site.xml" > "site/$site.yaml"

36
ls.php
View File

@ -1,36 +0,0 @@
<!doctype html>
<html lang="fr">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>lanScan</title>
<script src="https://cdn.jsdelivr.net/npm/jquery@3.6.3/dist/jquery.min.js"></script>
<link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/fomantic-ui@2.9.2/dist/semantic.min.css">
<script src="https://cdn.jsdelivr.net/npm/fomantic-ui@2.9.2/dist/semantic.min.js"></script>
<style>
#logo {
margin: 0 -.4rem 0 0;
}
.main.container {
margin-top: 5em;
}
</style>
</head>
<body>
<header class="ui fixed centered blue inverted menu">
<div class="header item">lan<img id="logo" src="logo.svg" alt="S"/>can</div>
</header>
<div class="ui main text container">
<div class="ui link selection list">
<?php foreach (scandir("./confs") as $file) {
if (strrpos($file, ".yaml")) {
$site = str_replace(".yaml", "", $file);
if (file_exists("scans/$site.xml")) {
echo " <a href='?site=$site' class='item'>$site</a>\n";
}
}
} ?>
</div>
</div>
</body>
</html>

View File

@ -1,146 +0,0 @@
<!doctype html>
<html lang="fr">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>lanScan - <?=$site?></title>
<script src="https://cdn.jsdelivr.net/npm/jquery@3.6.3/dist/jquery.min.js"></script>
<link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/fomantic-ui@2.9.2/dist/semantic.min.css">
<script src="https://cdn.jsdelivr.net/npm/fomantic-ui@2.9.2/dist/semantic.min.js"></script>
<style>
#logo {
margin: 0 -.4rem 0 0;
}
.main.container {
margin-top: 5em;
}
.ui.dropdown, .ui.dropdown .menu > .item {
font-size: .85714286rem;
}
.ui.mini button > .detail {
margin-left: .1em;
}
.ui.mini.cards > .card {
width: inherit;
flex-grow: 1;
}
.ui.cards > .card > .content {
display: flex;
align-items: baseline;
gap: .5em;
padding: .3em;
}
.ui.mini.menu .item {
padding: .6em;
}
.ui.mini.menu {
min-height: 1em;
}
</style>
<script>
onload = function (event) {
$('.ui.dropdown').dropdown()
}
</script>
</head>
<body>
<header class="ui fixed blue inverted menu">
<a href="." class="header item">lan<img id="logo" src="logo.svg" alt="S"/>can</a>
<div class="item"><?=$site?></div>
</header>
<div class="ui main container">
<p><?=$scan->runstats->finished["summary"]?></p>
<?php foreach($conf as $conf_groupname => $conf_hosts) { ?>
<h1 class="ui header"><?=$conf_groupname?></h1>
<div class="ui mini cards">
<?php
if ($conf_hosts) foreach($conf_hosts as $conf_address => $conf_services) {
echo " <!-- $conf_address -->\n";
$scan_host = $scan->xpath("host[hostnames/hostname/@name='$conf_address' or address/@addr='$conf_address']")[0];
$address = count($scan_host->xpath("hostnames/hostname/@name")) ? $scan_host->xpath("hostnames/hostname/@name")[0] : $scan_host->xpath("address/@addr")[0];
if ($scan_host->status["state"] =="up") {
?>
<div class="ui card">
<div class="content">
<div class="ui green empty circular label"></div>
<div><?=$scan_host->address["addr"]?></div>
<div class="header" title="<?=$scan_host->hostnames->hostname["name"]?>"><?=strtok($scan_host->hostnames->hostname["name"], ".")?></div>
</div>
<div class="ui inverted primary centered wrapped wrapping bottom attached mini menu">
<?php
if ($conf_services) foreach($conf_services as $conf_service) {
$scan_service = $scan_host->xpath("ports/port[service/@name='$conf_service' or @portid='$conf_service']")[0];
switch($scan_service->state["state"]) {
case "open": $state = "primary"; break;
case "closed": $state = "red disabled"; break;
default: $state = "yellow";
}
switch($scan_service->service['name']) {
case "microsoft-ds":
case "netbios-ssn":
$shares = $scan_host->xpath("hostscript/script[@id='smb-enum-shares']/table[not(contains(@key, '$'))]");
if (count($shares)) {
?>
<div class="ui dropdown <?=$state?> item">
<?=$scan_service->service['name']?><small>:<?=$scan_service['portid']?></small>
<i class="dropdown icon"></i>
<div class="menu">
<?php
foreach($shares as $share) {
?>
<a class='item' href='file:////$address/<?=$share['key']?>'><?=$share['key']?></a>
<?php
}
?>
</div>
</div>
<?php
} else {
?>
<div class="ui <?=$state?> disabled item" disabled><?=$scan_service->service['name']?><small>:<?=$scan_service['portid']?></small></div>
<?php
}
break;
case "telnet":
case "ftp":
case "ssh":
case "http":
case "https":
?>
<a href="<?=$scan_service->service['name']?>://<?=$address?>:<?=$scan_service['portid']?>" class="ui <?=$state?> item"><?=$scan_service->service['name']?><small>:<?=$scan_service['portid']?></small></a>
<?php
break;
case "ms-wbt-server":
?>
<a href="rdp.php?v=<?=$address?>:<?=$scan_service['portid']?>" class="ui <?=$state?> item">rdp<small>:<?=$scan_service['portid']?></small></a>
<?php
break;
default:
?>
<div class="ui <?=$state?> disabled item" disabled><?=$scan_service->service['name']?><small>:<?=$scan_service['portid']?></small></div>
<?php
}
}
?>
</div>
</div>
<?php
} else {
?>
<div class="ui red card">
<div class="content">
<div class="ui red empty circular label"></div>
<div ><?=$scan_host->address["addr"]?></div>
<div class="header" title="<?=$scan_host->hostnames->hostname["name"]?>"><?=strtok($scan_host->hostnames->hostname["name"], ".")?></div>
</div>
</div>
<?php
}
}
?>
</div>
<?php
}
?>
</body>
</html>

138
results.xsl Normal file
View File

@ -0,0 +1,138 @@
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
version="1.1">
<xsl:output method="html" encoding="UTF-8" indent="yes" />
<xsl:variable name="scan" select="document(string(lanScanConf/scan/@path))/nmaprun"/>
<xsl:template match="lanScanConf">
<html lang="fr">
<head>
<title>lanScan - <xsl:value-of select="@name"/></title>
<script src="https://cdn.jsdelivr.net/npm/jquery@3.6.3/dist/jquery.min.js"></script>
<link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/fomantic-ui@2.9.2/dist/semantic.min.css" />
<script src="https://cdn.jsdelivr.net/npm/fomantic-ui@2.9.2/dist/semantic.min.js"></script>
<style>
#logo {
margin: 0 -.4rem 0 0;
}
.main.container {
margin-top: 5em;
}
.ui.grid > .column:not(.row) {
padding: .5em !important;
}
</style>
</head>
<body>
<header class="ui fixed blue inverted menu">
<a href="." class="header item">lan<img id="logo" src="../logo.svg" alt="S"/>can</a>
<div class="item"><xsl:value-of select="@name"/></div>
</header>
<div class="ui main container">
<p><xsl:value-of select="$scan/runstats/finished/@summary"/></p>
<xsl:apply-templates select="group"/>
</div>
<script>
$('.ui.dropdown').dropdown()
</script>
</body>
</html>
</xsl:template>
<xsl:template match="group">
<h1 class="ui header"><xsl:value-of select="@name"/></h1>
<div class="ui doubling stackable four column grid">
<xsl:apply-templates select="host"/>
</div>
</xsl:template>
<xsl:template match="host">
<xsl:variable name="address" select="@address"/>
<xsl:variable name="scannedHost" select="$scan/host[hostnames/hostname/@name=$address or address/@addr=$address]"/>
<xsl:variable name="scannedHostAddress">
<xsl:choose>
<xsl:when test="$scannedHost/hostnames/hostname/@name">
<xsl:value-of select="$scannedHost/hostnames/hostname/@name" />
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$scannedHost/address/@addr" />
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<div class="column">
<xsl:choose>
<xsl:when test="$scannedHost/status/@state='up'">
<div class="ui fluid mini action input success">
<input type="text" value="{substring-before($scannedHost/hostnames/hostname/@name, '.')}" title="{$scannedHost/hostnames/hostname/@name} ({$scannedHost/address/@addr})" readonly="" />
<xsl:apply-templates select="service">
<xsl:with-param name="scannedHost" select="$scannedHost" />
<xsl:with-param name="scannedHostAddress" select="$scannedHostAddress" />
</xsl:apply-templates>
</div>
</xsl:when>
<xsl:otherwise>
<div class="ui fluid mini input error">
<input type="text" value="{substring-before(@address, '.')}" title="{@address}" readonly="" />
</div>
</xsl:otherwise>
</xsl:choose>
</div>
</xsl:template>
<xsl:template match="service">
<xsl:param name="scannedHost" />
<xsl:param name="scannedHostAddress" />
<xsl:variable name="serviceName" select="@name"/>
<xsl:variable name="scannedPort" select="$scannedHost/ports/port[service/@name=$serviceName or @portid=$serviceName]"/>
<xsl:comment><xsl:value-of select="@name"/>,<xsl:value-of select="$scannedPort/service/@name='ftp'"/></xsl:comment>
<xsl:choose>
<xsl:when test="$scannedPort/state/@state='open'">
<xsl:choose>
<xsl:when test="($scannedPort/service/@name='microsoft-ds' or $scannedPort/service/@name='netbios-ssn') and $scannedHost/hostscript/script[@id='smb-enum-shares']/table[not(contains(@key, '$'))]">
<div class="ui primary dropdown mini button">
<div class="text">smb</div>
<i class="dropdown icon"></i>
<div class="menu">
<xsl:apply-templates select="$scannedHost/hostscript/script[@id='smb-enum-shares']/table[not(contains(@key, '$'))]">
<xsl:with-param name="scannedHostAddress" select="$scannedHostAddress" />
</xsl:apply-templates>
</div>
</div>
</xsl:when>
<xsl:when test="$scannedPort/service/@name='ms-wbt-server'">
<a class="ui primary mini button" href="../rdp.php?v={$scannedHostAddress}:{$scannedPort/@portid}">
rdp
</a>
</xsl:when>
<xsl:when test="$scannedPort/service/@name='ftp' or $scannedPort/service/@name='ssh' or $scannedPort/service/@name='http' or $scannedPort/service/@name='https'">
<a class="ui primary mini button" role="button" href="{$scannedPort/service/@name}://{$scannedHostAddress}:{$scannedPort/@portid}">
<xsl:value-of select="@name"/>
</a>
</xsl:when>
<xsl:otherwise>
<a class="ui disabled primary mini button" role="button">
<xsl:value-of select="@name"/>
</a>
</xsl:otherwise>
</xsl:choose>
</xsl:when>
<xsl:otherwise>
<a class="ui red disabled mini button" role="button">
<xsl:value-of select="@name"/>
</a>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template match="table">
<xsl:param name="scannedHostAddress" />
<a class="item" href="file:///{@key}" target="_blank" rel="noopener noreferrer">
<xsl:value-of select="@key" />
</a>
</xsl:template>
</xsl:stylesheet>

View File

@ -1,27 +1,44 @@
<?php
if (!file_exists("scans")) mkdir("scans");
foreach (scandir("./confs") as $file) {
foreach (scandir("./site") as $file) {
if (strrpos($file, ".yaml")) {
$site = str_replace(".yaml", "", $file);
$conf = yaml_parse_file("confs/$file");
$yaml = yaml_parse_file("site/$file");
$targets = [];
$services = [];
foreach ($conf as $sitename => $hosts) {
foreach($hosts as $hostaddress => $servicesList) {
$targets[$hostaddress] = true;
foreach ($servicesList as $service) {
$services[$service] = true;
$xml = new SimpleXMLElement(<<<XML
<?xml version="1.0"?>
<?xml-stylesheet href='../results.xsl' type='text/xsl'?>
<lanScanConf/>
XML);
$xml->addChild("scan path='scans/$site.xml'");
foreach ($yaml as $siteName => $groups) {
$xml->addAttribute("name", $siteName);
if ($groups) foreach ($groups as $groupName => $hosts) {
$xmlGroup = $xml->addChild("group");
$xmlGroup->addAttribute("name", $groupName);
if ($hosts) foreach($hosts as $hostaddress => $servicesList) {
$targets[$hostaddress] = true;
$xmlHost = $xmlGroup->addChild("host");
$xmlHost->addAttribute("address", $hostaddress);
if ($servicesList) foreach ($servicesList as $service) {
$services[$service] = true;
$xmlService = $xmlHost->addChild("service");
$xmlService->addAttribute("name", $service);
}
}
}
}
$targets = array_keys($targets);
$services = array_keys($services);
$xml->asXML("site/$site.xml");
exec("nmap -v -Pn -p ".join($services, ",")." --script smb-enum-shares.nse -oX 'scans/$site.xml' ".join($targets, " "));
//exec("nmap -v -Pn -p ".join($services, ",")." --script smb-enum-shares.nse -oX 'scans/$site.xml' ".join($targets, " "));
}
};

View File

@ -1,19 +1,29 @@
<?php
$yaml = yaml_parse_file($argv[1]);
$xml = new SimpleXMLElement("<lanScanConf></lanScanConf>");
$site = str_replace(".yaml", "", basename($argv[1]));
foreach ($yaml as $groupName => $hosts) {
$xmlGroup = $xml->addChild("group");
$xmlGroup->addAttribute("name", $groupName);
if ($hosts) foreach ($hosts as $hostName => $services) {
$xmlHost = $xmlGroup->addChild("host");
$xmlHost->addAttribute("name", $hostName);
if ($services) foreach ($services as $service) {
$xmlHost->addChild("service");
$xmlHost->addAttribute("name", $service);
$xml = new SimpleXMLElement(<<<XML
<?xml version="1.0"?>
<?xml-stylesheet href='../results.xsl' type='text/xsl'?>
<lanScanConf/>
XML);
$xml->addChild("scan path='scans/$site.xml'");
foreach ($yaml as $siteName => $groups) {
$xml->addAttribute("name", $siteName);
if ($groups) foreach ($groups as $groupName => $hosts) {
$xmlGroup = $xml->addChild("group");
$xmlGroup->addAttribute("name", $groupName);
if ($hosts) foreach ($hosts as $hostName => $services) {
$xmlHost = $xmlGroup->addChild("host");
$xmlHost->addAttribute("address", $hostName);
if ($services) foreach ($services as $service) {
$xmlService = $xmlHost->addChild("service");
$xmlService->addAttribute("name", $service);
}
}
}
}
}
echo $xml->asXML();
$xml->asXML("site/$site.xml");
?>

View File

@ -5,15 +5,19 @@
version="1.1">
<xsl:output method="text" encoding="UTF-8" indent="yes" />
<xsl:param name="site" />
<xsl:param name="network" />
<xsl:template match="nmaprun">
<xsl:text>---
</xsl:text>
<xsl:value-of select="substring-after(@args, '&quot; ')" />:
<xsl:value-of select="$site" />:
<xsl:text> </xsl:text><xsl:value-of select="$network" />:
<xsl:apply-templates select="host"/>
</xsl:template>
<xsl:template match="host">
<xsl:text> </xsl:text>
<xsl:text> </xsl:text>
<xsl:choose>
<xsl:when test="hostnames/hostname/@name"><xsl:value-of select="hostnames/hostname/@name" /></xsl:when>
<xsl:otherwise> <xsl:value-of select="address/@addr" /></xsl:otherwise>