Skip to content

Commit d928ffc

Browse files
committed
Adding a generator for Pentester Land's Writeup list
1 parent 9750397 commit d928ffc

File tree

3 files changed

+131
-1
lines changed

3 files changed

+131
-1
lines changed

README.md

+2-1
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,12 @@ If you're only interested in the feeds that this already outputs, I generate all
1414

1515
**-f [feed generator type]**
1616

17-
There are currently three supported feed types:
17+
There are currently five supported feed types:
1818

1919
- `h1` which runs the Hackerone generator, which tracks the [latest disclosed Hacktivity](https://hackerone.com/hacktivity?querystring=&filter=type:public&order_direction=DESC&order_field=latest_disclosable_activity_at&followed_only=false) generator
2020
- `p0` which runs the ProjectZero generator, which tracks the [Project Zero issues list](https://bugs.chromium.org/p/project-zero/issues/list?q=&can=1&sort=-id). One important note about this one is that the feed does not grab dates so it is only accurate after it has been running. The first feed generated will be be based purely on ids.
2121
- `p0rca` which runs the Project Zero Root Cause Analysis generator, which tracks the [Project Zero Root Cause Analysis list](https://googleprojectzero.github.io/0days-in-the-wild/rca.html)
22+
- `pl` which runs the PentesterLand Writeups generator tracking the writeups published on [Pentester.Land](https://pentester.land/writeups/)
2223
- `css` is the more generic and useful option. It takes in a config file (json) which defines CSS selectors to match page elements that represent different parts of the feed.
2324

2425
**-t [output type]**

cmd/feedgen/main.go

+5
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,11 @@ func main() {
5151
g := generators.SyzbotGenerator{}
5252
g.WorkDir(workDir)
5353
gen = &g
54+
case "pl":
55+
g := generators.PentesterLandGenerator{
56+
MaxLength: 50,
57+
}
58+
gen = &g
5459
default:
5560
log.Println("Missing valid feed type")
5661
flag.Usage()
+124
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
package generators
2+
3+
import (
4+
"encoding/json"
5+
"fmt"
6+
"github.com/gorilla/feeds"
7+
"io/ioutil"
8+
"net/http"
9+
"strings"
10+
"time"
11+
)
12+
13+
type PentesterLandGenerator struct {
14+
filterFunc ItemFilterFunc
15+
itemModFunc ItemModifierFunc
16+
MaxLength int
17+
}
18+
19+
type PentesterLandEntry struct {
20+
Links []struct {
21+
Title string
22+
Link string
23+
}
24+
Authors []string
25+
Programs []string
26+
Bugs []string
27+
Bounty string
28+
PublicationDate string
29+
AddedDate string
30+
}
31+
32+
func (g *PentesterLandGenerator) fetch() ([]PentesterLandEntry, error) {
33+
url := "https://pentester.land/writeups.json"
34+
client := http.Client{
35+
Timeout: 15 * time.Second,
36+
}
37+
38+
res, err := client.Get(url)
39+
if err != nil {
40+
return nil, err
41+
}
42+
defer func() { _ = res.Body.Close() }()
43+
44+
body, err := ioutil.ReadAll(res.Body)
45+
if err != nil {
46+
return nil, err
47+
}
48+
49+
var entries struct {
50+
Data []PentesterLandEntry `json:"data"`
51+
}
52+
53+
err = json.Unmarshal(body, &entries)
54+
if err != nil {
55+
return nil, err
56+
}
57+
return entries.Data, nil
58+
}
59+
60+
func (g *PentesterLandGenerator) Feed() (*feeds.Feed, error) {
61+
entries, err := g.fetch()
62+
if err != nil {
63+
return nil, err
64+
}
65+
66+
out := feeds.Feed{}
67+
out.Title = "Pentester.Land Writeups"
68+
out.Link = &feeds.Link{Href: "https://pentester.land/writeups/"}
69+
out.Updated = time.Now()
70+
71+
for _, e := range entries {
72+
item := &feeds.Item{
73+
Title: e.Links[0].Title,
74+
Link: &feeds.Link{
75+
Href: e.Links[0].Link,
76+
},
77+
Author: &feeds.Author{
78+
Name: strings.Join(e.Authors, ", "),
79+
},
80+
Description: strings.Join(e.Bugs, ", "),
81+
Updated: time.Time{},
82+
Created: time.Time{},
83+
}
84+
85+
if e.Bounty != "-" && e.Bounty != "" {
86+
item.Description += fmt.Sprintf("(%s Bounty)", e.Bounty)
87+
}
88+
89+
t, err := time.Parse("2006-01-02", e.PublicationDate)
90+
if err != nil {
91+
continue
92+
}
93+
item.Created = t
94+
95+
t, err = time.Parse("2006-01-02", e.AddedDate)
96+
if err != nil {
97+
continue
98+
}
99+
item.Updated = t
100+
101+
if g.itemModFunc != nil {
102+
g.itemModFunc(item)
103+
}
104+
if g.filterFunc == nil || g.filterFunc(item) {
105+
out.Items = append(out.Items, item)
106+
}
107+
108+
if len(out.Items) >= g.MaxLength {
109+
break
110+
}
111+
}
112+
if len(out.Items) > 0 {
113+
out.Updated = out.Items[0].Updated
114+
}
115+
116+
return &out, nil
117+
}
118+
119+
func (g *PentesterLandGenerator) RegisterItemFilter(callback ItemFilterFunc) {
120+
g.filterFunc = callback
121+
}
122+
func (g *PentesterLandGenerator) RegisterItemModifier(callback ItemModifierFunc) {
123+
g.itemModFunc = callback
124+
}

0 commit comments

Comments
 (0)