pwn 0.5.317 → 0.5.318

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: 867fb28f8e587319ad4cdaa05757178c1cb4c89dcb6d02904b795f1afc5bf6bd
4
- data.tar.gz: c3c9c9bd85f6654a3ac22ce2771165d696914cbaf3b55936bedafda60fa61742
3
+ metadata.gz: f686b3b286fba8e530a257dbd5e51e8c47d7103c25d39a9306e6621addd50905
4
+ data.tar.gz: dc9004429f6545cbc9c11e95c134afbe1f67b23482336382c6fcbdb829095273
5
5
  SHA512:
6
- metadata.gz: 9bbf94f9caf372277d1637967f8ad5d0d9f83ddd306b05f1e631c8d3276054abbcfda50d2637e6fb89676bc9215a9fe37e40fe415333ee9d46ed14adc293131e
7
- data.tar.gz: 056e03f80f7a641093f10dc405a18dfbd44f4dc4fce653d9097885f5802122fa74dda3c3477a1bfdeee47051844c296445dcd1d33d564f2afab0e61ee1eebea6
6
+ metadata.gz: ecfe213e36866e3faaa86feec1d7ad31ddfe687c8f69a3c3ad5ec99f79ddcd01d349e336a24cbe3d70bf8d6fa01a5b20168cab0f7a8a9f3aaa5ff7baa8aaa303
7
+ data.tar.gz: 22c4c983e03da55dd2f4ef550b21a59196784ed1d2f8d9c45bc9107e091cbdb7176ca4fb479bc1bf58ea5f131d21c5f7f6afb98f0283b0a44af537921de67843
data/Gemfile CHANGED
@@ -41,7 +41,7 @@ gem 'htmlentities', '4.3.4'
41
41
  gem 'ipaddress', '0.8.3'
42
42
  gem 'jenkins_api_client2', '1.9.0'
43
43
  gem 'js-beautify', '0.1.8'
44
- gem 'json', '2.12.2'
44
+ gem 'json', '2.13.0'
45
45
  gem 'jsonpath', '1.1.5'
46
46
  gem 'jwt', '3.1.2'
47
47
  gem 'libusb', '0.7.2'
@@ -64,7 +64,7 @@ gem 'open3', '0.2.1'
64
64
  # Relies on cargo, which is not available in OpenBSD via pkg_add atm.
65
65
  # gem 'openapi3_parser', '0.10.1'
66
66
  gem 'os', '1.1.4'
67
- gem 'ostruct', '0.6.2'
67
+ gem 'ostruct', '0.6.3'
68
68
  gem 'packetfu', '2.0.0'
69
69
  gem 'packetgen', '4.1.0'
70
70
  gem 'pdf-reader', '2.14.1'
@@ -93,7 +93,7 @@ gem 'selenium-devtools', '0.138.0'
93
93
  # gem 'serialport', '1.3.2'
94
94
  # gem 'sinatra', '4.0.0'
95
95
  gem 'slack-ruby-client', '2.6.0'
96
- gem 'socksify', '1.7.1'
96
+ gem 'socksify', '1.8.0'
97
97
  gem 'spreadsheet', '1.3.4'
98
98
  gem 'sqlite3', '2.7.2'
99
99
  gem 'thin', '2.0.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.317]:001 >>> PWN.help
40
+ pwn[v0.5.318]: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.317]:001 >>> PWN.help
55
+ pwn[v0.5.318]: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.317]:001 >>> PWN.help
65
+ pwn[v0.5.318]: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:
@@ -488,11 +488,14 @@ module PWN
488
488
  raise e
489
489
  end
490
490
 
491
- # Supported Method Parameters::
491
+ # Supported Method Parameters:
492
492
  # console_resp = PWN::Plugins::TransparentBrowser.view_dom_mutations(
493
- # browser_obj: browser_obj1,
493
+ # browser_obj: 'required - browser_obj returned from #open method',
494
494
  # index: 'optional - index of tab to switch to (defaults to active tab)',
495
- # target: 'optional - target JavaScript node to observe (defaults to document.body)'
495
+ # target: 'optional - target JavaScript node to observe (defaults to document.body)',
496
+ # observe_clobbering: 'optional - boolean to enable DOM Clobbering detection (defaults to true)',
497
+ # observe_redirects: 'optional - boolean to enable Insecure Redirect detection (defaults to true)',
498
+ # observe_resources: 'optional - boolean to enable resource load monitoring (defaults to true)'
496
499
  # )
497
500
 
498
501
  public_class_method def self.view_dom_mutations(opts = {})
@@ -503,6 +506,9 @@ module PWN
503
506
  jmp_tab(browser_obj: browser_obj, index: index) if index
504
507
 
505
508
  target = opts[:target] ||= 'undefined'
509
+ observe_clobbering = opts.fetch(:observe_clobbering, true)
510
+ observe_redirects = opts.fetch(:observe_redirects, true)
511
+ observe_resources = opts.fetch(:observe_resources, true)
506
512
 
507
513
  jmp_devtools_panel(
508
514
  browser_obj: browser_obj,
@@ -510,138 +516,147 @@ module PWN
510
516
  )
511
517
 
512
518
  js = <<~JAVASCRIPT
513
- // Select the target node to observe (replace 'target-id' with your element's ID or use document.body)
519
+ // Select the target node to observe (default to document.body)
514
520
  const targetNode = document.getElementById(#{target}) || document.body;
515
521
 
516
522
  // Configuration for MutationObserver
517
523
  const config = {
518
- attributes: true, // Observe attribute changes
519
- childList: true, // Observe additions/removals of child nodes
520
- subtree: true, // Observe descendants
521
- characterData: true, // Observe text content changes
524
+ attributes: true,
525
+ childList: true,
526
+ subtree: true,
527
+ characterData: true,
528
+ attributeOldValue: true
522
529
  };
523
530
 
531
+ // Exhaustive list of elements that can execute scripts or load resources
532
+ const xssElements = [
533
+ 'SCRIPT', 'IFRAME', 'FRAME', 'OBJECT', 'EMBED', 'APPLET', 'SVG', 'IMG', 'VIDEO', 'AUDIO', 'LINK', 'META', 'BASE',
534
+ 'INPUT', 'SOURCE', 'TRACK', 'FORM', 'BUTTON', 'AREA', 'NOSCRIPT', 'STYLE', 'HTML', 'BODY'
535
+ ];
536
+
537
+ // Exhaustive list of attributes that can contain URLs, scripts, or event handlers
538
+ const xssAttributes = [
539
+ 'src', 'href', 'action', 'srcdoc', 'data', 'codebase', 'style', 'manifest', 'poster', 'background', 'lowsrc',
540
+ 'formaction', 'cite', 'ping', 'icon', 'longdesc', 'usemap', 'content', 'value', 'pattern',
541
+ 'onload', 'onerror', 'onclick', 'onmouseover', 'onmouseout', 'onfocus', 'onblur', 'onchange', 'onsubmit', 'onreset',
542
+ 'onselect', 'ondblclick', 'onkeydown', 'onkeypress', 'onkeyup', 'onmousedown', 'onmousemove', 'onmouseup', 'onwheel',
543
+ 'oncontextmenu', 'ondrag', 'ondragend', 'ondragenter', 'ondragleave', 'ondragover', 'ondragstart', 'ondrop', 'onscroll',
544
+ 'ontouchstart', 'ontouchmove', 'ontouchend', 'ontouchcancel', 'onanimationstart', 'onanimationend', 'onanimationiteration',
545
+ 'ontransitionend'
546
+ ];
547
+
548
+ // Attributes that can cause navigation (for insecure redirects)
549
+ const redirectAttributes = ['href', 'action', 'src', 'formaction', 'content'];
550
+
551
+ // Attributes that load resources (for data exfiltration)
552
+ const resourceAttributes = ['src', 'href', 'poster', 'data', 'background', 'lowsrc', 'cite', 'ping', 'icon', 'longdesc'];
553
+
554
+ // Global properties that could be clobbered
555
+ const globalProperties = [
556
+ 'document', 'window', 'location', 'navigator', 'history', 'screen', 'console', 'alert', 'confirm', 'prompt',
557
+ 'fetch', 'XMLHttpRequest', 'WebSocket', 'localStorage', 'sessionStorage'
558
+ ];
559
+
524
560
  // Callback function to handle mutations
525
561
  const callback = (mutationList, observer) => {
526
- console.group('DOM Mutation Detected');
527
- mutationList.forEach((mutation, index) => {
528
- console.log(`Mutation ${index + 1}:`, mutation.type);
529
-
562
+ mutationList.forEach((mutation) => {
530
563
  if (mutation.type === 'childList') {
531
564
  if (mutation.addedNodes.length) {
532
565
  mutation.addedNodes.forEach((node) => {
533
566
  if (node.nodeType === Node.ELEMENT_NODE) {
534
- let logObj = {
535
- tagName: node.tagName,
536
- id: node.id || 'N/A',
537
- classList: node.className || 'N/A',
538
- outerHTML: node.outerHTML,
539
- };
540
- if (['SCRIPT', 'IFRAME', 'FRAME', 'OBJECT', 'EMBED', 'APPLET'].includes(node.tagName)) {
541
- console.warn('Potential XSS sink: Added', node.tagName, logObj);
542
- } else {
543
- console.log('Added Element:', logObj);
567
+ const tagName = node.tagName.toUpperCase();
568
+ // Check for XSS sinks
569
+ if (xssElements.includes(tagName)) {
570
+ console.warn('Potential DOM-XSS sink: Added element', {
571
+ tagName: tagName,
572
+ id: node.id || 'N/A',
573
+ classList: node.className || 'N/A',
574
+ outerHTML: node.outerHTML
575
+ });
576
+ }
577
+ // Check for DOM Clobbering
578
+ if (#{observe_clobbering} && (node.id || node.name) && globalProperties.includes(node.id || node.name)) {
579
+ console.warn('Potential DOM Clobbering: Added element with id/name', {
580
+ id: node.id || 'N/A',
581
+ name: node.name || 'N/A',
582
+ tagName: tagName,
583
+ outerHTML: node.outerHTML
584
+ });
544
585
  }
545
- } else if (node.nodeType === Node.TEXT_NODE) {
546
- console.log('Added Text Node:', {
547
- textContent: node.textContent,
548
- parentTag: node.parentElement?.tagName || 'N/A',
549
- });
550
- }
551
- });
552
- }
553
- if (mutation.removedNodes.length) {
554
- mutation.removedNodes.forEach((node) => {
555
- if (node.nodeType === Node.ELEMENT_NODE) {
556
- console.log('Removed Element:', {
557
- tagName: node.tagName,
558
- id: node.id || 'N/A',
559
- classList: node.className || 'N/A',
560
- outerHTML: node.outerHTML,
561
- });
562
- } else if (node.nodeType === Node.TEXT_NODE) {
563
- console.log('Removed Text Node:', {
564
- textContent: node.textContent,
565
- parentTag: node.parentElement?.tagName || 'N/A',
566
- });
567
586
  }
568
587
  });
569
588
  }
570
589
  } else if (mutation.type === 'attributes') {
571
- let logObj = {
572
- element: mutation.target.tagName,
573
- id: mutation.target.id || 'N/A',
574
- attribute: mutation.attributeName,
575
- oldValue: mutation.oldValue,
576
- newValue: mutation.target.getAttribute(mutation.attributeName),
577
- outerHTML: mutation.target.outerHTML,
578
- };
579
- if (
580
- (mutation.attributeName === 'src' && ['SCRIPT', 'IFRAME', 'FRAME', 'OBJECT', 'EMBED'].includes(mutation.target.tagName)) ||
581
- (mutation.attributeName === 'href' && ['A', 'AREA', 'LINK'].includes(mutation.target.tagName)) ||
582
- (mutation.attributeName === 'action' && mutation.target.tagName === 'FORM') ||
583
- mutation.attributeName.startsWith('on') ||
584
- (mutation.attributeName === 'srcdoc' && mutation.target.tagName === 'IFRAME') ||
585
- (mutation.attributeName === 'data' && mutation.target.tagName === 'OBJECT') ||
586
- (mutation.attributeName === 'codebase' && mutation.target.tagName === 'OBJECT')
587
- ) {
588
- console.warn('Potential XSS sink: Attribute change', logObj);
589
- } else {
590
- console.log('Attribute changed:', logObj);
590
+ const attrName = mutation.attributeName.toLowerCase();
591
+ const tagName = mutation.target.tagName.toUpperCase();
592
+ // Check for XSS sinks
593
+ if (xssAttributes.includes(attrName)) {
594
+ console.warn('Potential DOM-XSS sink: Attribute change', {
595
+ element: tagName,
596
+ id: mutation.target.id || 'N/A',
597
+ attribute: attrName,
598
+ oldValue: mutation.oldValue,
599
+ newValue: mutation.target.getAttribute(attrName),
600
+ outerHTML: mutation.target.outerHTML
601
+ });
591
602
  }
592
- } else if (mutation.type === 'characterData') {
593
- if (mutation.target.parentElement && mutation.target.parentElement.tagName === 'SCRIPT') {
594
- console.warn('Potential XSS sink: Script content changed', {
595
- scriptId: mutation.target.parentElement.id || 'N/A',
603
+ // Check for insecure redirects
604
+ if (#{observe_redirects} && redirectAttributes.includes(attrName) &&
605
+ (tagName === 'A' || tagName === 'FORM' || tagName === 'IFRAME' || tagName === 'BUTTON' || tagName === 'INPUT' ||
606
+ (tagName === 'META' && mutation.target.getAttribute('http-equiv') === 'refresh'))) {
607
+ console.warn('Potential Insecure Redirect: Attribute change', {
608
+ element: tagName,
609
+ id: mutation.target.id || 'N/A',
610
+ attribute: attrName,
596
611
  oldValue: mutation.oldValue,
597
- newValue: mutation.target.textContent,
612
+ newValue: mutation.target.getAttribute(attrName),
613
+ outerHTML: mutation.target.outerHTML
598
614
  });
599
- } else {
600
- console.log('Text Content Changed:', {
601
- element: mutation.target.parentElement?.tagName || 'N/A',
602
- id: mutation.target.parentElement?.id || 'N/A',
615
+ }
616
+ // Check for resource loads (data exfiltration)
617
+ if (#{observe_resources} && resourceAttributes.includes(attrName)) {
618
+ console.warn('Potential Resource Load (Data Exfiltration): Attribute change', {
619
+ element: tagName,
620
+ id: mutation.target.id || 'N/A',
621
+ attribute: attrName,
603
622
  oldValue: mutation.oldValue,
604
- newValue: mutation.target.textContent,
605
- innerHTML: mutation.target.parentElement?.innerHTML || 'N/A',
623
+ newValue: mutation.target.getAttribute(attrName),
624
+ outerHTML: mutation.target.outerHTML
606
625
  });
607
626
  }
627
+ } else if (mutation.type === 'characterData') {
628
+ if (mutation.target.parentElement) {
629
+ const parentTag = mutation.target.parentElement.tagName.toUpperCase();
630
+ if (parentTag === 'SCRIPT') {
631
+ console.warn('Potential DOM-XSS sink: Script content changed', {
632
+ scriptId: mutation.target.parentElement.id || 'N/A',
633
+ oldValue: mutation.oldValue,
634
+ newValue: mutation.target.textContent
635
+ });
636
+ } else if (parentTag === 'STYLE') {
637
+ console.warn('Potential DOM-XSS sink: Style content changed', {
638
+ styleId: mutation.target.parentElement.id || 'N/A',
639
+ oldValue: mutation.oldValue,
640
+ newValue: mutation.target.textContent
641
+ });
642
+ }
643
+ }
608
644
  }
609
645
  });
610
- console.groupEnd();
611
646
  };
612
647
 
613
648
  // Create and start the MutationObserver
614
649
  const observer = new MutationObserver(callback);
615
650
  observer.observe(targetNode, config);
616
651
 
617
- // Optional: Add event listeners to capture user interactions
618
- const logUserInteraction = (event) => {
619
- console.group('User Interaction Detected');
620
- console.log('Event Type:', event.type);
621
- console.log('Target:', {
622
- tagName: event.target.tagName,
623
- id: event.target.id || 'N/A',
624
- classList: event.target.className || 'N/A',
625
- value: 'value' in event.target ? event.target.value : 'N/A',
626
- innerHTML: event.target.innerHTML || 'N/A',
627
- });
628
- console.groupEnd();
629
- };
630
-
631
- // Attach listeners for keyboard and click events
632
- document.addEventListener('input', logUserInteraction); // For form inputs, contenteditable
633
- document.addEventListener('click', logUserInteraction); // For clicks
634
-
635
- // Function to stop the observer (run in console when needed)
652
+ // Function to stop the observer
636
653
  window.hide_dom_mutations = () => {
637
654
  observer.disconnect();
638
- document.removeEventListener('input', logUserInteraction);
639
- document.removeEventListener('click', logUserInteraction);
640
- console.log('MutationObserver and event listeners stopped.');
655
+ console.log('MutationObserver stopped.');
641
656
  };
642
657
 
643
658
  // Log instructions to console
644
- console.log('MutationObserver started. To stop, run: hide_dom_mutations()');
659
+ console.log('MutationObserver started for DOM-based vulnerabilities. To stop, run: hide_dom_mutations()');
645
660
  JAVASCRIPT
646
661
 
647
662
  console(browser_obj: browser_obj, js: 'clear();')
@@ -142,6 +142,7 @@ module PWN
142
142
  var oldStart = 0;
143
143
  var table = $('#pwn_fuzz_net_app_proto').DataTable( {
144
144
  "paging": true,
145
+ "lengthMenu": [10, 25, 50, 100, 250, 500, 1000, 2500, 5000],
145
146
  "pagingType": "full_numbers",
146
147
  "fnDrawCallback": function ( oSettings ) {
147
148
  /* Need to redo the counters if filtered or sorted */
@@ -143,6 +143,7 @@ module PWN
143
143
  var oldStart = 0;
144
144
  var table = $('#pwn_phone_results').DataTable( {
145
145
  "paging": true,
146
+ "lengthMenu": [10, 25, 50, 100, 250, 500, 1000, 2500, 5000],
146
147
  "pagingType": "full_numbers",
147
148
  "fnDrawCallback": function ( oSettings ) {
148
149
  /* Need to redo the counters if filtered or sorted */
@@ -134,6 +134,7 @@ module PWN
134
134
  var oldStart = 0;
135
135
  var table = $('#pwn_scan_git_source_results').DataTable( {
136
136
  "paging": true,
137
+ "lengthMenu": [10, 25, 50, 100, 250, 500, 1000, 2500, 5000],
137
138
  "pagingType": "full_numbers",
138
139
  "fnDrawCallback": function ( oSettings ) {
139
140
  /* Need to redo the counters if filtered or sorted */
@@ -134,6 +134,7 @@ module PWN
134
134
  var oldStart = 0;
135
135
  var table = $('#pwn_www_uri_buster_results').DataTable( {
136
136
  "paging": true,
137
+ "lengthMenu": [10, 25, 50, 100, 250, 500, 1000, 2500, 5000],
137
138
  "pagingType": "full_numbers",
138
139
  "fnDrawCallback": function ( oSettings ) {
139
140
  /* Need to redo the counters if filtered or sorted */
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.317'
4
+ VERSION = '0.5.318'
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.317
4
+ version: 0.5.318
5
5
  platform: ruby
6
6
  authors:
7
7
  - 0day Inc.
@@ -407,14 +407,14 @@ dependencies:
407
407
  requirements:
408
408
  - - '='
409
409
  - !ruby/object:Gem::Version
410
- version: 2.12.2
410
+ version: 2.13.0
411
411
  type: :runtime
412
412
  prerelease: false
413
413
  version_requirements: !ruby/object:Gem::Requirement
414
414
  requirements:
415
415
  - - '='
416
416
  - !ruby/object:Gem::Version
417
- version: 2.12.2
417
+ version: 2.13.0
418
418
  - !ruby/object:Gem::Dependency
419
419
  name: jsonpath
420
420
  requirement: !ruby/object:Gem::Requirement
@@ -687,14 +687,14 @@ dependencies:
687
687
  requirements:
688
688
  - - '='
689
689
  - !ruby/object:Gem::Version
690
- version: 0.6.2
690
+ version: 0.6.3
691
691
  type: :runtime
692
692
  prerelease: false
693
693
  version_requirements: !ruby/object:Gem::Requirement
694
694
  requirements:
695
695
  - - '='
696
696
  - !ruby/object:Gem::Version
697
- version: 0.6.2
697
+ version: 0.6.3
698
698
  - !ruby/object:Gem::Dependency
699
699
  name: packetfu
700
700
  requirement: !ruby/object:Gem::Requirement
@@ -1065,14 +1065,14 @@ dependencies:
1065
1065
  requirements:
1066
1066
  - - '='
1067
1067
  - !ruby/object:Gem::Version
1068
- version: 1.7.1
1068
+ version: 1.8.0
1069
1069
  type: :runtime
1070
1070
  prerelease: false
1071
1071
  version_requirements: !ruby/object:Gem::Requirement
1072
1072
  requirements:
1073
1073
  - - '='
1074
1074
  - !ruby/object:Gem::Version
1075
- version: 1.7.1
1075
+ version: 1.8.0
1076
1076
  - !ruby/object:Gem::Dependency
1077
1077
  name: spreadsheet
1078
1078
  requirement: !ruby/object:Gem::Requirement