{"id":18265868,"url":"https://github.com/mpgn/slanger-rce","last_synced_at":"2026-03-09T17:45:21.075Z","repository":{"id":76017864,"uuid":"176389708","full_name":"mpgn/Slanger-RCE","owner":"mpgn","description":"RCE in Slanger using deserialization of Ruby objects","archived":false,"fork":false,"pushed_at":"2019-03-19T00:41:55.000Z","size":7,"stargazers_count":11,"open_issues_count":0,"forks_count":2,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-08-11T04:09:51.393Z","etag":null,"topics":["rce","slanger"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/mpgn.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2019-03-19T00:12:35.000Z","updated_at":"2025-06-19T18:23:48.000Z","dependencies_parsed_at":null,"dependency_job_id":"5e090eeb-7d35-44fc-8f60-b412243bb119","html_url":"https://github.com/mpgn/Slanger-RCE","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/mpgn/Slanger-RCE","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mpgn%2FSlanger-RCE","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mpgn%2FSlanger-RCE/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mpgn%2FSlanger-RCE/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mpgn%2FSlanger-RCE/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mpgn","download_url":"https://codeload.github.com/mpgn/Slanger-RCE/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mpgn%2FSlanger-RCE/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30305301,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-09T17:35:44.120Z","status":"ssl_error","status_checked_at":"2026-03-09T17:35:43.707Z","response_time":61,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["rce","slanger"],"created_at":"2024-11-05T11:20:13.487Z","updated_at":"2026-03-09T17:45:21.038Z","avatar_url":"https://github.com/mpgn.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Slanger RCE\n\nRCE in Slanger \u003c 0.6.1 (a Ruby implementation of Pusher) using deserialization of Ruby objects ! \n\n\u003e While researching a web application last February, I learned about Slanger, an open source server implementation of Pusher. In this post I describe the discovery of a critical RCE vulnerability in Slanger 0.6.0, and the efforts that followed to responsibly disclose the vulnerability.\n\n![capture d'écran_1](https://user-images.githubusercontent.com/5891788/54571628-f64a9e80-49e3-11e9-8cdd-32229fdfd0c8.png)\nfound by [Pieter Hiele](https://twitter.com/honoki)\n\n**Technical Analysis**:\n- https://www.honoki.net/2019/03/rce-in-slanger-0-6-0/\n- https://www.honoki.net/2019/03/rce-in-slanger-0-6-0/2/\n\n**Patch**:\n- https://github.com/stevegraham/slanger/commit/5267b455caeb2e055cccf0d2b6a22727c111f5c3\n\n---\n\n### Proof Of Concept\n\nThe Slanger application uses the ressource `Oj.load` to read the json sent by the user through the websocket channel. The json is not loaded with the secure option `Oj.strict_load()` as explained by the [Oj library](https://github.com/ohler55/oj/blob/master/pages/Security.md).\n\n![image](https://user-images.githubusercontent.com/5891788/54572233-b802ae80-49e6-11e9-978f-ec01c515e93e.png)\n\nhttps://github.com/stevegraham/slanger/blob/7fb5f439b45d8e128883b3e9e9d59dd2e8deb284/lib/slanger/handler.rb#L28\n\nTherefore, the application is vulnerable to a remote code execution using unsecure ruby object deserialization.\n\n1. To build the serialized object is use the [Rails 3.2.10 Remote Code Execution](https://github.com/charliesome/charlie.bz/blob/master/posts/rails-3.2.10-remote-code-execution.md) ressource \n2. Then send the payload though the websocket channel\n3. That it.\n\n### Exploit\n\n```\npython3 slanger-exploit.py\n```\n\n![image](https://user-images.githubusercontent.com/5891788/54571529-6573c300-49e3-11e9-97da-ffcad66604a1.png)\n\n\n---\n\n```diff\nFrom 5267b455caeb2e055cccf0d2b6a22727c111f5c3 Mon Sep 17 00:00:00 2001\nFrom: Pieter Hiele \u003cpieter@honoki.net\u003e\nDate: Wed, 27 Feb 2019 10:15:22 +0100\nSubject: [PATCH] bug fixes\n\n---\n lib/slanger/api/request_validation.rb | 4 ++--\n lib/slanger/connection.rb             | 2 +-\n lib/slanger/handler.rb                | 4 ++--\n lib/slanger/presence_channel.rb       | 2 +-\n lib/slanger/redis.rb                  | 2 +-\n 5 files changed, 7 insertions(+), 7 deletions(-)\n\ndiff --git a/lib/slanger/api/request_validation.rb b/lib/slanger/api/request_validation.rb\nindex 1f2318a..56646ee 100644\n--- a/lib/slanger/api/request_validation.rb\n+++ b/lib/slanger/api/request_validation.rb\n@@ -12,7 +12,7 @@ def initialize(*args)\n       end\n \n       def data\n-        @data ||= Oj.load(body[\"data\"] || params[\"data\"])\n+        @data ||= Oj.strict_load(body[\"data\"] || params[\"data\"])\n       end\n \n       def body\n@@ -87,7 +87,7 @@ def parse_body!\n       end\n \n       def assert_valid_json!(string)\n-        Oj.load(string)\n+        Oj.strict_load(string)\n       rescue Oj::ParserError\n         raise Slanger::InvalidRequest.new(\"Invalid request body: #{raw_body}\")\n       end\ndiff --git a/lib/slanger/connection.rb b/lib/slanger/connection.rb\nindex 3a98d58..463b1e7 100644\n--- a/lib/slanger/connection.rb\n+++ b/lib/slanger/connection.rb\n@@ -9,7 +9,7 @@ def initialize socket, socket_id=nil\n     end\n \n     def send_message m\n-      msg = Oj.load m\n+      msg = Oj.strict_load m\n       s = msg.delete 'socket_id'\n       socket.send Oj.dump(msg, mode: :compat) unless s == socket_id\n     end\ndiff --git a/lib/slanger/handler.rb b/lib/slanger/handler.rb\nindex f294c34..2cd2d5a 100644\n--- a/lib/slanger/handler.rb\n+++ b/lib/slanger/handler.rb\n@@ -25,9 +25,9 @@ def initialize(socket, handshake)\n     # Dispatches message handling to method with same name as\n     # the event name\n     def onmessage(msg)\n-      msg = Oj.load(msg)\n+      msg = Oj.strict_load(msg)\n \n-      msg['data'] = Oj.load(msg['data']) if msg['data'].is_a? String\n+      msg['data'] = Oj.strict_load(msg['data']) if msg['data'].is_a? String\n \n       event = msg['event'].gsub(/\\Apusher:/, 'pusher_')\n \ndiff --git a/lib/slanger/presence_channel.rb b/lib/slanger/presence_channel.rb\nindex d996fa6..3600b92 100644\n--- a/lib/slanger/presence_channel.rb\n+++ b/lib/slanger/presence_channel.rb\n@@ -32,7 +32,7 @@ def initialize(attrs)\n     end\n \n     def subscribe(msg, callback, \u0026blk)\n-      channel_data = Oj.load msg['data']['channel_data']\n+      channel_data = Oj.strict_load msg['data']['channel_data']\n       public_subscription_id = SecureRandom.uuid\n \n       # Send event about the new subscription to the Redis slanger:connection_notification Channel.\ndiff --git a/lib/slanger/redis.rb b/lib/slanger/redis.rb\nindex b62345c..f79ac0e 100644\n--- a/lib/slanger/redis.rb\n+++ b/lib/slanger/redis.rb\n@@ -25,7 +25,7 @@ def publisher\n     def subscriber\n       @subscriber ||= new_connection.pubsub.tap do |c|\n         c.on(:message) do |channel, message|\n-          message = Oj.load(message)\n+          message = Oj.strict_load(message)\n           c = Channel.from message['channel']\n           c.dispatch message, channel\n         end\n```\n\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmpgn%2Fslanger-rce","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmpgn%2Fslanger-rce","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmpgn%2Fslanger-rce/lists"}