├── .github └── FUNDING.yml ├── .gitignore ├── LICENSE ├── README.md ├── SECURITY.md ├── generate.sh ├── generator.py ├── payloadfile └── wordlistfile /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | github: geeknik 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Binaries for programs and plugins 2 | *.exe 3 | *.exe~ 4 | *.dll 5 | *.so 6 | *.dylib 7 | 8 | # Test binary, built with `go test -c` 9 | *.test 10 | 11 | # Output of the go coverage tool, specifically when used with LiteIDE 12 | *.out 13 | 14 | # Dependency directories (remove the comment below to include it) 15 | # vendor/ 16 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Geeknik Labs 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Semi-automatic nuclei template generator 2 | 3 | NOTE: The bash script is superceded by the Python script and will no longer be updated. 4 | 5 | Usage: 6 | `./generate.sh wordlistfile payloadfile > template_name.yaml && nuclei -t template_name.yaml -validate` 7 | 8 | To build your own wordlistfile, check out this workflow by our friend [nullenc0de](https://twitter.com/nullenc0de/status/1423973855941509124) and pay special attention to the api_params.txt which gets created on the 3rd line: 9 | ``` 10 | wget https://gist.githubusercontent.com/nullenc0de/bb16be959686295b3b1caff519cc3e05/raw/2016dc0e692821ec045edd5ae5c0aba5ec9ec3f1/api-linkfinder.yaml 11 | echo https://stripe.com/docs/api | hakrawler | nuclei -t ./api-linkfinder.yaml -o api.txt 12 | cat api.txt | grep url_params | cut -d ' ' -f 7 |tr , '\n' | tr ] '\n' | tr [ '\n' |tr -d '"' | tr -d "'" | sort -u > api_params.txt 13 | cat api.txt | grep relative_links | cut -d ' ' -f 7 |tr , '\n' | tr ] '\n' | tr [ '\n' | tr -d '"' | tr -d "'" | sort -u > api_link_finder.txt 14 | ``` 15 | 16 | Be creative! Use your own custom built wordlists! Play with different payloads! You're limited only by your imagination. Good luck out there! \m/ 17 | 18 | # FIXED 🥳 (in the WIP Python script) 19 | * Generated templates now validate as long as the payloadfile is properly escaped or encoded 20 | * payloadfile supports more than one payload 21 | * Added support for Raw, Network and File templates 22 | * Added `unsafe` option. 23 | * Added support for multiple matchers 24 | * Added support for status matchers 25 | * Added better error handling 26 | 27 | # KNOWN ISSUES 🤒 (in the WIP Python script) 28 | * None! 29 | 30 | # TODO 🔨 (in the WIP Python script) 31 | * Missing something? Tell us! 32 | 33 | Please open an issue if you encounter a bug, have a suggestion, comment, or idea. Feel free to open a pull request if you want to fix a bug or make an improvement of your own. \m/ 34 | 35 | # Disclaimer 36 | * You agree, by downloading this software, to use it at your own risk. We are not responsible for damages caused by your use of this software. 37 | * This project is not affiliated with, nor endorsed by, [Project Discovery](https://github.com/projectdiscovery). 38 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | The purpose the of this file is to silence warnings from GitHub about a missing security policy file. 2 | -------------------------------------------------------------------------------- /generate.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | function prompt_until_valid { 4 | local varname=$1 5 | local prompt=$2 6 | local valid_values=$3 7 | 8 | while [[ -z ${!varname} || ( -n "$valid_values" && ! " ${valid_values[*]} " =~ " ${!varname} " ) ]]; do 9 | read -p "$prompt" $varname 10 | done 11 | } 12 | 13 | # Check command line arguments 14 | if [[ -z $1 || -z $2 ]]; then 15 | printf "Usage: generate.sh wordlistfile payloadfile > template_name.yaml\n" 16 | exit 1 17 | fi 18 | 19 | # Check files 20 | for file in "$1" "$2"; do 21 | if [[ ! -r $file ]]; then 22 | printf "Error: File '%s' not found or not readable\n" "$file" 23 | exit 1 24 | fi 25 | done 26 | 27 | # Prompt for template details 28 | prompt_until_valid template_id 'Template ID: ' 29 | prompt_until_valid template_name 'Template Name: ' 30 | prompt_until_valid template_description 'Template Description: ' 31 | prompt_until_valid template_reference 'Template Reference: ' 32 | prompt_until_valid template_author 'Template Author: ' 33 | prompt_until_valid template_severity 'Template Severity: ' 'info low medium high critical' 34 | prompt_until_valid template_tags 'Template Tags: ' 35 | prompt_until_valid template_method 'Template Method (GET/POST): ' 'GET POST' 36 | 37 | # Prepare payload and base URL 38 | template_payload=$(cat "$2") 39 | tempfile=$(mktemp) 40 | sed -e 's/^/ - "{{BaseURL}}\//' "$1" > "$tempfile" 41 | sed -e 's/^/ /' "$tempfile" > "$tempfile" 42 | template_baseurl=$(awk -v tp="$template_payload" '{print " " $0 tp "\""}' "$tempfile") 43 | rm "$tempfile" 44 | 45 | # Prompt for matchers details 46 | prompt_until_valid template_matchers_condition 'Template Matchers Condition (and/or): ' 'and or' 47 | prompt_until_valid template_matchers_type 'Template Matchers Type (regex/word): ' 'regex word' 48 | prompt_until_valid template_matchers_part 'Template Matchers Part (body/header): ' 'body header' 49 | prompt_until_valid template_matchers_words 'Template '"$template_matchers_type"' Matchers: ' 50 | 51 | # Output template 52 | cat << EOF 53 | id: $template_id 54 | 55 | info: 56 | name: $template_name 57 | description: $template_description 58 | reference: 59 | - $template_reference 60 | author: $template_author 61 | severity: $template_severity 62 | tags: $template_tags 63 | 64 | requests: 65 | - method: $template_method 66 | path: 67 | $template_baseurl 68 | 69 | matchers-condition: $template_matchers_condition 70 | matchers: 71 | - type: $template_matchers_type 72 | part: $template_matchers_part 73 | ${template_matchers_type}s: 74 | - '$template_matchers_words' 75 | EOF 76 | -------------------------------------------------------------------------------- /generator.py: -------------------------------------------------------------------------------- 1 | import oyaml as yaml 2 | 3 | def prompt_until_valid(prompt, valid_values=None, validate=True): 4 | while True: 5 | value = input(prompt) 6 | if not validate or (value and (valid_values is None or value in valid_values)): 7 | return value 8 | 9 | def add_matchers(unsafe): 10 | matchers = [] 11 | while True: 12 | matcher = { 13 | 'type': prompt_until_valid('Template Matchers Type: ', ['status', 'regex', 'word', 'binary', 'size'], not unsafe) 14 | } 15 | matcher_part = 'body' if matcher['type'] in ['regex', 'word'] else None 16 | if matcher_part: 17 | matcher['part'] = prompt_until_valid('Template Matchers Part: ', ['body', 'header'], not unsafe) 18 | matcher[matcher['type'] + 's'] = [prompt_until_valid(f"Template {matcher['type']} Matchers: ")] 19 | matchers.append(matcher) 20 | if prompt_until_valid('Add another matcher (yes/no): ', ['yes', 'no']) != 'yes': 21 | break 22 | return matchers 23 | 24 | def add_http_requests(unsafe): 25 | requests = [] 26 | while True: 27 | request = { 28 | 'method': prompt_until_valid('Template Method (GET/POST): ', ['GET', 'POST'], not unsafe), 29 | 'path': [prompt_until_valid('Template Path: ')], 30 | 'matchers-condition': prompt_until_valid('Template Matchers Condition (and/or): ', ['and', 'or'], not unsafe), 31 | 'matchers': add_matchers(unsafe) 32 | } 33 | requests.append(request) 34 | if prompt_until_valid('Add another request (yes/no): ', ['yes', 'no']) != 'yes': 35 | break 36 | return requests 37 | 38 | def add_network_requests(unsafe): 39 | requests = [] 40 | while True: 41 | request = { 42 | 'data': prompt_until_valid('Data: '), 43 | 'read-size': prompt_until_valid('Read Size: '), 44 | 'matchers': add_matchers(unsafe) 45 | } 46 | requests.append(request) 47 | if prompt_until_valid('Add another request (yes/no): ', ['yes', 'no']) != 'yes': 48 | break 49 | return requests 50 | 51 | def add_file_requests(unsafe): 52 | requests = [] 53 | while True: 54 | request = { 55 | 'extension': prompt_until_valid('File Extension: '), 56 | 'words': prompt_until_valid('Words: '), 57 | 'matchers': add_matchers(unsafe) 58 | } 59 | requests.append(request) 60 | if prompt_until_valid('Add another request (yes/no): ', ['yes', 'no']) != 'yes': 61 | break 62 | return requests 63 | 64 | def add_dns_requests(unsafe): 65 | requests = [] 66 | while True: 67 | request = { 68 | 'name': prompt_until_valid('Name: '), 69 | 'type': prompt_until_valid('Type: '), 70 | 'class': prompt_until_valid('Class: '), 71 | 'recursion': prompt_until_valid('Recursion Desired (yes/no): ', ['yes', 'no']), 72 | 'retries': prompt_until_valid('Retries: '), 73 | 'matchers': add_matchers(unsafe) 74 | } 75 | requests.append(request) 76 | if prompt_until_valid('Add another request (yes/no): ', ['yes', 'no']) != 'yes': 77 | break 78 | return requests 79 | 80 | def main(): 81 | # Prompt for template details 82 | template = { 83 | 'id': prompt_until_valid('Template ID: '), 84 | 'info': { 85 | 'name': prompt_until_valid('Template Name: '), 86 | 'description': prompt_until_valid('Template Description: '), 87 | 'reference': [prompt_until_valid('Template Reference: ')], 88 | 'author': prompt_until_valid('Template Author: '), 89 | 'severity': prompt_until_valid('Template Severity: ', ['info', 'low', 'medium', 'high', 'critical']), 90 | 'tags': prompt_until_valid('Template Tags: '), 91 | }, 92 | } 93 | 94 | # Ask for unsafe option 95 | unsafe = prompt_until_valid('Unsafe option (yes/no): ', ['yes', 'no']) == 'yes' 96 | 97 | # Select template type 98 | template_type = prompt_until_valid('Template type (HTTP/Network/File/DNS): ', ['HTTP', 'Network', 'File', 'DNS']) 99 | 100 | try: 101 | if template_type == 'HTTP': 102 | template['requests'] = add_http_requests(unsafe) 103 | elif template_type == 'Network': 104 | template['network'] = add_network_requests(unsafe) 105 | elif template_type == 'File': 106 | template['file'] = add_file_requests(unsafe) 107 | elif template_type == 'DNS': 108 | template['dns'] = add_dns_requests(unsafe) 109 | except Exception as e: 110 | print(f"An error occurred: {e}") 111 | 112 | # Output template 113 | print(yaml.dump(template)) 114 | 115 | if __name__ == "__main__": 116 | main() 117 | -------------------------------------------------------------------------------- /payloadfile: -------------------------------------------------------------------------------- 1 | %27%3E%22%3Csvg%5Conload%3Dconfirm(%27XSS%27)%3E 2 | -------------------------------------------------------------------------------- /wordlistfile: -------------------------------------------------------------------------------- 1 | &0= 2 | &128= 3 | &1= 4 | &2= 5 | &3= 6 | &4= 7 | &9= 8 | &BBOX= 9 | &a= 10 | &access_token= 11 | &autocomplete= 12 | &autoplay= 13 | &bbox= 14 | &browser= 15 | &browser_version= 16 | &c= 17 | &caniuse_source= 18 | &clcid= 19 | &client= 20 | &client_id= 21 | &count= 22 | &country= 23 | &createNewAccount= 24 | &description= 25 | &device= 26 | &device_browser= 27 | &display= 28 | &e= 29 | &f= 30 | &fl= 31 | &fm= 32 | &g= 33 | &i= 34 | &instance= 35 | &k= 36 | &l= 37 | &m= 38 | &marketplaceId= 39 | &media= 40 | &n= 41 | &nonce= 42 | &null= 43 | &original_referer= 44 | &os_version= 45 | &p_id= 46 | &proximity= 47 | &q= 48 | &r= 49 | &redirect_uri= 50 | &ref= 51 | &repo= 52 | &requestId= 53 | &s= 54 | &screen_name= 55 | &se= 56 | &session= 57 | &sig= 58 | &source= 59 | &sp= 60 | &sr= 61 | &sso_reload= 62 | &start= 63 | &state= 64 | &t= 65 | &tw_order_quantity= 66 | &tw_sale_amount= 67 | &type= 68 | &types= 69 | &u= 70 | &uio= 71 | &utm_campaign= 72 | &utm_medium= 73 | &utm_source= 74 | &v= 75 | ?0= 76 | ?128= 77 | ?1= 78 | ?3= 79 | ?LinkID= 80 | ?LinkId= 81 | ?M= 82 | ?__cf_chl_captcha_tk__= 83 | ?a= 84 | ?accessType= 85 | ?access_token= 86 | ?action= 87 | ?b= 88 | ?bid= 89 | ?body= 90 | ?c= 91 | ?callback= 92 | ?cb= 93 | ?channels= 94 | ?continue= 95 | ?d= 96 | ?dataset= 97 | ?dl= 98 | ?e= 99 | ?family= 100 | ?features= 101 | ?file= 102 | ?format= 103 | ?forum= 104 | ?fresh= 105 | ?g= 106 | ?gml= 107 | ?h= 108 | ?hl= 109 | ?i= 110 | ?ical= 111 | ?id= 112 | ?k= 113 | ?key= 114 | ?l= 115 | ?lang= 116 | ?language= 117 | ?last_url= 118 | ?limitTo= 119 | ?linkid= 120 | ?m= 121 | ?mt= 122 | ?n= 123 | ?nc1= 124 | ?nc2= 125 | ?nc= 126 | ?null= 127 | ?o= 128 | ?original_referer= 129 | ?p= 130 | ?package= 131 | ?page= 132 | ?pane= 133 | ?pid= 134 | ?provider= 135 | ?q= 136 | ?r= 137 | ?raw= 138 | ?ray= 139 | ?redirectUrl= 140 | ?ref= 141 | ?render= 142 | ?response_type= 143 | ?return_url= 144 | ?revision= 145 | ?ru= 146 | ?s= 147 | ?sapId= 148 | ?screen_name= 149 | ?searchQuery= 150 | ?sec= 151 | ?service= 152 | ?status= 153 | ?subject= 154 | ?sv= 155 | ?t= 156 | ?tab= 157 | ?text= 158 | ?title= 159 | ?trk= 160 | ?ts= 161 | ?txn_id= 162 | ?type= 163 | ?u= 164 | ?url= 165 | ?user= 166 | ?utm_medium= 167 | ?utm_ref= 168 | ?utm_source= 169 | ?v= 170 | ?ver= 171 | ?via= 172 | ?w= 173 | ?x= 174 | ?y= 175 | --------------------------------------------------------------------------------