⚡ Fast Web Security Scanner written in Rust based on Lua Scripts 🌖 🦀

Overview

⚠️ We're Looking for maintainers #39

lotus

Fast Web Security Scanner written in Rust based on Lua Scripts 🌖 🦀

Currently this project is still under beta version, there are alot of features that are still under developing it would be better if you make a contribute to this project to make it finish faster, you can check the project issues page for more, Don't forget to Join Us on Discord

Usage

you can build it from source

$ cargo install --git=https://github.com/rusty-sec/lotus/

or download the binary file from the release page

| img[onerror="alert()"][src="x"] ❯ cat test.json | jq [ { "risk": "medium", "name": "reflected cross site scripting", "description": "https://owasp.org/www-community/attacks/xss/", "url": "http://testphp.vulnweb.com/listproducts.php?cat=1%22%3E%3Cimg+src%3Dx+onerror%3Dalert%28%29%3E", "param": "cat", "attack": "\">", "evidence": "img[src=\"x\"][onerror=\"alert()\"]" } ] [ { "risk": "high", "name": "SQL Injection", "description": "https://owasp.org/www-community/attacks/SQL_Injection", "url": "http://testphp.vulnweb.com/listproducts.php?cat=1%27123", "param": "cat", "attack": "'123", "evidence": "check the manual that (corresponds to|fits) your MySQL server version" }, { "risk": "high", "name": "SQL Injection", "description": "https://owasp.org/www-community/attacks/SQL_Injection", "url": "http://testphp.vulnweb.com/listproducts.php?cat=1%27%27123", "param": "cat", "attack": "''123", "evidence": "check the manual that (corresponds to|fits) your MySQL server version" } ]">
echo "http://testphp.vulnweb.com/listproducts.php?cat=1" | lotus --scripts fuzzer/active --workers 30 --output test.json
🔥 RXSS: http://testphp.vulnweb.com/listproducts.php?cat=1%22%3E%3Cimg+src%3Dx+onerror%3Dalert%28%29%3E | "> | img[onerror="alert()"][src="x"]

❯ cat test.json | jq
[
  {
    "risk": "medium",
    "name": "reflected cross site scripting",
    "description": "https://owasp.org/www-community/attacks/xss/",
    "url": "http://testphp.vulnweb.com/listproducts.php?cat=1%22%3E%3Cimg+src%3Dx+onerror%3Dalert%28%29%3E",
    "param": "cat",
    "attack": "\">>",
    "evidence": "img[src=\"x\"][onerror=\"alert()\"]"
  }
]
[
  {
    "risk": "high",
    "name": "SQL Injection",
    "description": "https://owasp.org/www-community/attacks/SQL_Injection",
    "url": "http://testphp.vulnweb.com/listproducts.php?cat=1%27123",
    "param": "cat",
    "attack": "'123",
    "evidence": "check the manual that (corresponds to|fits) your MySQL server version"
  },
  {
    "risk": "high",
    "name": "SQL Injection",
    "description": "https://owasp.org/www-community/attacks/SQL_Injection",
    "url": "http://testphp.vulnweb.com/listproducts.php?cat=1%27%27123",
    "param": "cat",
    "attack": "''123",
    "evidence": "check the manual that (corresponds to|fits) your MySQL server version"
  }
 
]
Lotus 0.2-beta
Khaled Nassar <[email protected]>
Fast Web Security Scanner written in Rust based on Lua Scripts

USAGE:
    lotus [OPTIONS] --workers <workers> --scripts <scripts> --output <output> [nolog]

ARGS:
    <nolog>    no logging

OPTIONS:
    -h, --help                               Print help information
    -l, --log <log>                          Save all lots to custom file
    -o, --output <output>                    Path of the JSON output fiel
    -s, --scripts <scripts>                  Path of scripts dir
    -t, --script-threads <script_threads>    Workers for lua scripts [default: 5]
    -V, --version                            Print version information
    -w, --workers <workers>                  Number of works of urls [default: 10]

Lua API

Function About output type Example
is_match check if regex is matching with the text or not bool is_match("\d\d\d","123") -- true
println print message above the progress bar Nil println("XSS FOUND :D")
log_info logging with info level Nil log_info("Hello")
log_debug logging with debug level Nil log_debug("Hello")
log_warn logging with warn level Nil log_warn("Hello")
log_error logging with error level Nil log_error("Hello")
generate_css_selector generate Css Selector pattern for Xss payloads String generate_css_selector("
html_parse get the type of your payload in the response page List of Location Enum html_parse("

","hackerman") -- AttrName

html_search Search with CSS Selector in HTML String html_search("

demo

","h1")
change_urlquery add your payload to all url parameters Table (List) change_urlquery("http://google.com/?hello=1","hacker")
set_urlvalue Change custom parameter value in the url String set_urlvalue("http://google.com/?test=1","test","hacker")
urljoin Join Path to the url String urljoin("http://google.com/","/search")
send_req send Get http request to the url Table with ( url , status , body , errors ) send_req("https://google.com")

Enum

To get the value from lua script you can call it with value:GetEnumTypeOrNil

  • send_req
pub enum RespType {
    NoErrors,
    Emtpy,
    Str(String),
    Int(i32),
    Error(String),
}
local resp = send_req("http://google.com")
if resp.errors:GetErrorOrNil() == nil then
  -- NO Connection ERRORS
  if string.find(resp.body:GetStrOrNil(),"google") then
    log_info("FOUND GOOGLE")
  end
end
  
  • html_parse
pub enum Location {
    AttrValue(String),
    AttrName(String),
    TagName(String),
    Text(String),
    Comment(String),
}
Hello","Hello") for index_key,index_value in ipairs(searcher) do if index_value:GetTextOrNil() then println(string.format("FOUND IT IN TEXT %s",index_value:GetTextOrNil())) end end">
local searcher = html_parse("

Hello

"
,"Hello") for index_key,index_value in ipairs(searcher) do if index_value:GetTextOrNil() then println(string.format("FOUND IT IN TEXT %s",index_value:GetTextOrNil())) end end
Comments
  • interact.sh API

    interact.sh API

    lotus needs OAST client for interact.sh

    here's the client in Python as an example

    
    class Interactsh:
        # Source: https://github.com/knownsec/pocsuite3/blob/master/pocsuite3/modules/interactsh/__init__.py
        def __init__(self, token="", server=""):
            rsa = RSA.generate(2048)
            self.public_key = rsa.publickey().exportKey()
            self.private_key = rsa.exportKey()
            self.token = token
            self.server = server.lstrip('.') or 'interact.sh'
            self.headers = {
                "Content-Type": "application/json",
            }
            if self.token:
                self.headers['Authorization'] = self.token
            self.secret = str(uuid4())
            self.encoded = b64encode(self.public_key).decode("utf8")
            guid = uuid4().hex.ljust(33, 'a')
            guid = ''.join(i if i.isdigit() else chr(ord(i) + random.randint(0, 20)) for i in guid)
            self.domain = f'{guid}.{self.server}'
            self.correlation_id = self.domain[:20]
    
            self.session = requests.session()
            self.session.headers = self.headers
            self.session.verify = False
            self.session.proxies = proxies
            self.register()
    
        def register(self):
            data = {
                "public-key": self.encoded,
                "secret-key": self.secret,
                "correlation-id": self.correlation_id
            }
            res = self.session.post(
                f"https://{self.server}/register", headers=self.headers, json=data, timeout=30)
            if 'success' not in res.text:
                raise Exception("Can not initiate interact.sh DNS callback client")
    
        def pull_logs(self):
            result = []
            url = f"https://{self.server}/poll?id={self.correlation_id}&secret={self.secret}"
            res = self.session.get(url, headers=self.headers, timeout=30).json()
            aes_key, data_list = res['aes_key'], res['data']
            for i in data_list:
                decrypt_data = self.__decrypt_data(aes_key, i)
                result.append(self.__parse_log(decrypt_data))
            return result
    
        def __decrypt_data(self, aes_key, data):
            private_key = RSA.importKey(self.private_key)
            cipher = PKCS1_OAEP.new(private_key, hashAlgo=SHA256)
            aes_plain_key = cipher.decrypt(base64.b64decode(aes_key))
            decode = base64.b64decode(data)
            bs = AES.block_size
            iv = decode[:bs]
            cryptor = AES.new(key=aes_plain_key, mode=AES.MODE_CFB, IV=iv, segment_size=128)
            plain_text = cryptor.decrypt(decode)
            return json.loads(plain_text[16:])
    
        def __parse_log(self, log_entry):
            new_log_entry = {"timestamp": log_entry["timestamp"],
                             "host": f'{log_entry["full-id"]}.{self.domain}',
                             "remote_address": log_entry["remote-address"]
                             }
            return new_log_entry
    
    new-api 
    opened by knassar702 3
  • Installing Error

    Installing Error

    Hello, When I was trying to install the tool, I got an error image

    But I don't have enough knowledge to figure out what happened, and what is the solution are you can help me with that?

    good first issue 
    opened by xElkomy 1
  • removed redundant features from mlua

    removed redundant features from mlua

    Tealr already passes the features to mlua. No need to set them again in mlua.

    Some features from mlua (actually, most of them) break its API in some way that tealr needs to know about. As a result, I highly recommend to not enable any features in mlua directly but instead enable their equivalent in tealr. Doing this enables them in mlua (including in the mlua you depend directly on) and makes it harder to accidentally enable a feature only in mlua, which can cause compile errors.

    Ideally, you don't depend on mlua directly and instead use the reexport under tealr::mlu::mlua to side step this entire problem but I also agree that depending on mlua directly is nicer if its used a lot and it isn't a problem for as long as you keep the feature thing in mind.

    opened by lenscas 1
  • print the report automatically

    print the report automatically

    i think we can just print the report in the CLI for the use without using the println function just add the report and lotus will display it

        NewReport:setName("reflected cross site scripting")
        NewReport:setDescription("https://owasp.org/www-community/attacks/xss/")
        NewReport:setRisk("medium")
        NewReport:setUrl(url)
        NewReport:setParam(parameter)
        NewReport:setAttack(payload)
        NewReport:setEvidence(generate_css_selector(payload))
    
    [+] Reflected XSS on: {URL}
    [!] Vulnerable Parameter: {PARAM}
    [!] Risk: {RISK}
    [!] Used Payload: {PAYLOAD} 
    [!] Matching Pattern: {MATCHING PATTERN}
    [!] Matched with: {MATCHIGN}
    
    ---
    
    core-changes 
    opened by knassar702 0
  • [lua-api] xss payloads generator

    [lua-api] xss payloads generator

    we need to make something to generate xss payloads based of the location of the reflected point

    Avaible locatons

    • ATTR NAME
    • ATTR VALUE
    • HTML TAG
    • TEXT
    • COMMENTS
    missing-lua-api 
    opened by knassar702 0
  • Convert Lua Talbes to Vec or HashMap in reporting side

    Convert Lua Talbes to Vec or HashMap in reporting side

    when you tried to run some lua scripts like sqli.lua script you will find a weird thing in the reports, there's no List only hashmaps with numbers of index

    we can convert it from this

    {
      "5": {
        "payload": "\"\"123",
        "match": "Warning.*?\\Wmysqli?_",
        "url": "http://testphp.vulnweb.com/artists.php?artist=1%22%22123"
      },
    }
    

    to this

    {
      "report": [ {
        "payload": "\"\"123",
        "match": "Warning.*?\\Wmysqli?_",
        "url": "http://testphp.vulnweb.com/artists.php?artist=1%22%22123"
      }]
    }
    

    lotus report handler

                  let mut test_report: HashMap<String, mlua::Value> = HashMap::new();
                    lua.globals(
    )
                        .get::<_, mlua::Table>("REPORT")
                        .unwrap()
                        .pairs::<String, mlua::Value>()
                        .for_each(|out_report| {
                            let current_out = out_report.clone();
                            test_report.insert(current_out.unwrap().0, out_report.unwrap().1);
                        });
                    let results = serde_json::to_string(&test_report).unwrap();
                    self.write_report(&results);
    
    bug core-changes 
    opened by knassar702 0
  • Change http method with send_req function

    Change http method with send_req function

    headers = {}
    headers["User-agent"] = "Firefox"
    send_req("POST","http;//example.com","body=111",headers)
    
    missing-lua-api 
    opened by knassar702 0
  • raw http request handler

    raw http request handler

    I think lotus need to make the payload injection process simple to the user, so instead of calling a lot of functions to change the parameters values like this

    for payload in PAYLOADS:gmatch("[^\n]+") do
       new_querys = HttpMessage:setAllParams("testxss")
       for param_name, pay_url in pairs(new_querys) do 
          -- scanner logic
       end
    end
    

    to this

    --[[
    HttpMessage -> 
        set_payload(new_txt) -> set the chosien parameter value to the new_txt parameter value
        get_method() -> get http method
        get_url() -> get the request url
        get_body() -> get the request 
        get_targetparam() -> get the current param
        injection_point() -> get the injection point [body, url parameter value, url parameter name, url path, headers]
        set_*() -> to change all of get_* functions value
    --]]
    
    for payload in PAYLOADS:gmatch("[^\n]+") do
        new_req = HttpMessage:set_payload("xss_test")
        new_req:send()
    

    this will make the normal scanning tasks easier and faster for reading or writing

    inspired by zaproxy scripting

    https://github.com/zaproxy/community-scripts/blob/main/active/bxss.py

    new-api core-changes 
    opened by knassar702 0
  • Set scripts loading limit

    Set scripts loading limit

    There is a possibility to set a limit for loading and reading lua scripts, for example, by using the command --limit 5 (5 scripts per URL).

    We can read five scripts for each url if we have 100 scripts; when the five scripts end, we can read five more scripts for that url.

    core-changes 
    opened by knassar702 2
Owner
Rusty Sec
We're building Security Automation tools in Rust :crab: :heart:
Rusty Sec
Another cursed Garry's Mod module. This time, it adds the C preprocessor to Lua scripts

gm_cpreprocessor Another cursed Garry's Mod module. This time, it adds the C preprocessor to Lua scripts. It works by detouring RunStringEx and overri

William 6 Aug 14, 2022
An npm scripts runner written in Rust.

dum replaces npm run. Instead of waiting 200ms for your npm client to start, it will start immediately. ?? You can help the author become a full-time

EGOIST 1.3k Jan 9, 2023
A script language like Python or Lua written in Rust, with exactly the same syntax as Go's.

A script language like Python or Lua written in Rust, with exactly the same syntax as Go's.

null 1.4k Jan 1, 2023
A parser, compiler, and virtual machine evaluator for a minimal subset of Lua; written from scratch in Rust.

lust: Lua in Rust This project implements a parser, compiler, and virtual machine evaluator for a minimal subset of Lua. It is written from scratch in

Phil Eaton 146 Dec 16, 2022
Rust library for build scripts to compile C/C++ code into a Rust library

A library to compile C/C++/assembly into a Rust library/application.

Alex Crichton 1.3k Dec 21, 2022
Lua 5.3 bindings for Rust

rust-lua53 Aims to be complete Rust bindings for Lua 5.3 and beyond. Currently, master is tracking Lua 5.3.3. Requires a Unix-like environment. On Win

J.C. Moyer 150 Dec 14, 2022
Safe Rust bindings to Lua 5.1

rust-lua Copyright 2014 Lily Ballard Description This is a set of Rust bindings to Lua 5.1. The goal is to provide a (relatively) safe interface to Lu

Lily Ballard 124 Jan 5, 2023
Zero-cost high-level lua 5.3 wrapper for Rust

td_rlua This library is a high-level binding for Lua 5.3. You don't have access to the Lua stack, all you can do is read/write variables (including ca

null 47 May 4, 2022
Rust library to interface with Lua

hlua This library is a high-level binding for Lua 5.2. You don't have access to the Lua stack, all you can do is read/write variables (including callb

Pierre Krieger 488 Dec 26, 2022
Pure Rust Lua implementation

purua Pure Rust Lua implementation Usage $ bat lua_examples/defun.lua ───────┬────────────────────────────────────────── │ File: lua_examples/d

Kondo Uchio 35 Dec 28, 2021
Rust scaffold system with Lua embedded applets.

brickpack-2022 Demo Powered by Github Actions CI/CD (Heroku) https://demo-1642622230.herokuapp.com/#/users Frontent Runner Rendered sample code (Lua 5

null 0 Nov 24, 2022
📦 Pack hundreds of Garry's Mod Lua files into just a handful

?? gluapack gluapack is a program that can pack hundreds of Garry's Mod Lua files into just a handful. Features Quick, easy and portable - perfect for

null 11 Aug 10, 2021
A memory safe Lua interpreter

Hematita Da Lua Hematita Da Lua is an interpreter for the scripting language Lua, written entirely in 100% safe Rust. Hematita is the portugese word f

Daniel 149 Dec 29, 2022
A super-lightweight Lua microservice (toy) framework.

Hive A super-lightweight microservice (toy) framework written in Rust. It uses Lua as interface to provide simple, fun developing experience and fast

Eric Long 39 Aug 14, 2022
🐱‍👤 Cross-language static library for accessing the Lua state in Garry's Mod server plugins

gmserverplugin This is a utility library for making Server Plugins that access the Lua state in Garry's Mod. Currently, accessing the Lua state from a

William 5 Feb 7, 2022
This tool converts Lua code to TS automatically, including the conversion of common standards to their TS equivalents.

lua-to-ts This tool converts Lua code to TS automatically, including the conversion of common standards to their TS equivalents. Code that fails to be

Dion 11 Nov 21, 2022
Node.js bindings to Lua

Node.js bindings to Lua

Connor Brewster 6 Dec 19, 2022
A Web-App written in Rust with Yew, using the same SyntaxHighlighter from Google Code Archive as planetb.ca

PlanetB SyntaxHighlighter About This is a small app, providing static files to have a frontend to format your code so you can paste it with styles to

Christof Weickhardt 2 Dec 14, 2022
swc is a super-fast compiler written in rust; producing widely-supported javascript from modern standards and typescript.

Make the web (development) faster. SWC (stands for Speedy Web Compiler) is a super-fast TypeScript / JavaScript compiler written in Rust. It's a libra

swc 25.4k Dec 31, 2022