summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authors <[email protected]>2025-11-08 07:50:53 -0500
committers <[email protected]>2025-11-08 07:50:53 -0500
commit25c11b030e2b4fb9bc9742daea834f0a6e049671 (patch)
tree4c033a87fb2508abd42a5ba8464e12d85be3b87a
parentdfcf52f30cdbde3a4e1400024b0c27451d179e5d (diff)
downloaddborg-25c11b030e2b4fb9bc9742daea834f0a6e049671.tar.gz
dborg-25c11b030e2b4fb9bc9742daea834f0a6e049671.zip
feat: add buckets, bucket-files, and shortlinks osint commandsv0.5.0
-rw-r--r--cmd/osint.go112
-rw-r--r--internal/client/osint.go96
-rw-r--r--internal/models/osint.go43
3 files changed, 251 insertions, 0 deletions
diff --git a/cmd/osint.go b/cmd/osint.go
index 6b97464..6bb66c5 100644
--- a/cmd/osint.go
+++ b/cmd/osint.go
@@ -49,12 +49,36 @@ var osintFilesCmd = &cobra.Command{
RunE: runOsintFilesSearch,
}
+var osintBucketsCmd = &cobra.Command{
+ Use: "buckets",
+ Short: "List public buckets",
+ Long: `List public S3, Azure, GCP, and DigitalOcean buckets with file counts`,
+ RunE: runOsintBucketsSearch,
+}
+
+var osintBucketFilesCmd = &cobra.Command{
+ Use: "bucket-files",
+ Short: "Search public bucket files",
+ Long: `Search public S3, Azure, GCP, and DigitalOcean buckets for exposed files`,
+ RunE: runOsintBucketFilesSearch,
+}
+
+var osintShortlinksCmd = &cobra.Command{
+ Use: "shortlinks",
+ Short: "Search brute forced short links",
+ Long: `Search for exposed URLs discovered through brute forcing URL shortener services`,
+ RunE: runOsintShortlinksSearch,
+}
+
func init() {
rootCmd.AddCommand(osintCmd)
osintCmd.AddCommand(osintUsernameCmd)
osintCmd.AddCommand(osintBSSIDCmd)
osintCmd.AddCommand(osintBreachForumCmd)
osintCmd.AddCommand(osintFilesCmd)
+ osintCmd.AddCommand(osintBucketsCmd)
+ osintCmd.AddCommand(osintBucketFilesCmd)
+ osintCmd.AddCommand(osintShortlinksCmd)
osintUsernameCmd.Flags().StringSliceP("sites", "s", []string{}, "Specific sites to check (comma-separated)")
osintUsernameCmd.Flags().BoolP("fuzzy", "f", false, "Enable fuzzy validation mode")
@@ -71,6 +95,23 @@ func init() {
osintFilesCmd.Flags().StringP("exclude", "x", "html,HTML", "Exclude file extension(s) - comma-separated")
osintFilesCmd.Flags().IntP("size", "s", 10, "Number of results to return (max 40)")
osintFilesCmd.Flags().IntP("from", "f", 0, "Starting offset for pagination")
+
+ osintBucketsCmd.Flags().IntP("limit", "l", 1000, "Number of results to return")
+ osintBucketsCmd.Flags().IntP("start", "t", 0, "Starting offset for pagination")
+
+ osintBucketFilesCmd.Flags().StringP("keywords", "w", "", "Search keywords")
+ osintBucketFilesCmd.Flags().StringP("extensions", "e", "", "File extensions (comma-separated, e.g. 'sql,db,xlsx')")
+ osintBucketFilesCmd.Flags().StringP("buckets", "b", "", "Filter by bucket names (comma-separated)")
+ osintBucketFilesCmd.Flags().IntP("limit", "l", 1000, "Number of results to return")
+ osintBucketFilesCmd.Flags().IntP("start", "t", 0, "Starting offset for pagination")
+
+ osintShortlinksCmd.Flags().StringP("keywords", "w", "", "Search keywords")
+ osintShortlinksCmd.Flags().StringP("ext", "e", "", "File extensions (comma-separated, e.g. 'pdf,docx,xlsx')")
+ osintShortlinksCmd.Flags().StringP("order", "o", "", "Sort by property (size, timestamp)")
+ osintShortlinksCmd.Flags().StringP("direction", "d", "", "Sort direction (asc, desc)")
+ osintShortlinksCmd.Flags().BoolP("regexp", "r", false, "Treat keywords as regular expression")
+ osintShortlinksCmd.Flags().IntP("limit", "l", 100, "Number of results to return")
+ osintShortlinksCmd.Flags().IntP("start", "t", 0, "Starting offset for pagination")
}
func runOsintUsernameCheck(cmd *cobra.Command, args []string) error {
@@ -170,3 +211,74 @@ func runOsintFilesSearch(cmd *cobra.Command, args []string) error {
return utils.PrintJSON(response)
}
+
+func runOsintBucketsSearch(cmd *cobra.Command, args []string) error {
+ apiKey, _ := cmd.Flags().GetString("api-key")
+ cfg := config.New().WithAPIKey(apiKey)
+
+ c, err := client.New(cfg)
+ if err != nil {
+ return err
+ }
+
+ params := &models.BucketsSearchParams{}
+ params.Limit, _ = cmd.Flags().GetInt("limit")
+ params.Start, _ = cmd.Flags().GetInt("start")
+
+ response, err := c.SearchBuckets(params)
+ if err != nil {
+ return err
+ }
+
+ return utils.PrintJSON(response)
+}
+
+func runOsintBucketFilesSearch(cmd *cobra.Command, args []string) error {
+ apiKey, _ := cmd.Flags().GetString("api-key")
+ cfg := config.New().WithAPIKey(apiKey)
+
+ c, err := client.New(cfg)
+ if err != nil {
+ return err
+ }
+
+ params := &models.BucketsFilesSearchParams{}
+ params.Keywords, _ = cmd.Flags().GetString("keywords")
+ params.Extensions, _ = cmd.Flags().GetString("extensions")
+ params.Buckets, _ = cmd.Flags().GetString("buckets")
+ params.Limit, _ = cmd.Flags().GetInt("limit")
+ params.Start, _ = cmd.Flags().GetInt("start")
+
+ response, err := c.SearchBucketFiles(params)
+ if err != nil {
+ return err
+ }
+
+ return utils.PrintJSON(response)
+}
+
+func runOsintShortlinksSearch(cmd *cobra.Command, args []string) error {
+ apiKey, _ := cmd.Flags().GetString("api-key")
+ cfg := config.New().WithAPIKey(apiKey)
+
+ c, err := client.New(cfg)
+ if err != nil {
+ return err
+ }
+
+ params := &models.ShortlinksSearchParams{}
+ params.Keywords, _ = cmd.Flags().GetString("keywords")
+ params.Ext, _ = cmd.Flags().GetString("ext")
+ params.Order, _ = cmd.Flags().GetString("order")
+ params.Direction, _ = cmd.Flags().GetString("direction")
+ params.Regexp, _ = cmd.Flags().GetBool("regexp")
+ params.Limit, _ = cmd.Flags().GetInt("limit")
+ params.Start, _ = cmd.Flags().GetInt("start")
+
+ response, err := c.SearchShortlinks(params)
+ if err != nil {
+ return err
+ }
+
+ return utils.PrintJSON(response)
+}
diff --git a/internal/client/osint.go b/internal/client/osint.go
index 95e3550..d7e795c 100644
--- a/internal/client/osint.go
+++ b/internal/client/osint.go
@@ -88,3 +88,99 @@ func (c *Client) SearchOpenDirectoryFiles(params *models.OpenDirectorySearchPara
return &response, nil
}
+
+func (c *Client) SearchBuckets(params *models.BucketsSearchParams) (*models.BucketsSearchResponse, error) {
+ path := "/osint/buckets/buckets"
+
+ queryParams := url.Values{}
+ if params.Limit > 0 {
+ queryParams.Add("limit", fmt.Sprintf("%d", params.Limit))
+ }
+ if params.Start > 0 {
+ queryParams.Add("start", fmt.Sprintf("%d", params.Start))
+ }
+
+ data, err := c.Get(path, queryParams)
+ if err != nil {
+ return nil, err
+ }
+
+ var response models.BucketsSearchResponse
+ if err := json.Unmarshal(data, &response); err != nil {
+ return nil, fmt.Errorf("failed to parse buckets search response: %w", err)
+ }
+
+ return &response, nil
+}
+
+func (c *Client) SearchBucketFiles(params *models.BucketsFilesSearchParams) (*models.BucketsFilesSearchResponse, error) {
+ path := "/osint/buckets/files"
+
+ queryParams := url.Values{}
+ if params.Keywords != "" {
+ queryParams.Add("keywords", params.Keywords)
+ }
+ if params.Extensions != "" {
+ queryParams.Add("extensions", params.Extensions)
+ }
+ if params.Buckets != "" {
+ queryParams.Add("buckets", params.Buckets)
+ }
+ if params.Limit > 0 {
+ queryParams.Add("limit", fmt.Sprintf("%d", params.Limit))
+ }
+ if params.Start > 0 {
+ queryParams.Add("start", fmt.Sprintf("%d", params.Start))
+ }
+
+ data, err := c.Get(path, queryParams)
+ if err != nil {
+ return nil, err
+ }
+
+ var response models.BucketsFilesSearchResponse
+ if err := json.Unmarshal(data, &response); err != nil {
+ return nil, fmt.Errorf("failed to parse bucket files search response: %w", err)
+ }
+
+ return &response, nil
+}
+
+func (c *Client) SearchShortlinks(params *models.ShortlinksSearchParams) (*models.ShortlinksSearchResponse, error) {
+ path := "/osint/shortlinks"
+
+ queryParams := url.Values{}
+ if params.Keywords != "" {
+ queryParams.Add("keywords", params.Keywords)
+ }
+ if params.Ext != "" {
+ queryParams.Add("ext", params.Ext)
+ }
+ if params.Order != "" {
+ queryParams.Add("order", params.Order)
+ }
+ if params.Direction != "" {
+ queryParams.Add("direction", params.Direction)
+ }
+ if params.Regexp {
+ queryParams.Add("regexp", "true")
+ }
+ if params.Limit > 0 {
+ queryParams.Add("limit", fmt.Sprintf("%d", params.Limit))
+ }
+ if params.Start > 0 {
+ queryParams.Add("start", fmt.Sprintf("%d", params.Start))
+ }
+
+ data, err := c.Get(path, queryParams)
+ if err != nil {
+ return nil, err
+ }
+
+ var response models.ShortlinksSearchResponse
+ if err := json.Unmarshal(data, &response); err != nil {
+ return nil, fmt.Errorf("failed to parse shortlinks search response: %w", err)
+ }
+
+ return &response, nil
+}
diff --git a/internal/models/osint.go b/internal/models/osint.go
index 9f714c4..950225d 100644
--- a/internal/models/osint.go
+++ b/internal/models/osint.go
@@ -47,3 +47,46 @@ type OpenDirectorySearchParams struct {
}
type OpenDirectorySearchResponse map[string]interface{}
+
+type BucketsSearchParams struct {
+ Limit int
+ Start int
+}
+
+type BucketsFilesSearchParams struct {
+ Keywords string
+ Extensions string
+ Buckets string
+ Limit int
+ Start int
+}
+
+type ShortlinksSearchParams struct {
+ Keywords string
+ Ext string
+ Order string
+ Direction string
+ Regexp bool
+ Limit int
+ Start int
+}
+
+type CreditsInfo struct {
+ Used int `json:"used"`
+ Remaining int `json:"remaining"`
+}
+
+type BucketsSearchResponse struct {
+ Credits CreditsInfo `json:"credits"`
+ Results interface{} `json:"results"`
+}
+
+type BucketsFilesSearchResponse struct {
+ Credits CreditsInfo `json:"credits"`
+ Results interface{} `json:"results"`
+}
+
+type ShortlinksSearchResponse struct {
+ Credits CreditsInfo `json:"credits"`
+ Results interface{} `json:"results"`
+}