Skip to content

Commit

Permalink
feat: html output support
Browse files Browse the repository at this point in the history
  • Loading branch information
riza committed Jun 26, 2022
1 parent 210c96f commit dc7e807
Show file tree
Hide file tree
Showing 11 changed files with 175 additions and 9 deletions.
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
main
.idea
.idea
/*.html
linx
5 changes: 4 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@ linx --target=https://rizasabuncu.com/assets/admin_acces.js

# TODOs

* [ ] HTML Output
* [x] HTML output support
* [ ] JSON output support
* [ ] Custom cookie support
* [ ] Rule improvement & blacklist support
* [ ] Support parallel scan multiple files
* [ ] ...
2 changes: 1 addition & 1 deletion cmd/linx/linx.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import (
"github.com/riza/linx/pkg/logger"
)

const Version = "v0.0.1"
const Version = "v0.0.2"

func main() {
banner.Show(Version)
Expand Down
12 changes: 12 additions & 0 deletions internal/output/output.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package output

type OutputData struct {
Target string
Filename string
Results []Result
}

type Result struct {
URL string
Location string
}
36 changes: 36 additions & 0 deletions internal/output/output_html.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package output

import (
"html/template"
"os"
)

const templateFile = "./internal/output/output_html_template.html"

type OutputHTML struct {
output OutputData
}

func NewOutputHTML(output OutputData) OutputHTML {
return OutputHTML{output: output}
}

func (oh OutputHTML) RenderAndSave() error {
f, err := os.Create(oh.output.Filename)
if err != nil {
return err
}
defer f.Close()

t, err := template.ParseFiles(templateFile)
if err != nil {
return err
}

err = t.Execute(f, oh.output)
if err != nil {
return err
}

return nil
}
52 changes: 52 additions & 0 deletions internal/output/output_html_template.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>{{ .Target }} - linx report</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.0-beta1/dist/css/bootstrap.min.css" rel="stylesheet"
integrity="sha384-0evHe/X+R7YkIZDRvuzKMRqM+OrBnVFBL6DOitfPri4tjfHxaWutUpFmBp4vmVor" crossorigin="anonymous">
</head>
<body>

<div class="col-lg-8 mx-auto p-3 py-md-5">
<header class="d-flex align-items-center pb-3 mb-5 border-bottom">
<a href="/" class="d-flex align-items-center text-dark text-decoration-none">
<span class="fs-4">{{ .Target }}</span>
</a>
</header>

<main>
<div class="row g-12">
<div class="col-md-12">
<table style="table-layout: fixed" class="table table-striped table-hover">
<thead>
<tr>
<th scope="col">URL</th>
<th scope="col">Location in file</th>
</tr>
</thead>
<tbody>
{{range .Results}}
<tr>
<td>{{ .URL }}</td>
<td>
<pre><code>{{ .Location }}</code></pre>
</td>
</tr>
{{end}}
</tbody>
</table>
</div>
</div>
</main>
<footer class="pt-5 my-5 text-muted border-top">
created with <a href="https://github.com/riza/linx">linx</a>
</footer>
</div>

<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.0-beta1/dist/js/bootstrap.bundle.min.js"
integrity="sha384-pprn3073KE6tl6bjs2QrFaJGz5/SUsLqktiwsUTF55Jfv3qYSDhgCecCxMW52nD2"
crossorigin="anonymous"></script>
</body>
</html>
58 changes: 53 additions & 5 deletions internal/scanner/scanner.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,12 @@ package scanner

import (
"fmt"
"github.com/riza/linx/internal/output"
"github.com/riza/linx/internal/scanner/strategies"
"github.com/riza/linx/pkg/logger"
"os/exec"
"regexp"
"runtime"
"strings"
"unsafe"
)
Expand All @@ -24,6 +27,7 @@ type scanner struct {
func NewScanner(target string) scanner {
return scanner{
task{
target: target,
strategy: defineStrategyForTarget(target),
},
}
Expand All @@ -32,17 +36,42 @@ func NewScanner(target string) scanner {
func (s scanner) Run() error {
r, _ := regexp.Compile(rule)

content, err := s.task.strategy.GetContent()
strategy := s.task.strategy
content, err := strategy.GetContent()
if err != nil {
return fmt.Errorf(errGetFileContent, err)
}

urls := r.FindAllString(*(*string)(unsafe.Pointer(&content)), -1)
for _, s := range urls {
logger.Get().Infof("found possible url: %s", s)
out := output.OutputData{
Target: s.task.target,
Filename: strategy.GetFileName() + "_result.html",
Results: []output.Result{},
}

for _, s := range r.FindAllStringSubmatchIndex(*(*string)(unsafe.Pointer(&content)), -1) {
url := content[s[0]:s[1]]
closeLines := content[s[0]-100 : s[1]+100]

out.Results = append(out.Results, output.Result{
URL: string(url),
Location: string(closeLines),
})

logger.Get().Infof("found possible url: %s", string(url))
}

logger.Get().Infof("%d possible url found", len(out.Results))

err = output.NewOutputHTML(out).RenderAndSave()
if err != nil {
return fmt.Errorf(errOutputFailed, err)
}

err = openResults(out.Filename)
if err != nil {
return fmt.Errorf(errOutputOpenFailed, err)
}

logger.Get().Infof("%d possible url found", len(urls))
return nil
}

Expand All @@ -52,3 +81,22 @@ func defineStrategyForTarget(target string) strategies.ScanStrategy {
}
return strategies.FileStrategy{target}
}

func openResults(fileName string) error {
var err error
switch runtime.GOOS {
case "linux":
err = exec.Command("xdg-open", fileName).Start()
case "windows":
err = exec.Command("rundll32", "url.dll,FileProtocolHandler", fileName).Start()
case "darwin":
err = exec.Command("open", fileName).Start()
default:
err = fmt.Errorf("unsupported platform")
}
if err != nil {
return err
}

return nil
}
4 changes: 3 additions & 1 deletion internal/scanner/scanner_errors.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package scanner

var (
errGetFileContent = "error getting content err: %w"
errGetFileContent = "error getting content err: %w"
errOutputFailed = "output fail render and save err: %w"
errOutputOpenFailed = "output fail opening err: %w"
)
4 changes: 4 additions & 0 deletions internal/scanner/strategies/file.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@ func (fs FileStrategy) GetContent() ([]byte, error) {
return fs.readFileContent()
}

func (fs FileStrategy) GetFileName() string {
return fs.Target
}

func (fs FileStrategy) readFileContent() ([]byte, error) {
_, err := os.Stat(fs.Target)
if err != nil {
Expand Down
1 change: 1 addition & 0 deletions internal/scanner/strategies/strategy.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,5 @@ package strategies

type ScanStrategy interface {
GetContent() ([]byte, error)
GetFileName() string
}
6 changes: 6 additions & 0 deletions internal/scanner/strategies/url.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"github.com/riza/linx/pkg/logger"
"io/ioutil"
"net/http"
"path"
)

type URLStrategy struct {
Expand All @@ -16,6 +17,11 @@ func (us URLStrategy) GetContent() ([]byte, error) {
return us.getFileContent()
}

func (us URLStrategy) GetFileName() string {
_, file := path.Split(us.Target)
return file
}

func (us URLStrategy) getFileContent() ([]byte, error) {
logger.Get().Debugf("getting file from %s", us.Target)
resp, err := http.Get(us.Target)
Expand Down

0 comments on commit dc7e807

Please sign in to comment.