mirror of
https://github.com/elicpeter/nyx.git
synced 2026-06-21 20:18:06 +02:00
refactor(dynamic): enhance Ruby harness with framework-specific route replay logic (Sinatra, Rails, Hanami), extend Gemfile staging, and update tests/fixtures
This commit is contained in:
parent
41c7b73575
commit
aaf49acefb
20 changed files with 773 additions and 218 deletions
|
|
@ -1,8 +1,5 @@
|
|||
source 'https://rubygems.org'
|
||||
|
||||
# Phase 15 fixture — Hanami Action shape. The adapter only inspects
|
||||
# the class superclass / include list; the harness never actually
|
||||
# boots `Hanami::Application`, so the gem is informational for
|
||||
# cargo-side fixture pickup.
|
||||
gem 'hanami'
|
||||
# Hanami action fixture. The harness invokes the action with a Rack env.
|
||||
gem 'hanami-controller'
|
||||
gem 'rack'
|
||||
|
|
|
|||
|
|
@ -1,13 +1,19 @@
|
|||
# Phase 15 — Hanami Action.call, benign.
|
||||
# Validates payload before running the fixed echo.
|
||||
# Ruby Hanami Action.call, benign.
|
||||
# Validates the real request parameter before running a fixed echo.
|
||||
|
||||
# nyx-shape: hanami
|
||||
# nyx-route: GET /run
|
||||
require 'hanami/action'
|
||||
require 'rack/request'
|
||||
|
||||
class RunAction < Hanami::Action
|
||||
def call(req)
|
||||
payload = req && req.is_a?(Hash) ? (req['nyx.payload'] || '') : (ENV['NYX_PAYLOAD'] || '')
|
||||
payload = if req.is_a?(Hash)
|
||||
Rack::Request.new(req).params['payload'].to_s
|
||||
elsif req.respond_to?(:params)
|
||||
req.params['payload'].to_s
|
||||
else
|
||||
ENV['NYX_PAYLOAD'].to_s
|
||||
end
|
||||
unless payload =~ /\A[A-Za-z0-9]{1,32}\z/
|
||||
STDOUT.print("invalid\n")
|
||||
return "invalid"
|
||||
|
|
|
|||
|
|
@ -1,15 +1,21 @@
|
|||
# Phase 15 — Hanami Action.call, vulnerable.
|
||||
# Class includes Hanami::Action and exposes a `call` method that pipes
|
||||
# the request body into /bin/sh.
|
||||
# Ruby Hanami Action.call, vulnerable.
|
||||
# The class imports Hanami::Action and reads the Rack request routed by
|
||||
# the harness.
|
||||
|
||||
# nyx-shape: hanami
|
||||
# nyx-route: GET /run
|
||||
require 'hanami/action'
|
||||
require 'rack/request'
|
||||
|
||||
class RunAction < Hanami::Action
|
||||
def call(req)
|
||||
STDOUT.print("__NYX_SINK_HIT__\n")
|
||||
payload = req && req.is_a?(Hash) ? (req['nyx.payload'] || '') : (ENV['NYX_PAYLOAD'] || '')
|
||||
payload = if req.is_a?(Hash)
|
||||
Rack::Request.new(req).params['payload'].to_s
|
||||
elsif req.respond_to?(:params)
|
||||
req.params['payload'].to_s
|
||||
else
|
||||
ENV['NYX_PAYLOAD'].to_s
|
||||
end
|
||||
out = `echo hello #{payload}`
|
||||
STDOUT.print(out)
|
||||
out
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
source 'https://rubygems.org'
|
||||
|
||||
# Phase 15 fixture — Rack middleware shape. The harness constructs
|
||||
# a Rack-shaped env hash and dispatches; the rack gem is not required
|
||||
# at runtime because the env-hash invocation pattern is standalone.
|
||||
# Rack middleware fixture. The harness builds the env through
|
||||
# Rack::MockRequest before dispatching the middleware.
|
||||
gem 'rack'
|
||||
|
|
|
|||
|
|
@ -1,7 +1,5 @@
|
|||
source 'https://rubygems.org'
|
||||
|
||||
# Phase 15 fixture — Rails action shape. The harness instantiates
|
||||
# the controller via .new and calls the action through reflection;
|
||||
# the rails gem is not actually required at runtime. The Gemfile is
|
||||
# informational so cargo-side fixture pickup sees a non-empty manifest.
|
||||
gem 'rails'
|
||||
# ActionController fixture. The harness calls the controller's Rack
|
||||
# endpoint with Rack::MockRequest.
|
||||
gem 'actionpack'
|
||||
|
|
|
|||
|
|
@ -1,24 +1,21 @@
|
|||
# Phase 15 — Rails-style controller action, benign.
|
||||
# Ruby ActionController action, benign.
|
||||
|
||||
class ApplicationController
|
||||
def initialize; end
|
||||
require 'action_controller'
|
||||
|
||||
class ApplicationController < ActionController::Base
|
||||
self.view_paths = []
|
||||
end
|
||||
|
||||
class UsersController < ApplicationController
|
||||
def initialize
|
||||
super
|
||||
@__nyx_payload = nil
|
||||
@__nyx_request = nil
|
||||
end
|
||||
|
||||
def index
|
||||
payload = @__nyx_payload || ENV['NYX_PAYLOAD'] || ''
|
||||
payload = params[:payload].to_s
|
||||
unless payload =~ /\A[A-Za-z0-9]{1,32}\z/
|
||||
STDOUT.print("invalid\n")
|
||||
return "invalid"
|
||||
render plain: "invalid"
|
||||
return
|
||||
end
|
||||
out = `echo hello`
|
||||
STDOUT.print(out)
|
||||
out
|
||||
render plain: out
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1,23 +1,18 @@
|
|||
# Phase 15 — Rails-style controller action, vulnerable.
|
||||
# Controller inherits the conventional ApplicationController name so
|
||||
# RubyShape::detect picks RailsAction.
|
||||
# Ruby ActionController action, vulnerable.
|
||||
# The harness drives UsersController.action(:index) through Rack.
|
||||
|
||||
class ApplicationController
|
||||
def initialize; end
|
||||
require 'action_controller'
|
||||
|
||||
class ApplicationController < ActionController::Base
|
||||
self.view_paths = []
|
||||
end
|
||||
|
||||
class UsersController < ApplicationController
|
||||
def initialize
|
||||
super
|
||||
@__nyx_payload = nil
|
||||
@__nyx_request = nil
|
||||
end
|
||||
|
||||
def index
|
||||
STDOUT.print("__NYX_SINK_HIT__\n")
|
||||
payload = @__nyx_payload || ENV['NYX_PAYLOAD'] || ''
|
||||
payload = params[:payload].to_s
|
||||
out = `echo hello #{payload}`
|
||||
STDOUT.print(out)
|
||||
out
|
||||
render plain: out
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
source 'https://rubygems.org'
|
||||
|
||||
# Phase 15 fixture — Sinatra route shape. The harness emits its own
|
||||
# route registry shim so the real sinatra gem is not required at
|
||||
# runtime; the Gemfile is informational for cargo-side fixture pickup.
|
||||
# Sinatra route fixture. The harness replays a Rack request through the
|
||||
# real Sinatra app class.
|
||||
gem 'sinatra'
|
||||
|
|
|
|||
|
|
@ -1,13 +1,20 @@
|
|||
# Phase 15 — Sinatra route, benign.
|
||||
# Validates payload then runs a fixed echo.
|
||||
# Ruby Sinatra route, benign.
|
||||
# Validates the real path-capture parameter before running a fixed echo.
|
||||
|
||||
# nyx-shape: sinatra
|
||||
get '/run' do |payload|
|
||||
unless payload =~ /\A[A-Za-z0-9]{1,32}\z/
|
||||
STDOUT.print("invalid\n")
|
||||
next "invalid"
|
||||
require 'sinatra/base'
|
||||
|
||||
class NyxSinatraApp < Sinatra::Base
|
||||
set :environment, :test
|
||||
disable :run
|
||||
|
||||
get '/run/:payload' do |payload|
|
||||
unless payload =~ /\A[A-Za-z0-9]{1,32}\z/
|
||||
STDOUT.print("invalid\n")
|
||||
"invalid"
|
||||
else
|
||||
out = `echo hello`
|
||||
STDOUT.print(out)
|
||||
out
|
||||
end
|
||||
end
|
||||
out = `echo hello`
|
||||
STDOUT.print(out)
|
||||
out
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1,11 +1,16 @@
|
|||
# Phase 15 — Sinatra route, vulnerable.
|
||||
# Reads payload (passed by harness via block argument) and pipes through /bin/sh.
|
||||
# Entry: route block Cap: CODE_EXEC
|
||||
# Ruby Sinatra route, vulnerable.
|
||||
# Reads a real path-capture parameter from Sinatra and pipes it through /bin/sh.
|
||||
|
||||
# nyx-shape: sinatra
|
||||
get '/run' do |payload|
|
||||
STDOUT.print("__NYX_SINK_HIT__\n")
|
||||
out = `echo hello #{payload}`
|
||||
STDOUT.print(out)
|
||||
out
|
||||
require 'sinatra/base'
|
||||
|
||||
class NyxSinatraApp < Sinatra::Base
|
||||
set :environment, :test
|
||||
disable :run
|
||||
|
||||
get '/run/:payload' do |payload|
|
||||
STDOUT.print("__NYX_SINK_HIT__\n")
|
||||
out = `echo hello #{payload}`
|
||||
STDOUT.print(out)
|
||||
out
|
||||
end
|
||||
end
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue