Jinja2 SSTI - Filter Bypass help needed

So, I am in a CTF where I need to exploit a server vulnerable to jinja2 SSTI.

The challenges are:

  • Full attack, including {{ and }} needs to be 45 characters or less
  • The system rejects any strings which contain ", (,),[ and ] (possibly more, that’s all I’ve confirmed so far).
  • I can use ' and { but when I replace () with {} it generates a HTTP 500 error.

I have got most of the way, but now need to try and get an arbitrary file read (ideally using os.popen) but I’ve hit a block.

Can anyone suggest ways I could bypass the restrictions on () (and URL encoding, Hex Encoding etc hasn’t worked).

self.__dict__ has returned a lot of data but, so far, I’ve failed at making it useful. I’ve tried a few tutorials but they all require () to work.

Has anyone got any suggestions?

Some good news, it also blocks \ and .

Urgh.

And it blocks +. This is killing me :sweat_smile:

/facepalm

Unfortunately no - at least not in any way I can get it to accept. It looks like there is a validation check first which is pretty aggressive on decoding stuff.

:stuck_out_tongue: helps to fully read before trying to post. Done so much sqli the past couple weeks lol everything is sql

Its ok @PrivacyMonk3y - I really appreciate the help!

I’ve spend hours on this step this evening.

I think I’ve gone word blind. I don’t want to stop because it took me ages to get to this point and I don’t have a way to leap back here when I spin it up again :smile:

â– â– â– â– â–  that sucks been there :slight_smile:

Gl hopefully something breaks soon :smiley:

Have you tried using alternative parentheses? Like e.g. the UTF-8 full-width characters? Maybe the filter is somewhere in front and Jinja gracefully converts them back, for you.

os.system(‘id’)
aka. os.system%uff08'id'%uff09

@HomeSen said:

Have you tried using alternative parentheses? Like e.g. the UTF-8 full-width characters? Maybe the filter is somewhere in front and Jinja gracefully converts them back, for you.

os.system(‘id’)
aka. os.system%uff08'id'%uff09

I hadn’t - trying now.

@HomeSen said:

Have you tried using alternative parentheses? Like e.g. the UTF-8 full-width characters? Maybe the filter is somewhere in front and Jinja gracefully converts them back, for you.

os.system(‘id’)
aka. os.system%uff08'id'%uff09

I owe you at least a small beer!

It progressed slightly - getting server errors now but that could be down to all the ■■■■ I’ve been throwing at it.

So far it looks like this bypassed at least part of the content filtering.

EDITED TO ADD
Might have been a bit too optimistic. It just generates HTTP500s even with a clean boot, I think its breaking the content filter rather than bypass. Also it s a lot of characters when I only have 45 to play with.

But I am genuinely indebted to @HomeSen for the nudge here.

Too bad.
Just checked how Chrome would URL-encode those. Maybe try %EF%BC%88 and %EF%BC%89 for the opening and closing parentheses.

Sadly that one also triggers the content filter as it decodes it quickly.

I’d never thought of using that before though, so I am going to add those to my notebooks! Thanks!

Might be a silly suggestion, but can you use Jinja2’s |safe filter to disable the automatic escaping?

@svenkali said:

Might be a silly suggestion, but can you use Jinja2’s |safe filter to disable the automatic escaping?

Sadly this isn’t working either. As far as I can establish, the content filtering is happening before the code is sent to Jinja2.

Bump - I am still stuck :smile: :cry:

Type your comment> @TazWake said:

Bump - I am still stuck :smile: :cry:

Can you send me challenge URL ? It’s seem fun, I want to give it a try :blush:

@jkana101 said:

Can you send me challenge URL ? It’s seem fun, I want to give it a try :blush:

It isn’t a publicly accessible challenge, sorry. Its provided by a commercial enterprise to a client who given me access.

So, I am still stuck, but I’ve made some progress.

I can write to the HTTP referrer string and I can call request.environ.HTTP_REFERER in the SSTI, but it still remains static.

So for example: {{os.popen.request.environ.HTTP_REFERER}} doesn’t work but {{request.environ.HTTP_REFERER}} does actually print whatever I put in the referer field.

Oh my god… Taz asking for help?

So for example: {{os.popen.request.environ.HTTP_REFERER}} doesn’t work but {{request.environ.HTTP_REFERER}} does actually print whatever I put in the referer field.

So clearly the OS module is not wholly imported, just os.popen.request. Maybe something useful in there? Not 100% sure though without being able to look at it.

Then again that has absolutely nothing to do with the HTTP_REFERER string unless you are down a rabbit hole, it does seem like a perfect XSS opportunity only question is how to trigger it…