pwn 0.5.387 → 0.5.388

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 6276f7133a84a10851a85b44e5b21543de34abaec589011698c04667ede52f35
4
- data.tar.gz: b632de2f5bf6957b5ab1ce5f4408403a935a4fce1709bbcaa223d56962cef613
3
+ metadata.gz: 83eff2a7a3a7bb75e65d7df503f9d773e7e9e9fcb8fa3c8527f5dc7bd66e5596
4
+ data.tar.gz: 46699a59f9b2dc261bd284c88b6f208a4ea5ab595e6fa4daa08cbdb6bc3a913f
5
5
  SHA512:
6
- metadata.gz: bdc09c6f2b768550ab1c288bccab9e02c8008eb09769313f350719c19b8a4d87b6121116f481f013ee2ba2b978b79ccf5a81ec7a177f0f966103b810887e367b
7
- data.tar.gz: f6911fdab5cffa4038412815b4b8a1f5ccba48d6bd0b645900aa65b79138322c00945b6740c0f5f165bcb3169b2c54582ad0c5735b19d07ac68081e60eff2f23
6
+ metadata.gz: 8a10d8b6ec39c6ab136c87e6e940aa25dd5e22b6afcb93edaf3e4ff844f3460d1136aa70a4f659cab119a63bf39d1f5cbdf0048c76df69c424ef2e2df94808f7
7
+ data.tar.gz: 84c8c21cd15963b576b0206b90ebc70f6606416e03219b6beec601ef868100f8be6e6d3bb09f272552bc640bb55e28b2f740653a579c44cceaf869196b1b5275
data/.rubocop.yml CHANGED
@@ -16,7 +16,7 @@ Metrics/ClassLength:
16
16
  Metrics/CyclomaticComplexity:
17
17
  Max: 157
18
18
  Metrics/MethodLength:
19
- Max: 663
19
+ Max: 666
20
20
  Metrics/ModuleLength:
21
21
  Max: 1000
22
22
  Metrics/PerceivedComplexity:
data/Gemfile CHANGED
@@ -82,7 +82,7 @@ gem 'rmagick', '6.1.4'
82
82
  gem 'rqrcode', '3.1.0'
83
83
  gem 'rspec', '3.13.1'
84
84
  gem 'rtesseract', '3.1.4'
85
- gem 'rubocop', '1.80.0'
85
+ gem 'rubocop', '1.80.1'
86
86
  gem 'rubocop-rake', '0.7.1'
87
87
  gem 'rubocop-rspec', '3.6.0'
88
88
  gem 'ruby-audio', '1.6.1'
data/README.md CHANGED
@@ -37,7 +37,7 @@ $ cd /opt/pwn
37
37
  $ ./install.sh
38
38
  $ ./install.sh ruby-gem
39
39
  $ pwn
40
- pwn[v0.5.387]:001 >>> PWN.help
40
+ pwn[v0.5.388]:001 >>> PWN.help
41
41
  ```
42
42
 
43
43
  [![Installing the pwn Security Automation Framework](https://raw.githubusercontent.com/0dayInc/pwn/master/documentation/pwn_install.png)](https://youtu.be/G7iLUY4FzsI)
@@ -52,7 +52,7 @@ $ rvm use ruby-3.4.4@pwn
52
52
  $ gem uninstall --all --executables pwn
53
53
  $ gem install --verbose pwn
54
54
  $ pwn
55
- pwn[v0.5.387]:001 >>> PWN.help
55
+ pwn[v0.5.388]:001 >>> PWN.help
56
56
  ```
57
57
 
58
58
  If you're using a multi-user install of RVM do:
@@ -62,7 +62,7 @@ $ rvm use ruby-3.4.4@pwn
62
62
  $ rvmsudo gem uninstall --all --executables pwn
63
63
  $ rvmsudo gem install --verbose pwn
64
64
  $ pwn
65
- pwn[v0.5.387]:001 >>> PWN.help
65
+ pwn[v0.5.388]:001 >>> PWN.help
66
66
  ```
67
67
 
68
68
  PWN periodically upgrades to the latest version of Ruby which is reflected in `/opt/pwn/.ruby-version`. The easiest way to upgrade to the latest version of Ruby from a previous PWN installation is to run the following script:
@@ -56,11 +56,7 @@ module PWN
56
56
  target_file = opts[:target_file].to_s
57
57
  target_file.gsub!(%r{^#{repo_root}/}, '')
58
58
 
59
- if File.directory?(repo_root) && File.file?("#{repo_root}/#{target_file}")
60
- `git --git-dir="#{Shellwords.escape(repo_root)}/.git" log -L #{from_line},#{to_line}:"#{Shellwords.escape(target_file)}" 2> /dev/null | grep Author | head -n 1`.to_s.scrub
61
- else
62
- -1
63
- end
59
+ `git --git-dir="#{Shellwords.escape(repo_root)}/.git" log -L #{from_line},#{to_line}:"#{Shellwords.escape(target_file)}" 2> /dev/null | grep Author | head -n 1`.to_s.scrub if File.directory?(repo_root) && File.file?("#{repo_root}/#{target_file}")
64
60
  rescue StandardError => e
65
61
  raise e
66
62
  end
@@ -120,7 +116,7 @@ module PWN
120
116
  )
121
117
  end
122
118
 
123
- author
119
+ author ||= 'N/A'
124
120
  rescue StandardError => e
125
121
  raise e
126
122
  end
@@ -1,8 +1,10 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'barby'
4
- require 'rqrcode'
4
+ require 'base64'
5
+ require 'fileutils'
5
6
  require 'chunky_png'
7
+ require 'rqrcode'
6
8
 
7
9
  module PWN
8
10
  module Plugins
@@ -12,7 +14,9 @@ module PWN
12
14
  # response = PWN::Plugins::ScannableCodes.generate(
13
15
  # data: 'required - data to encode',
14
16
  # type: 'optional - :barcode || :qrcode (defaults to :qrcode)',
17
+ # size: 'optional - size of the image when type is :qrcode (defaults to 200)',
15
18
  # path: 'optional - path to save image (defaults to "./#{data}.png")'
19
+ # return_type: 'optional - :base64 || :file (defaults to :file)'
16
20
  # )
17
21
 
18
22
  public_class_method def self.generate(opts = {})
@@ -22,22 +26,34 @@ module PWN
22
26
  type = opts[:type]
23
27
  type ||= :qrcode
24
28
 
29
+ size = opts[:size]
30
+ raise 'ERROR: size is only applicable when type is :qrcode.' if size && type != :qrcode
31
+
25
32
  path = opts[:path]
26
33
  path ||= "./#{data}.png"
27
34
 
35
+ return_type = opts[:return_type] ||= :file
36
+
28
37
  case type
29
38
  when :barcode
30
39
  barcode = Barby::Code128B.new(data)
31
40
  barcode.to_png.save(path)
32
41
  when :qrcode
42
+ size ||= 200
33
43
  qrcode = RQRCode::QRCode.new(data)
34
44
  png = qrcode.as_png
35
- png.resize(200, 200).save(path)
45
+ png.resize(size, size).save(path)
36
46
  else
37
47
  raise 'ERROR: type must be :barcode or :qrcode.'
38
48
  end
39
49
 
40
- puts "Saved #{type} to #{path}"
50
+ data = "Saved #{type} to #{path}"
51
+ if return_type == :base64
52
+ data = Base64.strict_encode64(File.binread(path))
53
+ FileUtils.rm_f(path)
54
+ end
55
+
56
+ data
41
57
  rescue Interrupt
42
58
  puts "\nGoodbye."
43
59
  rescue StandardError => e
@@ -59,6 +75,7 @@ module PWN
59
75
  #{self}.generate(
60
76
  data: 'required - data to encode',
61
77
  type: 'optional - :barcode || :qrcode (defaults to :qrcode)',
78
+ size: 'optional - size of the image when type is :qrcode (defaults to 200)',
62
79
  path: 'optional - path to save image (defaults to \"./\#{data}.png\")'
63
80
  )
64
81
 
@@ -207,22 +207,15 @@ module PWN
207
207
 
208
208
  <script src="https://cdn.datatables.net/v/dt/jszip-3.10.1/dt-2.3.3/b-3.2.4/b-colvis-3.2.4/b-html5-3.2.4/b-print-3.2.4/fc-5.0.4/fh-4.0.3/kt-2.12.1/r-3.0.6/rg-1.5.2/rr-1.5.0/sc-2.4.3/sb-1.8.3/sp-2.3.5/sl-3.1.0/datatables.min.js" integrity="sha384-jvnxkXTB++rTO/pbg6w5nj0jm5HiSGtTcBW5vnoLGRfmSxw3eyqNA0bJ+m6Skjw/" crossorigin="anonymous"></script>
209
209
 
210
- <script src="https://cdn.sheetjs.com/xlsx-0.20.2/package/dist/xlsx.full.min.js"></script>
211
-
212
- <!--
213
- <script type="text/javascript" src="//code.jquery.com/jquery-3.6.0.min.js"></script>
214
-
215
- <link rel="stylesheet" type="text/css" href="//cdn.datatables.net/v/dt/dt-1.11.4/b-2.2.2/b-colvis-2.2.2/b-html5-2.2.2/b-print-2.2.2/cr-1.5.5/fc-4.0.1/fh-3.2.1/kt-2.6.4/r-2.2.9/rg-1.1.4/rr-1.2.8/sc-2.0.5/sp-1.4.0/sl-1.3.4/datatables.min.css"/>
216
-
217
- <script type="text/javascript" src="//cdn.datatables.net/v/dt/dt-1.11.4/b-2.2.2/b-colvis-2.2.2/b-html5-2.2.2/b-print-2.2.2/cr-1.5.5/fc-4.0.1/fh-3.2.1/kt-2.6.4/r-2.2.9/rg-1.1.4/rr-1.2.8/sc-2.0.5/sp-1.4.0/sl-1.3.4/datatables.min.js"></script>
218
- -->
210
+ <script src="https://unpkg.com/exceljs@4.4.0/dist/exceljs.min.js"></script>
219
211
  </head>
220
212
 
221
213
  <body id="pwn_body">
222
214
 
223
215
  <h1 style="display:inline">
224
- <a href="https://github.com/0dayinc/pwn/tree/master">~ pwn sast</a>
225
- </h1><br /><br />
216
+ <img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAIEAAACCCAQAAADLPWN1AAAAAXNSR0IB2cksfwAAAARnQU1BAACxjwv8YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAAJiS0dEAIKpO8E+AAAACXBIWXMAAAsTAAALEwEAmpwYAAADTElEQVR42u2dyY7jMBBDqxrz/7+sOTRycCKJpOwBBsjzrWO3F4Ks3XKPUV++/dTXb3+qqjr8p1/i9HLPa2uxZ0z+6s011HXPngMWAAEQvGzBXK+fW6b+uUJ7ebTWuL7+yXPAAiB4E8IdurV5XObs1rLQEZ37HLAACKZCcLcrIe8QXFF7wAKEAAT/sS2oSWbnuqUOz55dFxYAwQNCyKi1iwdbuEudOq0j0A6jUlgABLYQ+saJVP1vHB1X0XFnzwELgAAIXrbgLMLS3YS2LMdZoWO2b8AChPB0mjRLQ9okX9tSWcuiTUepos2dbGmoIYSLEDRxXYur+0Pne3bRYZv3OXtCWAAEQFBGyUSVPa52ZCydZ5lO1tXz7nwl7xYWAMGbD/ocumvTEenUpc0oci2sLM4zHndyNCwAgjchtJlyKOK6SUt8s5GkdAxLmoQQgOCeU8wyOzevHNFv6fkomSAEu2Qyo4xKk3QXOROWS/fZddOBf1gABDI67JC4KkrLxmt3tQv3v1qKAxYAARBcbUE6OZzZhzKjtCzeO7MSRXSIEM7SJOWiRljOUCR1644loz7teBECQrikSSUJqbtESg6usLKY0+9E9fIasAAIgKA2M8juaNXM3eiO8RN5IywAgn8aHaoE5XTZjJNoUzvo7FqUTBCCIYQsQXKjSHdk485c+lnNkjQJIQDBzha4M4ZnTjGr+9fyumddbjrLCGGTJqWlEHeecOaclHx091rf3/o3OssIwagXeHTzaazjzKySoGoSPZUPLAACIHiiZDJu6F5Flm6mmHavVXZLdIgQ7OjQXZVGL+2kSe+ObHREc7ejDQuA4G0VCzcNcY+bRXPKgj9RhchqErAACICgNivjP1fDc2dJynSe2vWt+xyz54AFQBAu7ZS2vLJFNmbnc1t86RvRsAAITI+gBXG2LLyb6gzhiTqscTQsQAhAIG3BmcPyoj3nfCOKIl3b4rp1WAAEt76Vso4En3gXWb39nA7yUzJBCKEQUnvuRXO741Qi41r8sxEQWAAEQHDPFqy/cjduaPzsrbX1ne3WY4QFQLARwtMvQWWLx6VncqPX9W+wAAge/FbK2p5nn6PU4x6uRNzCOiwAAiCozdwhLAACIPiq7S/uVkwm4fz8nQAAAABJRU5ErkJggg==" type="image/png" style="iheight:100px;width:100px;"/>
217
+ <a href="https://github.com/0dayInc/pwn/blob/master/bin/pwn_sast" target="_blank">~ pwn sast</a>
218
+ </h1>
226
219
  <h2 id="report_name"></h2><br />
227
220
 
228
221
  <div class="dt-buttons" id="button_group">
@@ -614,6 +607,8 @@ module PWN
614
607
  test_case: row.security_references.sast_module.split('::')[2],
615
608
  nist_800_53_security_control: row.security_references.nist_800_53_uri,
616
609
  cwe: row.security_references.cwe_uri,
610
+ nist_section: row.security_references.section,
611
+ cwe_id: row.security_references.cwe_id,
617
612
  path: row.filename.entry,
618
613
  line_no: line.line_no,
619
614
  contents: line.contents,
@@ -627,63 +622,70 @@ module PWN
627
622
  var title = '~ pwn sast >>> ' + report_name + ' (Exported on ' + exportDate + ')';
628
623
 
629
624
  if (type === 'xlsx') {
630
- // Add title row
631
- var titleRow = [{ v: title, t: 's', s: { font: { sz: 14, bold: true }, alignment: { horizontal: 'center' } } }];
632
- var ws = XLSX.utils.json_to_sheet(flatData, {skipHeader: true});
633
- XLSX.utils.sheet_add_aoa(ws, [titleRow], {origin: 'A1'});
634
- XLSX.utils.sheet_add_json(ws, flatData, {origin: 'A2', skipHeader: false});
635
-
636
- // Merge title cell across columns
637
- if (!ws['!merges']) ws['!merges'] = [];
638
- ws['!merges'].push({s: {r:0, c:0}, e: {r:0, c:8}}); // A1 to I1
639
-
640
- // Set column widths by dividing desired column inches by 0.135
641
- // column inches observed with Exce
642
- // e.g 2.83 inches / 0.0135 ~ 209px
643
- ws['!cols'] = [
644
- {wpx: 209},
645
- {wpx: 130},
646
- {wpx: 580},
647
- {wpx: 256},
648
- {wpx: 110},
649
- {wpx: 40},
650
- {wpx: 370},
651
- {wpx: 370},
652
- {wpx: 185}
653
- ];
654
-
655
- // Style header row (row 2, since title at 1, header at 2, data from 3)
656
- var headerStyle = {
657
- font: { bold: true, color: { rgb: "000000" } },
658
- fill: { fgColor: { rgb: "999999" } },
659
- alignment: { horizontal: 'center', wrapText: true }
660
- };
661
- for (var col = 0; col < 9; col++) {
662
- var cellRef = XLSX.utils.encode_cell({r:1, c:col}); // Row 2 (0-based)
663
- if (ws[cellRef]) ws[cellRef].s = headerStyle;
664
- }
625
+ const workbook = new ExcelJS.Workbook();
626
+ const worksheet = workbook.addWorksheet('PWN SAST Results');
627
+
628
+ // Add title row and merge
629
+ worksheet.mergeCells('A1:I1');
630
+ const titleCell = worksheet.getCell('A1');
631
+ titleCell.value = title;
632
+ titleCell.font = { size: 14, bold: true };
633
+ titleCell.alignment = { horizontal: 'center' };
634
+
635
+ // Add header row
636
+ worksheet.addRow(['Timestamp', 'Test Case', 'NIST 800-53', 'CWE', 'Path', 'Line#', 'Content', 'AI Analysis', 'Author']);
637
+ const headerRow = worksheet.getRow(2);
638
+ headerRow.eachCell((cell) => {
639
+ cell.font = { bold: true, color: { argb: 'FF000000' } };
640
+ cell.fill = { type: 'pattern', pattern: 'solid', fgColor: { argb: 'FF999999' } };
641
+ cell.alignment = { horizontal: 'center', wrapText: true };
642
+ });
665
643
 
666
- // Alternate row colors for data rows (starting from row 3)
667
- var grayFill = { fgColor: { rgb: "DEDEDE" } };
668
- var whiteFill = { fgColor: { rgb: "FFFFFF" } };
669
- for (var rowNum = 3; rowNum < flatData.length + 2; rowNum++) { // Data rows 2-based from 3
670
- var fill = (rowNum % 2 === 0) ? whiteFill : grayFill;
671
- for (var col = 0; col < 9; col++) {
672
- var cellRef = XLSX.utils.encode_cell({r: rowNum, c: col});
673
- if (ws[cellRef]) {
674
- if (!ws[cellRef].s) ws[cellRef].s = {};
675
- ws[cellRef].s.fill = fill;
676
- ws[cellRef].s.alignment = { wrapText: true, vertical: 'top' };
677
- }
678
- }
679
- }
644
+ // Add data rows with alternating fills and hyperlinks
645
+ flatData.forEach((item, index) => {
646
+ const row = worksheet.addRow([
647
+ item.timestamp,
648
+ item.test_case,
649
+ { text: item.nist_section, hyperlink: item.nist_800_53_security_control },
650
+ { text: item.cwe_id, hyperlink: item.cwe },
651
+ item.path,
652
+ item.line_no,
653
+ item.contents,
654
+ item.ai_analysis,
655
+ item.author
656
+ ]);
657
+
658
+ const fill = (index % 2 === 0)
659
+ ? { type: 'pattern', pattern: 'solid', fgColor: { argb: 'FFDEDEDE' } }
660
+ : { type: 'pattern', pattern: 'solid', fgColor: { argb: 'FFFFFFFF' } };
661
+
662
+ row.eachCell((cell) => {
663
+ cell.fill = fill;
664
+ cell.alignment = { wrapText: true, vertical: 'top', horizontal: 'left' };
665
+ });
666
+ });
680
667
 
681
- // Freeze header
682
- ws['!freeze'] = { xSplit: 0, ySplit: 2 };
668
+ // Set column widths (converted from pixels to character units approx.)
669
+ const pixelWidthsInches = [1.0, 2.0, 4.5, 0.5, 2.5, 0.75, 3.5, 3.5, 2];
670
+ worksheet.columns = pixelWidthsInches.map(inches => {
671
+ let width;
672
+ width = inches / 0.077
673
+ return { width: width };
674
+ });
683
675
 
684
- var wb = XLSX.utils.book_new();
685
- XLSX.utils.book_append_sheet(wb, ws, 'PWN SAST Results');
686
- XLSX.writeFile(wb, report_name + '.xlsx');
676
+ // Freeze header
677
+ worksheet.views = [{ state: 'frozen', ySplit: 2 }];
678
+
679
+ // Generate and download the file
680
+ workbook.xlsx.writeBuffer().then(buffer => {
681
+ const blob = new Blob([buffer], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' });
682
+ const url = URL.createObjectURL(blob);
683
+ const a = document.createElement('a');
684
+ a.href = url;
685
+ a.download = report_name + '.xlsx';
686
+ a.click();
687
+ URL.revokeObjectURL(url);
688
+ });
687
689
  } else if (type === 'pdf') {
688
690
  var docDefinition = {
689
691
  pageOrientation: 'landscape',
@@ -716,8 +718,8 @@ module PWN
716
718
  ...flatData.map(r => [
717
719
  r.timestamp,
718
720
  r.test_case,
719
- r.nist_800_53_security_control,
720
- r.cwe,
721
+ { text: r.nist_section, link: r.nist_800_53_security_control, style: {decoration: 'underline'} },
722
+ { text: r.cwe_id, link: r.cwe, style: {decoration: 'underline'} },
721
723
  r.path,
722
724
  r.line_no,
723
725
  r.contents,
@@ -761,7 +763,6 @@ module PWN
761
763
  }
762
764
  });
763
765
  }
764
-
765
766
  // Detect window size changes and recalculate/update scrollY
766
767
  $(window).resize(function() {
767
768
  var newWindowHeight = $(window).height();
data/lib/pwn/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module PWN
4
- VERSION = '0.5.387'
4
+ VERSION = '0.5.388'
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pwn
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.387
4
+ version: 0.5.388
5
5
  platform: ruby
6
6
  authors:
7
7
  - 0day Inc.
@@ -939,14 +939,14 @@ dependencies:
939
939
  requirements:
940
940
  - - '='
941
941
  - !ruby/object:Gem::Version
942
- version: 1.80.0
942
+ version: 1.80.1
943
943
  type: :runtime
944
944
  prerelease: false
945
945
  version_requirements: !ruby/object:Gem::Requirement
946
946
  requirements:
947
947
  - - '='
948
948
  - !ruby/object:Gem::Version
949
- version: 1.80.0
949
+ version: 1.80.1
950
950
  - !ruby/object:Gem::Dependency
951
951
  name: rubocop-rake
952
952
  requirement: !ruby/object:Gem::Requirement